Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dcd44c42ed | |||
| 6c563d7619 | |||
| 97f22c500b | |||
| 9cbeccfa15 | |||
| 86722a31d0 | |||
| 589b33a673 | |||
| dae0348710 | |||
| a7f6155627 | |||
| 7f5bc4a3e5 | |||
| ec32278f1a | |||
| c02c5aa915 | |||
| f267f2ad5b | |||
| 03bc09c1aa | |||
| c4df418081 | |||
| a9c79d5fb3 | |||
| 529100a947 | |||
| 062f6d5aa0 | |||
| deb0a95985 | |||
| ca70f80900 | |||
| 23e3ec20b6 | |||
| 32d97ed194 | |||
| 167a4e9820 | |||
| aef0b50663 | |||
| 5b5e6c8f44 | |||
| 5dc96384bd | |||
| affdea3ec2 | |||
| 1436d86c7e | |||
| b7c9eaa981 | |||
| db99ab526a | |||
| 133c34dee2 | |||
| 775cf258ba | |||
| ed34807a58 | |||
| 31acbbdcdc | |||
| ef7708e324 | |||
| de353c3334 | |||
| b47a317c48 | |||
| 2b163c91a9 | |||
| d380a078a2 | |||
| 556afacd13 | |||
| 598d622d0b | |||
| 3a1d0d65bf | |||
| cc7b8a9b69 | |||
| 6c6f09ac5a | |||
| 1fe309f363 | |||
| 3417fdb1a4 | |||
| a6394672e7 | |||
| 1fc97e4b7a | |||
| fe853aa1c5 | |||
| 9c3f805eab | |||
| 410eda6d6c | |||
| 719c24fb38 | |||
| a7cb182bbe | |||
| dbb970d7b5 | |||
| 887a27cf3e | |||
| eed8ffb9d4 | |||
| dd412e33ad | |||
| 94e5c33785 | |||
| 6f3f109723 | |||
| d8082de1db | |||
| 2daccb57b5 | |||
| e64bddf9d5 | |||
| 9f6f15f64d | |||
| ad28c9a482 | |||
| 8404fb5738 | |||
| 75c057e83e | |||
| d44e2df55e | |||
| aebc15d4e4 | |||
| c835140fe8 | |||
| f35031db7e | |||
| ca81f48c1c | |||
| 30dcc6801a | |||
| 46ba4ac182 | |||
| 2c6a57ab39 | |||
| 79a3aedf5c | |||
| 38fc1fe805 | |||
| 5daf5e82f4 | |||
| dacfb8a740 | |||
| fec9f1f10c | |||
| 293fb7597c | |||
| 0cf6a6ef2d | |||
| 4d44e093d5 | |||
| 2c75649a3c | |||
| 1ca599a550 | |||
| dc7cd5b3c8 | |||
| 67196fb7b6 | |||
| 9b8e81a063 | |||
| 91b7f0c1d0 | |||
| 32bcf49b97 | |||
| 6a9efe3a41 | |||
| 945d5ebf75 | |||
| d38b1d27d0 | |||
| 6ad618b494 | |||
| a63f7b4e62 | |||
| 6e57a62e2a | |||
| 100f16000e | |||
| 78c7facf6c | |||
| b210491db5 | |||
| ca944f3f38 | |||
| 2eca6dc707 | |||
| 90835256ff | |||
| 80351cd594 | |||
| 7cdfa68d77 | |||
| 3f74a6d33f | |||
| 27d8896937 | |||
| 7b92d06eee | |||
| cbfb433e55 | |||
| c3503dbd3c | |||
| 7e151ddb83 | |||
| 2204435d29 | |||
| c85d6ec1d0 | |||
| 9b9655df90 | |||
| 7cc6b7147f | |||
| 84e4a66b08 | |||
| ea9427026d | |||
| c1af389eea | |||
| 0ee0df3471 | |||
| 0af70d23dd | |||
| d741685836 | |||
| f59b6e393e | |||
| 6632589027 | |||
| a009d5d080 | |||
| 29bbf77e7c | |||
| 5a4bb2c5d3 | |||
| e28878c5ee | |||
| a80a765ee5 | |||
| a96079c14c | |||
| d99b3b1203 | |||
| ba2b85c3ee | |||
| 320eb3f16a | |||
| 5dced2d173 | |||
| 09a18be5b9 | |||
| f6407805d3 | |||
| f24d50af44 | |||
| a13de19c81 | |||
| efb95864cd | |||
| 14da34de64 |
@@ -1 +0,0 @@
|
||||
ko_fi: inorichi
|
||||
@@ -1,34 +0,0 @@
|
||||
**PLEASE READ THIS**
|
||||
|
||||
I acknowledge that:
|
||||
|
||||
- I have updated:
|
||||
- To the latest version of the app (stable is v1.10.0)
|
||||
- All extensions
|
||||
- I have gone through the FAQ (https://tachiyomi.org/docs/faq/general) and troubleshooting guide (https://tachiyomi.org/docs/guides/troubleshooting/)
|
||||
- If this is an issue with an official extension, that I should be opening an issue in https://github.com/tachiyomiorg/extensions
|
||||
- I have searched the existing issues and this is new ticket **NOT** a duplicate or related to another open or closed issue
|
||||
- I will fill out the title and the information in this template
|
||||
|
||||
Note that the issue will be automatically closed if you do not fill out the title or requested information.
|
||||
|
||||
**DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT**
|
||||
|
||||
---
|
||||
|
||||
## Device information
|
||||
* Tachiyomi version: ?
|
||||
* Android version: ?
|
||||
* Device: ?
|
||||
|
||||
## Steps to reproduce
|
||||
1. First step
|
||||
2. Second step
|
||||
|
||||
## Issue/Request
|
||||
?
|
||||
|
||||
## Other details
|
||||
Additional details and attachments.
|
||||
|
||||
If you're experiencing crashes, share the crash logs from More → Settings → Advanced → Dump crash logs.
|
||||
@@ -1,11 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: ⚠️ Extension/source issue
|
||||
url: https://github.com/tachiyomiorg/extensions/issues/new/choose
|
||||
about: Issues and requests for official extensions and sources should be opened in the extensions repository instead
|
||||
- name: 📦 Tachiyomi extensions
|
||||
url: https://tachiyomi.org/extensions/
|
||||
about: List of all available extensions with download links
|
||||
- name: 🖥️ Tachiyomi website
|
||||
url: https://tachiyomi.org/
|
||||
- name: 🖥️ Mihon website
|
||||
url: https://mihon.app/
|
||||
about: Guides, troubleshooting, and answers to common questions
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: 🐞 Issue report
|
||||
description: Report an issue in Tachiyomi
|
||||
description: Report an issue in TachiyomiSY
|
||||
labels: [Bug]
|
||||
body:
|
||||
|
||||
@@ -48,12 +48,12 @@ body:
|
||||
You can paste the crash logs in plain text or upload it as an attachment.
|
||||
|
||||
- type: input
|
||||
id: tachiyomi-version
|
||||
id: tachiyomisy-version
|
||||
attributes:
|
||||
label: Tachiyomi version
|
||||
description: You can find your Tachiyomi version in **More → About**.
|
||||
label: TachiyomiSY version
|
||||
description: You can find your TachiyomiSY version in **More → About**.
|
||||
placeholder: |
|
||||
Example: "1.9.4"
|
||||
Example: "1.10.5"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -90,17 +90,13 @@ body:
|
||||
label: Acknowledgements
|
||||
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
|
||||
options:
|
||||
- label: This is a TachiyomiSY specific issue that does not happen in [Tachiyomi Preview](https://github.com/tachiyomiorg/tachiyomi/).
|
||||
required: true
|
||||
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
|
||||
- label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https:/mihon.app/docs/guides/troubleshooting/).
|
||||
required: true
|
||||
- label: I have gone through the [FAQ](https://tachiyomi.org/docs/faq/general) and [troubleshooting guide](https://tachiyomi.org/docs/guides/troubleshooting/).
|
||||
required: true
|
||||
- label: I have updated the app to version **[1.10.0](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
|
||||
- label: I have updated the app to version **[1.10.5](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
|
||||
required: true
|
||||
- label: I have updated all installed extensions.
|
||||
required: true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: ⭐ Feature request
|
||||
description: Suggest a feature to improve Tachiyomi
|
||||
description: Suggest a feature to improve TachiyomiSY
|
||||
labels: [Feature request]
|
||||
body:
|
||||
|
||||
@@ -7,7 +7,7 @@ body:
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Describe your suggested feature
|
||||
description: How can Tachiyomi be improved?
|
||||
description: How can TachiyomiSY be improved?
|
||||
placeholder: |
|
||||
Example:
|
||||
"It should work like this..."
|
||||
@@ -31,9 +31,7 @@ body:
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
|
||||
required: true
|
||||
- label: I have updated the app to version **[1.10.0](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
|
||||
- label: I have updated the app to version **[1.10.5](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
|
||||
required: true
|
||||
- label: I will fill out all of the requested information in this form.
|
||||
required: true
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 489 KiB After Width: | Height: | Size: 713 KiB |
@@ -32,10 +32,11 @@ jobs:
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
- name: Build app
|
||||
uses: gradle/gradle-command-action@v2
|
||||
with:
|
||||
arguments: assembleDevDebug
|
||||
run: ./gradlew assembleDevDebug
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -18,7 +18,11 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
uses: gradle/wrapper-validation-action@v2
|
||||
|
||||
- name: Setup Android SDK
|
||||
run: |
|
||||
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3"
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v4
|
||||
@@ -26,6 +30,9 @@ jobs:
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Set up gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
# SY <--
|
||||
- name: Write google-services.json
|
||||
uses: DamianReeves/write-file-action@v1.2
|
||||
@@ -36,9 +43,7 @@ jobs:
|
||||
# SY -->
|
||||
|
||||
- name: Build app and run unit tests
|
||||
uses: gradle/gradle-command-action@v2
|
||||
with:
|
||||
arguments: ktlintCheck assembleStandardRelease testStandardReleaseUnitTest --stacktrace
|
||||
run: ./gradlew assembleStandardRelease testStandardReleaseUnitTest --stacktrace
|
||||
|
||||
- name: Sign APK
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
@@ -90,6 +95,8 @@ jobs:
|
||||
| armeabi-v7a | ${{ env.APK_ARMEABI_V7A_SHA }} |
|
||||
| x86 | ${{ env.APK_X86_SHA }} |
|
||||
| x86_64 | ${{ env.APK_X86_64_SHA }} |
|
||||
|
||||
## If you are unsure which version to choose then go with TachiyomiSY.apk
|
||||
files: |
|
||||
TachiyomiSY.apk
|
||||
TachiyomiSY-arm64-v8a.apk
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: TAG - Bump version and push tag
|
||||
uses: anothrNick/github-tag-action@1.39.0
|
||||
uses: anothrNick/github-tag-action@1.67.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WITH_V: true
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Moderate issues
|
||||
uses: tachiyomiorg/issue-moderator-action@v2
|
||||
uses: tachiyomiorg/issue-moderator-action@v2.6.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
duplicate-label: Duplicate
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
"regex": ".*(?:fail(?:ed|ure|s)?|can\\s*(?:no|')?t|(?:not|un).*able|(?<!n[o']?t )blocked by|error) (?:to )?(?:get past|by ?pass|penetrate)?.*cloud ?fl?are.*",
|
||||
"ignoreCase": true,
|
||||
"labels": ["Cloudflare protected"],
|
||||
"message": "Refer to the **Solving Cloudflare issues** section at https://tachiyomi.org/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
|
||||
"message": "Refer to the **Solving Cloudflare issues** section at https://mihon.app/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
|
||||
}
|
||||
]
|
||||
auto-close-ignore-label: do-not-autoclose
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ representative at an online or offline event.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community moderators responsible for enforcement at
|
||||
the [Tachiyomi Discord server](https://discord.gg/tachiyomi).
|
||||
the [Mihon Discord server](https://discord.gg/mihon).
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community moderators are obligated to respect the privacy and security of the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| Preview Builds | Release Builds | Tachiyomi Support Server |
|
||||
|-------|----------|----------|
|
||||
| [](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [](https://github.com/jobobby04/tachiyomisy/releases/latest) | [](https://discord.gg/tachiyomi) |
|
||||
| [](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [](https://github.com/jobobby04/tachiyomisy/releases/latest) | [](https://discord.gg/mihon) |
|
||||
|
||||
|
||||
# TachiyomiSY
|
||||
@@ -75,7 +75,7 @@ Please make sure to read the full guidelines. Your issue may be closed without w
|
||||
<details><summary>Issues</summary>
|
||||
|
||||
1. **Before reporting a new issue, take a look at the [FAQ](https://tachiyomi.org/docs/faq/general), the [changelog](https://github.com/jobobby04/tachiyomisy/releases) and the already opened [issues](https://github.com/jobobby04/tachiyomisy/issues).**
|
||||
2. If you are unsure, ask here: [](https://discord.gg/tachiyomi)
|
||||
2. If you are unsure, ask here: [](https://discord.gg/mihon)
|
||||
|
||||
</details>
|
||||
|
||||
@@ -115,5 +115,5 @@ See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
|
||||
|
||||
## FAQ
|
||||
|
||||
[See our website.](https://tachiyomi.org/)
|
||||
You can also reach out to us on [Discord](https://discord.gg/tachiyomi).
|
||||
[See our website.](https://mihon.app/)
|
||||
You can also reach out to us on [Discord](https://discord.gg/mihon).
|
||||
+19
-14
@@ -26,8 +26,8 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "eu.kanade.tachiyomi.sy"
|
||||
|
||||
versionCode = 60
|
||||
versionName = "1.10.0"
|
||||
versionCode = 65
|
||||
versionName = "1.10.5"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
||||
@@ -140,18 +140,18 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":i18n"))
|
||||
implementation(projects.i18n)
|
||||
// SY -->
|
||||
implementation(project(":i18n-sy"))
|
||||
implementation(projects.i18nSy)
|
||||
// SY <--
|
||||
implementation(project(":core"))
|
||||
implementation(project(":core-metadata"))
|
||||
implementation(project(":source-api"))
|
||||
implementation(project(":source-local"))
|
||||
implementation(project(":data"))
|
||||
implementation(project(":domain"))
|
||||
implementation(project(":presentation-core"))
|
||||
implementation(project(":presentation-widget"))
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.coreMetadata)
|
||||
implementation(projects.sourceApi)
|
||||
implementation(projects.sourceLocal)
|
||||
implementation(projects.data)
|
||||
implementation(projects.domain)
|
||||
implementation(projects.presentationCore)
|
||||
implementation(projects.presentationWidget)
|
||||
|
||||
// Compose
|
||||
implementation(platform(compose.bom))
|
||||
@@ -167,7 +167,6 @@ dependencies {
|
||||
implementation(compose.ui.util)
|
||||
implementation(compose.accompanist.webview)
|
||||
implementation(compose.accompanist.systemuicontroller)
|
||||
lintChecks(compose.lintchecks)
|
||||
|
||||
implementation(androidx.paging.runtime)
|
||||
implementation(androidx.paging.compose)
|
||||
@@ -311,7 +310,7 @@ tasks {
|
||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
||||
"-opt-in=coil.annotation.ExperimentalCoilApi",
|
||||
"-opt-in=coil3.annotation.ExperimentalCoilApi",
|
||||
"-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi",
|
||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"-opt-in=kotlinx.coroutines.FlowPreview",
|
||||
@@ -331,6 +330,12 @@ tasks {
|
||||
project.layout.buildDirectory.dir("compose_metrics").get().asFile.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
// https://developer.android.com/jetpack/androidx/releases/compose-compiler#1.5.9
|
||||
kotlinOptions.freeCompilerArgs += listOf(
|
||||
"-P",
|
||||
"plugin:androidx.compose.compiler.plugins.kotlin:nonSkippingGroupOptimization=true",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="tachiyomi" />
|
||||
<data android:scheme="mihon" />
|
||||
|
||||
<data android:host="anilist-auth" />
|
||||
<data android:host="bangumi-auth" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.core.preference
|
||||
|
||||
import androidx.compose.ui.state.ToggleableState
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.core.common.preference.CheckboxState
|
||||
|
||||
fun <T> CheckboxState.TriState<T>.asToggleableState() = when (this) {
|
||||
is CheckboxState.TriState.Exclude -> ToggleableState.Indeterminate
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
|
||||
class PreferenceMutableState<T>(
|
||||
private val preference: Preference<T>,
|
||||
|
||||
@@ -4,8 +4,8 @@ import android.content.Context
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
class BasePreferences(
|
||||
|
||||
@@ -5,9 +5,9 @@ import eu.kanade.domain.base.BasePreferences.ExtensionInstaller
|
||||
import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller
|
||||
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.getEnum
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getEnum
|
||||
|
||||
class ExtensionInstallerPreference(
|
||||
private val context: Context,
|
||||
|
||||
@@ -3,8 +3,8 @@ package eu.kanade.domain.chapter.interactor
|
||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.chapter.interactor.GetMergedChaptersByMangaId
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.chapter.model.ChapterUpdate
|
||||
|
||||
@@ -171,7 +171,7 @@ class SyncChaptersWithSource(
|
||||
var updatedToAdd = newChapters.map { toAddItem ->
|
||||
var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--)
|
||||
|
||||
if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
|
||||
if (!chapter.isRecognizedNumber || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
|
||||
|
||||
chapter = chapter.copy(
|
||||
read = chapter.chapterNumber in deletedReadChapterNumbers,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.download.interactor
|
||||
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.extension.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.plusAssign
|
||||
import tachiyomi.core.common.preference.plusAssign
|
||||
|
||||
class CreateExtensionRepo(private val preferences: SourcePreferences) {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.extension.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.minusAssign
|
||||
import tachiyomi.core.common.preference.minusAssign
|
||||
|
||||
class DeleteExtensionRepo(private val preferences: SourcePreferences) {
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class GetExtensionSources(
|
||||
ExtensionSourceItem(
|
||||
source = source,
|
||||
enabled = source.isEnabled(),
|
||||
labelAsName = isMultiSource && isMultiLangSingleSource.not(),
|
||||
labelAsName = isMultiSource && !isMultiLangSingleSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ class GetExtensionsByType(
|
||||
extensionManager.availableExtensionsFlow,
|
||||
) { _activeLanguages, _installed, _untrusted, _available ->
|
||||
val (updates, installed) = _installed
|
||||
.filter { (showNsfwSources || it.isNsfw.not()) }
|
||||
.filter { (showNsfwSources || !it.isNsfw) }
|
||||
.sortedWith(
|
||||
compareBy<Extension.Installed> {
|
||||
it.isObsolete.not() /* SY --> */ && it.isRedundant.not() /* SY <-- */
|
||||
!it.isObsolete /* SY --> */ && !it.isRedundant /* SY <-- */
|
||||
}.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name },
|
||||
)
|
||||
.partition { it.hasUpdate }
|
||||
@@ -37,7 +37,7 @@ class GetExtensionsByType(
|
||||
.filter { extension ->
|
||||
_installed.none { it.pkgName == extension.pkgName } &&
|
||||
_untrusted.none { it.pkgName == extension.pkgName } &&
|
||||
(showNsfwSources || extension.isNsfw.not())
|
||||
(showNsfwSources || !extension.isNsfw)
|
||||
}
|
||||
.flatMap { ext ->
|
||||
if (ext.sources.isEmpty()) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package eu.kanade.domain.extension.interactor
|
||||
import android.content.pm.PackageInfo
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
class TrustExtension(
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.kanade.domain.manga.interactor
|
||||
|
||||
import tachiyomi.core.preference.plusAssign
|
||||
import tachiyomi.core.common.preference.plusAssign
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
|
||||
class CreateSortTag(
|
||||
|
||||
@@ -6,9 +6,9 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@@ -55,6 +55,7 @@ fun Manga.copyFrom(other: SManga): Manga {
|
||||
// SY -->
|
||||
val author = other.author ?: ogAuthor
|
||||
val artist = other.artist ?: ogArtist
|
||||
val thumbnailUrl = other.thumbnail_url ?: ogThumbnailUrl
|
||||
val description = other.description ?: ogDescription
|
||||
val genres = if (other.genre != null) {
|
||||
other.getGenres()
|
||||
@@ -62,15 +63,14 @@ fun Manga.copyFrom(other: SManga): Manga {
|
||||
ogGenre
|
||||
}
|
||||
// SY <--
|
||||
val thumbnailUrl = other.thumbnail_url ?: thumbnailUrl
|
||||
return this.copy(
|
||||
// SY -->
|
||||
ogAuthor = author,
|
||||
ogArtist = artist,
|
||||
ogThumbnailUrl = thumbnailUrl,
|
||||
ogDescription = description,
|
||||
ogGenre = genres,
|
||||
// SY <--
|
||||
thumbnailUrl = thumbnailUrl,
|
||||
// SY -->
|
||||
ogStatus = other.status.toLong(),
|
||||
// SY <--
|
||||
@@ -86,11 +86,11 @@ fun SManga.toDomainManga(sourceId: Long): Manga {
|
||||
ogTitle = title,
|
||||
ogArtist = artist,
|
||||
ogAuthor = author,
|
||||
ogThumbnailUrl = thumbnail_url,
|
||||
ogDescription = description,
|
||||
ogGenre = getGenres(),
|
||||
ogStatus = status.toLong(),
|
||||
// SY <--
|
||||
thumbnailUrl = thumbnail_url,
|
||||
updateStrategy = update_strategy,
|
||||
initialized = initialized,
|
||||
source = sourceId,
|
||||
@@ -104,7 +104,13 @@ fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean {
|
||||
/**
|
||||
* Creates a ComicInfo instance based on the manga and chapter metadata.
|
||||
*/
|
||||
fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories: List<String>?) = ComicInfo(
|
||||
fun getComicInfo(
|
||||
manga: Manga,
|
||||
chapter: Chapter,
|
||||
urls: List<String>,
|
||||
categories: List<String>?,
|
||||
sourceName: String,
|
||||
) = ComicInfo(
|
||||
title = ComicInfo.Title(chapter.name),
|
||||
series = ComicInfo.Series(manga.title),
|
||||
number = chapter.chapterNumber.takeIf { it >= 0 }?.let {
|
||||
@@ -114,7 +120,7 @@ fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories:
|
||||
ComicInfo.Number(it.toString())
|
||||
}
|
||||
},
|
||||
web = ComicInfo.Web(chapterUrl),
|
||||
web = ComicInfo.Web(urls.joinToString(" ")),
|
||||
summary = manga.description?.let { ComicInfo.Summary(it) },
|
||||
writer = manga.author?.let { ComicInfo.Writer(it) },
|
||||
penciller = manga.artist?.let { ComicInfo.Penciller(it) },
|
||||
@@ -124,6 +130,7 @@ fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories:
|
||||
ComicInfoPublishingStatus.toComicInfoValue(manga.status),
|
||||
),
|
||||
categories = categories?.let { ComicInfo.CategoriesTachiyomi(it.joinToString()) },
|
||||
source = ComicInfo.SourceMihon(sourceName),
|
||||
// SY -->
|
||||
padding = CbzCrypto.createComicInfoPadding()?.let { ComicInfo.PaddingTachiyomiSY(it) },
|
||||
// SY <--
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.plusAssign
|
||||
import tachiyomi.core.common.preference.plusAssign
|
||||
|
||||
class CreateSourceCategory(private val preferences: SourcePreferences) {
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.preference.minusAssign
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.minusAssign
|
||||
|
||||
class DeleteSourceCategory(private val preferences: SourcePreferences) {
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.source.interactor.GetSavedSearchById
|
||||
import tachiyomi.domain.source.interactor.GetSavedSearchBySourceId
|
||||
import tachiyomi.domain.source.model.EXHSavedSearch
|
||||
|
||||
@@ -3,7 +3,7 @@ package eu.kanade.domain.source.interactor
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import tachiyomi.core.util.lang.compareToWithCollator
|
||||
import tachiyomi.core.common.util.lang.compareToWithCollator
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.domain.source.repository.SourceRepository
|
||||
import tachiyomi.source.local.isLocal
|
||||
@@ -34,15 +34,15 @@ class GetSourcesWithFavoriteCount(
|
||||
when (sorting) {
|
||||
SetMigrateSorting.Mode.ALPHABETICAL -> {
|
||||
when {
|
||||
a.first.isStub && b.first.isStub.not() -> -1
|
||||
b.first.isStub && a.first.isStub.not() -> 1
|
||||
a.first.isStub && !b.first.isStub -> -1
|
||||
b.first.isStub && !a.first.isStub -> 1
|
||||
else -> a.first.name.lowercase().compareToWithCollator(b.first.name.lowercase())
|
||||
}
|
||||
}
|
||||
SetMigrateSorting.Mode.TOTAL -> {
|
||||
when {
|
||||
a.first.isStub && b.first.isStub.not() -> -1
|
||||
b.first.isStub && a.first.isStub.not() -> 1
|
||||
a.first.isStub && !b.first.isStub -> -1
|
||||
b.first.isStub && !a.first.isStub -> 1
|
||||
else -> a.second.compareTo(b.second)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
class RenameSourceCategory(
|
||||
private val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
class SetSourceCategories(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
class ToggleExcludeFromDataSaver(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
|
||||
class ToggleLanguage(
|
||||
val preferences: SourcePreferences,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
class ToggleSource(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.domain.source.interactor
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.domain.source.model.Source
|
||||
|
||||
class ToggleSourcePin(
|
||||
|
||||
@@ -2,9 +2,9 @@ package eu.kanade.domain.source.service
|
||||
|
||||
import eu.kanade.domain.source.interactor.SetMigrateSorting
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.getEnum
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getEnum
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
|
||||
class SourcePreferences(
|
||||
|
||||
@@ -8,9 +8,9 @@ import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.history.interactor.GetHistory
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
|
||||
@@ -30,9 +30,9 @@ class RefreshTracks(
|
||||
.map { (track, service) ->
|
||||
async {
|
||||
return@async try {
|
||||
val updatedTrack = service!!.refresh(track.toDbTrack())
|
||||
insertTrack.await(updatedTrack.toDomainTrack()!!)
|
||||
syncChapterProgressWithTrack.await(mangaId, track, service)
|
||||
val updatedTrack = service!!.refresh(track.toDbTrack()).toDomainTrack()!!
|
||||
insertTrack.await(updatedTrack)
|
||||
syncChapterProgressWithTrack.await(mangaId, updatedTrack, service)
|
||||
null
|
||||
} catch (e: Throwable) {
|
||||
service to e
|
||||
|
||||
@@ -4,7 +4,7 @@ import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.chapter.interactor.UpdateChapter
|
||||
import tachiyomi.domain.chapter.model.toChapterUpdate
|
||||
|
||||
@@ -11,8 +11,8 @@ import exh.md.utils.FollowStatus
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.lang.withNonCancellableContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import tachiyomi.domain.track.interactor.InsertTrack
|
||||
|
||||
@@ -23,7 +23,7 @@ class TrackChapter(
|
||||
private val delayedTrackingStore: DelayedTrackingStore,
|
||||
) {
|
||||
|
||||
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) {
|
||||
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double, setupJobOnFailure: Boolean = true) {
|
||||
withNonCancellableContext {
|
||||
val tracks = getTracks.await(mangaId)
|
||||
if (tracks.isEmpty()) return@withNonCancellableContext
|
||||
@@ -34,7 +34,7 @@ class TrackChapter(
|
||||
service == null ||
|
||||
!service.isLoggedIn ||
|
||||
chapterNumber <= track.lastChapterRead /* SY --> */ ||
|
||||
(service is MdList && track.status == FollowStatus.UNFOLLOWED.int.toLong())/* SY <-- */
|
||||
(service is MdList && track.status == FollowStatus.UNFOLLOWED.long)/* SY <-- */
|
||||
) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
@@ -50,7 +50,9 @@ class TrackChapter(
|
||||
delayedTrackingStore.remove(track.id)
|
||||
} catch (e: Exception) {
|
||||
delayedTrackingStore.add(track.id, chapterNumber)
|
||||
DelayedTrackingUpdateJob.setupTask(context)
|
||||
if (setupJobOnFailure) {
|
||||
DelayedTrackingUpdateJob.setupTask(context)
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,30 +19,28 @@ fun Track.toDbTrack(): DbTrack = DbTrack.create(trackerId).also {
|
||||
it.remote_id = remoteId
|
||||
it.library_id = libraryId
|
||||
it.title = title
|
||||
it.last_chapter_read = lastChapterRead.toFloat()
|
||||
it.total_chapters = totalChapters.toInt()
|
||||
it.status = status.toInt()
|
||||
it.score = score.toFloat()
|
||||
it.last_chapter_read = lastChapterRead
|
||||
it.total_chapters = totalChapters
|
||||
it.status = status
|
||||
it.score = score
|
||||
it.tracking_url = remoteUrl
|
||||
it.started_reading_date = startDate
|
||||
it.finished_reading_date = finishDate
|
||||
}
|
||||
|
||||
fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
|
||||
val trackId = id ?: if (idRequired.not()) -1 else return null
|
||||
val trackId = id ?: if (!idRequired) -1 else return null
|
||||
return Track(
|
||||
id = trackId,
|
||||
mangaId = manga_id,
|
||||
trackerId = tracker_id.toLong(),
|
||||
trackerId = tracker_id,
|
||||
remoteId = remote_id,
|
||||
libraryId = library_id,
|
||||
title = title,
|
||||
lastChapterRead = last_chapter_read.toDouble(),
|
||||
totalChapters = total_chapters.toLong(),
|
||||
status = status.toLong(),
|
||||
// Jank workaround due to precision issues while converting
|
||||
// See https://github.com/tachiyomiorg/tachiyomi/issues/10343
|
||||
score = score.toString().toDouble(),
|
||||
lastChapterRead = last_chapter_read,
|
||||
totalChapters = total_chapters,
|
||||
status = status,
|
||||
score = score,
|
||||
remoteUrl = tracking_url,
|
||||
startDate = started_reading_date,
|
||||
finishDate = finished_reading_date,
|
||||
|
||||
@@ -12,8 +12,8 @@ import eu.kanade.domain.track.interactor.TrackChapter
|
||||
import eu.kanade.domain.track.store.DelayedTrackingStore
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.track.interactor.GetTracks
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@@ -45,7 +45,7 @@ class DelayedTrackingUpdateJob(private val context: Context, workerParams: Worke
|
||||
logcat(LogPriority.DEBUG) {
|
||||
"Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}"
|
||||
}
|
||||
trackChapter.await(context, track.mangaId, track.lastChapterRead)
|
||||
trackChapter.await(context, track.mangaId, track.lastChapterRead, setupJobOnFailure = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package eu.kanade.domain.track.service
|
||||
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.anilist.Anilist
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
|
||||
class TrackPreferences(
|
||||
private val preferenceStore: PreferenceStore,
|
||||
@@ -19,9 +19,15 @@ class TrackPreferences(
|
||||
"",
|
||||
)
|
||||
|
||||
fun trackAuthExpired(tracker: Tracker) = preferenceStore.getBoolean(
|
||||
Preference.privateKey("pref_tracker_auth_expired_${tracker.id}"),
|
||||
false,
|
||||
)
|
||||
|
||||
fun setCredentials(tracker: Tracker, username: String, password: String) {
|
||||
trackUsername(tracker).set(username)
|
||||
trackPassword(tracker).set(password)
|
||||
trackAuthExpired(tracker).set(false)
|
||||
}
|
||||
|
||||
fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")
|
||||
|
||||
@@ -3,7 +3,7 @@ package eu.kanade.domain.track.store
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
|
||||
class DelayedTrackingStore(context: Context) {
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import eu.kanade.domain.ui.model.TabletUiMode
|
||||
import eu.kanade.domain.ui.model.ThemeMode
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.getEnum
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getEnum
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.util.Locale
|
||||
|
||||
class UiPreferences(
|
||||
@@ -38,11 +38,15 @@ class UiPreferences(
|
||||
|
||||
fun expandFilters() = preferenceStore.getBoolean("eh_expand_filters", false)
|
||||
|
||||
fun hideFeedTab() = preferenceStore.getBoolean("hide_latest_tab", false)
|
||||
|
||||
fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false)
|
||||
|
||||
fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", false)
|
||||
|
||||
fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", false)
|
||||
fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", true)
|
||||
|
||||
fun previewsRowCount() = preferenceStore.getInt("pref_previews_row_count", 4)
|
||||
|
||||
fun useNewSourceNavigation() = preferenceStore.getBoolean("use_new_source_navigation", true)
|
||||
|
||||
@@ -55,9 +59,9 @@ class UiPreferences(
|
||||
// SY <--
|
||||
|
||||
companion object {
|
||||
fun dateFormat(format: String): DateFormat = when (format) {
|
||||
"" -> DateFormat.getDateInstance(DateFormat.SHORT)
|
||||
else -> SimpleDateFormat(format, Locale.getDefault())
|
||||
fun dateFormat(format: String): DateTimeFormatter = when (format) {
|
||||
"" -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
|
||||
else -> DateTimeFormatter.ofPattern(format, Locale.getDefault())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import exh.source.isEhBasedSource
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
|
||||
@@ -53,6 +53,7 @@ import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
@@ -232,7 +233,31 @@ private fun DetailsHeader(
|
||||
end = MaterialTheme.padding.medium,
|
||||
top = MaterialTheme.padding.medium,
|
||||
bottom = MaterialTheme.padding.small,
|
||||
),
|
||||
)
|
||||
.clickable {
|
||||
val extDebugInfo = buildString {
|
||||
append(
|
||||
"""
|
||||
Extension name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
|
||||
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
||||
NSFW: ${extension.isNsfw}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
if (extension is Extension.Installed) {
|
||||
append("\n\n")
|
||||
append(
|
||||
"""
|
||||
Update available: ${extension.hasUpdate}
|
||||
Obsolete: ${extension.isObsolete}
|
||||
Shared: ${extension.isShared}
|
||||
Repository: ${extension.repoUrl}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
context.copyToClipboard("Extension Debug information", extDebugInfo)
|
||||
},
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
ExtensionIcon(
|
||||
|
||||
@@ -10,13 +10,11 @@ import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Close
|
||||
import androidx.compose.material.icons.outlined.ErrorOutline
|
||||
import androidx.compose.material.icons.outlined.GetApp
|
||||
import androidx.compose.material.icons.outlined.Public
|
||||
import androidx.compose.material.icons.outlined.Refresh
|
||||
@@ -40,14 +38,16 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.presentation.browse.components.BaseBrowseItem
|
||||
import eu.kanade.presentation.browse.components.ExtensionIcon
|
||||
import eu.kanade.presentation.components.WarningBanner
|
||||
import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText
|
||||
import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
|
||||
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
|
||||
import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||
@@ -55,6 +55,7 @@ import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
@@ -63,6 +64,7 @@ import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.EmptyScreenAction
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import tachiyomi.presentation.core.theme.header
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
@@ -84,6 +86,8 @@ fun ExtensionScreen(
|
||||
onClickUpdateAll: () -> Unit,
|
||||
onRefresh: () -> Unit,
|
||||
) {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
PullRefresh(
|
||||
refreshing = state.isRefreshing,
|
||||
onRefresh = onRefresh,
|
||||
@@ -94,16 +98,19 @@ fun ExtensionScreen(
|
||||
state.isEmpty -> {
|
||||
val msg = if (!searchQuery.isNullOrEmpty()) {
|
||||
MR.strings.no_results_found
|
||||
// SY -->
|
||||
} else if (!state.hasExtensionRepos) {
|
||||
SYMR.strings.no_repos_found
|
||||
// SY <--
|
||||
} else {
|
||||
MR.strings.empty_screen
|
||||
}
|
||||
EmptyScreen(
|
||||
msg,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
actions = persistentListOf(
|
||||
EmptyScreenAction(
|
||||
stringRes = MR.strings.label_extension_repos,
|
||||
icon = Icons.Outlined.Settings,
|
||||
onClick = { navigator.push(ExtensionReposScreen()) },
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
@@ -157,31 +164,6 @@ private fun ExtensionContent(
|
||||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
if (!state.hasExtensionRepos) {
|
||||
item(key = "extension-repos-warning") {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = MaterialTheme.padding.medium),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.ErrorOutline,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(SYMR.strings.no_repos_found),
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
||||
state.items.forEach { (header, items) ->
|
||||
item(
|
||||
contentType = "header",
|
||||
@@ -222,7 +204,13 @@ private fun ExtensionContent(
|
||||
items(
|
||||
items = items,
|
||||
contentType = { "item" },
|
||||
key = { "extension-${it.hashCode()}" },
|
||||
key = { item ->
|
||||
when (item.extension) {
|
||||
is Extension.Untrusted -> "extension-untrusted-${item.hashCode()}"
|
||||
is Extension.Installed -> "extension-installed-${item.hashCode()}"
|
||||
is Extension.Available -> "extension-available-${item.hashCode()}"
|
||||
}
|
||||
},
|
||||
) { item ->
|
||||
ExtensionItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
|
||||
@@ -37,7 +37,7 @@ import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.model.FeedSavedSearch
|
||||
import tachiyomi.domain.source.model.SavedSearch
|
||||
|
||||
@@ -31,7 +31,7 @@ import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
|
||||
@@ -25,13 +25,13 @@ import androidx.compose.ui.res.imageResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import coil.compose.AsyncImage
|
||||
import coil3.compose.AsyncImage
|
||||
import eu.kanade.domain.source.model.icon
|
||||
import eu.kanade.presentation.util.rememberResourceBitmapPainter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.source.local.isLocal
|
||||
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ private fun BrowseSourceComfortableGridItem(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ private fun BrowseSourceCompactGridItem(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
|
||||
|
||||
+9
-6
@@ -41,8 +41,8 @@ import exh.util.SourceTagsUtil
|
||||
import exh.util.SourceTagsUtil.GenreColor
|
||||
import exh.util.floor
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import tachiyomi.core.i18n.pluralStringResource
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.i18n.pluralStringResource
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
@@ -50,7 +50,8 @@ import tachiyomi.presentation.core.components.Badge
|
||||
import tachiyomi.presentation.core.components.BadgeGroup
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import java.util.Date
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
|
||||
@Composable
|
||||
fun BrowseSourceEHentaiList(
|
||||
@@ -128,9 +129,11 @@ fun BrowseSourceEHentaiListItem(
|
||||
}
|
||||
val datePosted by produceState("", metadata) {
|
||||
value = withIOContext {
|
||||
runCatching { metadata.datePosted?.let { MetadataUtil.EX_DATE_FORMAT.format(Date(it)) } }
|
||||
.getOrNull()
|
||||
.orEmpty()
|
||||
runCatching {
|
||||
metadata.datePosted?.let {
|
||||
MetadataUtil.EX_DATE_FORMAT.format(Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()))
|
||||
}
|
||||
}.getOrNull().orEmpty()
|
||||
}
|
||||
}
|
||||
val genre by produceState<Pair<GenreColor, StringResource>?>(null, metadata) {
|
||||
|
||||
@@ -79,7 +79,7 @@ private fun BrowseSourceListItem(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
|
||||
|
||||
@@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.Badge
|
||||
|
||||
@@ -25,7 +25,7 @@ import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.util.rememberResourceBitmapPainter
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@@ -2,7 +2,7 @@ package eu.kanade.presentation.category
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.Composable
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@@ -31,7 +31,7 @@ import eu.kanade.presentation.category.visualName
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.core.common.preference.CheckboxState
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
||||
@@ -97,5 +97,5 @@ fun AdaptiveSheet(
|
||||
|
||||
private val dialogProperties = DialogProperties(
|
||||
usePlatformDefaultWidth = false,
|
||||
decorFitsSystemWindows = false,
|
||||
decorFitsSystemWindows = true,
|
||||
)
|
||||
|
||||
@@ -9,20 +9,26 @@ import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
|
||||
@Composable
|
||||
fun relativeDateText(
|
||||
dateEpochMillis: Long,
|
||||
): String {
|
||||
return relativeDateText(
|
||||
date = Date(dateEpochMillis).takeIf { dateEpochMillis > 0L },
|
||||
localDate = LocalDate.ofInstant(
|
||||
Instant.ofEpochMilli(dateEpochMillis),
|
||||
ZoneId.systemDefault(),
|
||||
)
|
||||
.takeIf { dateEpochMillis > 0L },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun relativeDateText(
|
||||
date: Date?,
|
||||
localDate: LocalDate?,
|
||||
): String {
|
||||
val context = LocalContext.current
|
||||
|
||||
@@ -30,11 +36,10 @@ fun relativeDateText(
|
||||
val relativeTime = remember { preferences.relativeTime().get() }
|
||||
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) }
|
||||
|
||||
return date
|
||||
?.toRelativeString(
|
||||
context = context,
|
||||
relative = relativeTime,
|
||||
dateFormat = dateFormat,
|
||||
)
|
||||
return localDate?.toRelativeString(
|
||||
context = context,
|
||||
relative = relativeTime,
|
||||
dateFormat = dateFormat,
|
||||
)
|
||||
?: stringResource(MR.strings.not_applicable)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import androidx.compose.material.icons.outlined.Refresh
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
@@ -15,7 +15,7 @@ import tachiyomi.presentation.core.screens.EmptyScreenAction
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun NoActionPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Surface {
|
||||
EmptyScreen(
|
||||
stringRes = MR.strings.empty_screen,
|
||||
@@ -27,7 +27,7 @@ private fun NoActionPreview() {
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun WithActionPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Surface {
|
||||
EmptyScreen(
|
||||
stringRes = MR.strings.empty_screen,
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -29,7 +30,6 @@ import androidx.compose.ui.util.fastForEachIndexed
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.components.material.TabText
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@@ -78,9 +78,8 @@ fun TabbedDialog(
|
||||
modifier = Modifier.animateContentSize(),
|
||||
state = pagerState,
|
||||
verticalAlignment = Alignment.Top,
|
||||
) { page ->
|
||||
content(page)
|
||||
}
|
||||
pageContent = { page -> content(page) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.PrimaryTabRow
|
||||
@@ -24,7 +25,6 @@ import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.TabText
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
@@ -101,6 +101,6 @@ data class TabContent(
|
||||
val titleRes: StringResource,
|
||||
val badgeNumber: Int? = null,
|
||||
val searchEnabled: Boolean = false,
|
||||
val actions: ImmutableList<AppBar.Action> = persistentListOf(),
|
||||
val actions: ImmutableList<AppBar.AppBarAction> = persistentListOf(),
|
||||
val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit,
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
@@ -63,7 +63,7 @@ fun CrashScreen(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun CrashScreenPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
CrashScreen(exception = RuntimeException("Dummy")) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import eu.kanade.presentation.components.AppBarTitle
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.presentation.components.relativeDateText
|
||||
import eu.kanade.presentation.history.components.HistoryItem
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -29,7 +29,7 @@ import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import java.util.Date
|
||||
import java.time.LocalDate
|
||||
|
||||
@Composable
|
||||
fun HistoryScreen(
|
||||
@@ -134,7 +134,7 @@ private fun HistoryScreenContent(
|
||||
}
|
||||
|
||||
sealed interface HistoryUiModel {
|
||||
data class Header(val date: Date) : HistoryUiModel
|
||||
data class Header(val date: LocalDate) : HistoryUiModel
|
||||
data class Item(val item: HistoryWithRelations) : HistoryUiModel
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ internal fun HistoryScreenPreviews(
|
||||
@PreviewParameter(HistoryScreenModelStateProvider::class)
|
||||
historyState: HistoryScreenModel.State,
|
||||
) {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
HistoryScreen(
|
||||
state = historyState,
|
||||
snackbarHostState = SnackbarHostState(),
|
||||
|
||||
@@ -7,6 +7,7 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.Date
|
||||
import kotlin.random.Random
|
||||
@@ -73,10 +74,10 @@ class HistoryScreenModelStateProvider : PreviewParameterProvider<HistoryScreenMo
|
||||
private object HistoryUiModelExamples {
|
||||
val headerToday = header()
|
||||
val headerTomorrow =
|
||||
HistoryUiModel.Header(Date.from(Instant.now().plus(1, ChronoUnit.DAYS)))
|
||||
HistoryUiModel.Header(LocalDate.now().plusDays(1))
|
||||
|
||||
fun header(instantBuilder: (Instant) -> Instant = { it }) =
|
||||
HistoryUiModel.Header(Date.from(instantBuilder(Instant.now())))
|
||||
HistoryUiModel.Header(LocalDate.from(instantBuilder(Instant.now())))
|
||||
|
||||
fun items() = sequence {
|
||||
var count = 1
|
||||
@@ -103,7 +104,7 @@ class HistoryScreenModelStateProvider : PreviewParameterProvider<HistoryScreenMo
|
||||
mangaId = Random.nextLong(),
|
||||
sourceId = Random.nextLong(),
|
||||
isMangaFavorite = Random.nextBoolean(),
|
||||
url = "https://example.com/cover.png",
|
||||
ogUrl = "https://example.com/cover.png",
|
||||
lastModified = Random.nextLong(),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -12,7 +12,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
@@ -91,7 +91,7 @@ fun HistoryDeleteAllDialog(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun HistoryDeleteDialogPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
HistoryDeleteDialog(
|
||||
onDismissRequest = {},
|
||||
onDelete = {},
|
||||
|
||||
@@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.util.lang.toTimestampString
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
@@ -98,7 +98,7 @@ private fun HistoryItemPreviews(
|
||||
@PreviewParameter(HistoryWithRelationsProvider::class)
|
||||
historyWithRelations: HistoryWithRelations,
|
||||
) {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Surface {
|
||||
HistoryItem(
|
||||
history = historyWithRelations,
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
|
||||
mangaId = 3L,
|
||||
sourceId = 4L,
|
||||
isMangaFavorite = false,
|
||||
url = "https://example.com/cover.png",
|
||||
ogUrl = "https://example.com/cover.png",
|
||||
lastModified = 5L,
|
||||
),
|
||||
)
|
||||
@@ -39,7 +39,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
|
||||
mangaId = 3L,
|
||||
sourceId = 4L,
|
||||
isMangaFavorite = false,
|
||||
url = "https://example.com/cover.png",
|
||||
ogUrl = "https://example.com/cover.png",
|
||||
lastModified = 5L,
|
||||
),
|
||||
)
|
||||
@@ -58,7 +58,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
|
||||
mangaId = 3L,
|
||||
sourceId = 4L,
|
||||
isMangaFavorite = false,
|
||||
url = "https://example.com/cover.png",
|
||||
ogUrl = "https://example.com/cover.png",
|
||||
lastModified = 5L,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.core.common.preference.CheckboxState
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@@ -26,7 +26,7 @@ import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.library.model.LibraryGroup
|
||||
|
||||
@@ -6,7 +6,7 @@ import androidx.compose.material.icons.outlined.Folder
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.presentation.core.components.Badge
|
||||
|
||||
@Composable
|
||||
@@ -50,7 +50,7 @@ internal fun LanguageBadge(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun BadgePreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Column {
|
||||
DownloadsBadge(count = 10)
|
||||
UnreadBadge(count = 10)
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ internal fun LibraryComfortableGrid(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
coverBadgeStart = {
|
||||
|
||||
@@ -42,7 +42,7 @@ internal fun LibraryCompactGrid(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
coverBadgeStart = {
|
||||
|
||||
@@ -51,7 +51,7 @@ internal fun LibraryList(
|
||||
mangaId = manga.id,
|
||||
sourceId = manga.source,
|
||||
isMangaFavorite = manga.favorite,
|
||||
url = manga.thumbnailUrl,
|
||||
ogUrl = manga.thumbnailUrl,
|
||||
lastModified = manga.coverLastModified,
|
||||
),
|
||||
badge = {
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
@@ -22,7 +23,6 @@ import eu.kanade.tachiyomi.ui.library.LibraryItem
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import exh.favorites.FavoritesSyncStatus
|
||||
import kotlinx.coroutines.delay
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.core.text.HtmlCompat
|
||||
import exh.util.toAnnotatedString
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@@ -31,7 +31,7 @@ import eu.kanade.domain.manga.model.forceDownloaded
|
||||
import eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
|
||||
@@ -106,7 +106,8 @@ import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrollingUp
|
||||
import tachiyomi.source.local.isLocal
|
||||
import java.time.Instant
|
||||
import java.util.Date
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@Composable
|
||||
fun MangaScreen(
|
||||
@@ -150,6 +151,7 @@ fun MangaScreen(
|
||||
onMergeWithAnotherClicked: () -> Unit,
|
||||
onOpenPagePreview: (Int) -> Unit,
|
||||
onMorePreviewsClicked: () -> Unit,
|
||||
previewsRowCount: Int,
|
||||
// SY <--
|
||||
|
||||
// For bottom action menu
|
||||
@@ -208,6 +210,7 @@ fun MangaScreen(
|
||||
onMergeWithAnotherClicked = onMergeWithAnotherClicked,
|
||||
onOpenPagePreview = onOpenPagePreview,
|
||||
onMorePreviewsClicked = onMorePreviewsClicked,
|
||||
previewsRowCount = previewsRowCount,
|
||||
// SY <--
|
||||
onMultiBookmarkClicked = onMultiBookmarkClicked,
|
||||
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
|
||||
@@ -253,6 +256,7 @@ fun MangaScreen(
|
||||
onMergeWithAnotherClicked = onMergeWithAnotherClicked,
|
||||
onOpenPagePreview = onOpenPagePreview,
|
||||
onMorePreviewsClicked = onMorePreviewsClicked,
|
||||
previewsRowCount = previewsRowCount,
|
||||
// SY <--
|
||||
onMultiBookmarkClicked = onMultiBookmarkClicked,
|
||||
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
|
||||
@@ -308,6 +312,7 @@ private fun MangaScreenSmallImpl(
|
||||
onMergeWithAnotherClicked: () -> Unit,
|
||||
onOpenPagePreview: (Int) -> Unit,
|
||||
onMorePreviewsClicked: () -> Unit,
|
||||
previewsRowCount: Int,
|
||||
// SY <--
|
||||
|
||||
// For bottom action menu
|
||||
@@ -544,13 +549,14 @@ private fun MangaScreenSmallImpl(
|
||||
}
|
||||
}
|
||||
|
||||
if (state.pagePreviewsState !is PagePreviewState.Unused) {
|
||||
if (state.pagePreviewsState !is PagePreviewState.Unused && previewsRowCount > 0) {
|
||||
PagePreviewItems(
|
||||
pagePreviewState = state.pagePreviewsState,
|
||||
onOpenPage = onOpenPagePreview,
|
||||
onMorePreviewsClicked = onMorePreviewsClicked,
|
||||
maxWidth = maxWidth,
|
||||
setMaxWidth = { maxWidth = it }
|
||||
setMaxWidth = { maxWidth = it },
|
||||
rowCount = previewsRowCount,
|
||||
)
|
||||
}
|
||||
// SY <--
|
||||
@@ -632,6 +638,7 @@ fun MangaScreenLargeImpl(
|
||||
onMergeWithAnotherClicked: () -> Unit,
|
||||
onOpenPagePreview: (Int) -> Unit,
|
||||
onMorePreviewsClicked: () -> Unit,
|
||||
previewsRowCount: Int,
|
||||
// SY <--
|
||||
|
||||
// For bottom action menu
|
||||
@@ -832,11 +839,12 @@ fun MangaScreenLargeImpl(
|
||||
onMergeWithAnotherClicked = onMergeWithAnotherClicked,
|
||||
)
|
||||
}
|
||||
if (state.pagePreviewsState !is PagePreviewState.Unused) {
|
||||
if (state.pagePreviewsState !is PagePreviewState.Unused && previewsRowCount > 0) {
|
||||
PagePreviews(
|
||||
pagePreviewState = state.pagePreviewsState,
|
||||
onOpenPage = onOpenPagePreview,
|
||||
onMorePreviewsClicked = onMorePreviewsClicked,
|
||||
rowCount = previewsRowCount,
|
||||
)
|
||||
}
|
||||
// SY <--
|
||||
@@ -979,9 +987,10 @@ private fun LazyListScope.sharedChapterItems(
|
||||
?.let {
|
||||
// SY -->
|
||||
if (manga.isEhBasedManga()) {
|
||||
MetadataUtil.EX_DATE_FORMAT.format(Date(it))
|
||||
MetadataUtil.EX_DATE_FORMAT
|
||||
.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(it), ZoneId.systemDefault()))
|
||||
} else {
|
||||
relativeDateText(Date(item.chapter.dateUpload))
|
||||
relativeDateText(item.chapter.dateUpload)
|
||||
}
|
||||
// SY <--
|
||||
},
|
||||
|
||||
+25
-21
@@ -2,7 +2,6 @@ package eu.kanade.presentation.manga.components
|
||||
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -10,7 +9,7 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.outlined.ArrowDownward
|
||||
import androidx.compose.material.icons.outlined.ErrorOutline
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material.ripple
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -24,8 +23,8 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
@@ -86,11 +85,13 @@ private fun NotDownloadedIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: (ChapterDownloadAction) -> Unit,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(IconButtonTokens.StateLayerSize)
|
||||
.commonClickable(
|
||||
enabled = enabled,
|
||||
hapticFeedback = hapticFeedback,
|
||||
onLongClick = { onClick(ChapterDownloadAction.START_NOW) },
|
||||
onClick = { onClick(ChapterDownloadAction.START) },
|
||||
)
|
||||
@@ -114,12 +115,14 @@ private fun DownloadingIndicator(
|
||||
onClick: (ChapterDownloadAction) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(IconButtonTokens.StateLayerSize)
|
||||
.commonClickable(
|
||||
enabled = enabled,
|
||||
hapticFeedback = hapticFeedback,
|
||||
onLongClick = { onClick(ChapterDownloadAction.CANCEL) },
|
||||
onClick = { isMenuExpanded = true },
|
||||
),
|
||||
@@ -185,12 +188,14 @@ private fun DownloadedIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: (ChapterDownloadAction) -> Unit,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(IconButtonTokens.StateLayerSize)
|
||||
.commonClickable(
|
||||
enabled = enabled,
|
||||
hapticFeedback = hapticFeedback,
|
||||
onLongClick = { isMenuExpanded = true },
|
||||
onClick = { isMenuExpanded = true },
|
||||
),
|
||||
@@ -220,11 +225,13 @@ private fun ErrorIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: (ChapterDownloadAction) -> Unit,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(IconButtonTokens.StateLayerSize)
|
||||
.commonClickable(
|
||||
enabled = enabled,
|
||||
hapticFeedback = hapticFeedback,
|
||||
onLongClick = { onClick(ChapterDownloadAction.START) },
|
||||
onClick = { onClick(ChapterDownloadAction.START) },
|
||||
),
|
||||
@@ -241,26 +248,23 @@ private fun ErrorIndicator(
|
||||
|
||||
private fun Modifier.commonClickable(
|
||||
enabled: Boolean,
|
||||
hapticFeedback: HapticFeedback,
|
||||
onLongClick: () -> Unit,
|
||||
onClick: () -> Unit,
|
||||
) = composed {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
|
||||
Modifier.combinedClickable(
|
||||
enabled = enabled,
|
||||
onLongClick = {
|
||||
onLongClick()
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onClick = onClick,
|
||||
role = Role.Button,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(
|
||||
bounded = false,
|
||||
radius = IconButtonTokens.StateLayerSize / 2,
|
||||
),
|
||||
)
|
||||
}
|
||||
) = this.combinedClickable(
|
||||
enabled = enabled,
|
||||
onLongClick = {
|
||||
onLongClick()
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onClick = onClick,
|
||||
role = Role.Button,
|
||||
interactionSource = null,
|
||||
indication = ripple(
|
||||
bounded = false,
|
||||
radius = IconButtonTokens.StateLayerSize / 2,
|
||||
),
|
||||
)
|
||||
|
||||
private val IndicatorSize = 26.dp
|
||||
private val IndicatorPadding = 2.dp
|
||||
|
||||
@@ -33,7 +33,7 @@ import androidx.compose.material.icons.outlined.Label
|
||||
import androidx.compose.material.icons.outlined.MoreVert
|
||||
import androidx.compose.material.icons.outlined.RemoveDone
|
||||
import androidx.compose.material.icons.outlined.SwapCalls
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material.ripple
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -200,7 +200,7 @@ private fun RowScope.Button(
|
||||
.weight(animatedWeight)
|
||||
.combinedClickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false),
|
||||
indication = ripple(bounded = false),
|
||||
onLongClick = onLongClick,
|
||||
onClick = onClick,
|
||||
),
|
||||
|
||||
+112
-147
@@ -24,36 +24,27 @@ import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import me.saket.swipe.SwipeableActionsBox
|
||||
import me.saket.swipe.rememberSwipeableActionsState
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
@Composable
|
||||
fun MangaChapterListItem(
|
||||
@@ -78,158 +69,132 @@ fun MangaChapterListItem(
|
||||
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val density = LocalDensity.current
|
||||
|
||||
val textAlpha = if (read) ReadItemAlpha else 1f
|
||||
val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha
|
||||
|
||||
// Increase touch slop of swipe action to reduce accidental trigger
|
||||
val configuration = LocalViewConfiguration.current
|
||||
CompositionLocalProvider(
|
||||
LocalViewConfiguration provides object : ViewConfiguration by configuration {
|
||||
override val touchSlop: Float = configuration.touchSlop * 3f
|
||||
},
|
||||
val start = getSwipeAction(
|
||||
action = chapterSwipeStartAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeStartAction) },
|
||||
)
|
||||
val end = getSwipeAction(
|
||||
action = chapterSwipeEndAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
|
||||
)
|
||||
|
||||
SwipeableActionsBox(
|
||||
modifier = Modifier.clipToBounds(),
|
||||
startActions = listOfNotNull(start),
|
||||
endActions = listOfNotNull(end),
|
||||
swipeThreshold = swipeActionThreshold,
|
||||
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||
) {
|
||||
val start = getSwipeAction(
|
||||
action = chapterSwipeStartAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeStartAction) },
|
||||
)
|
||||
val end = getSwipeAction(
|
||||
action = chapterSwipeEndAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
|
||||
)
|
||||
|
||||
val swipeableActionsState = rememberSwipeableActionsState()
|
||||
LaunchedEffect(Unit) {
|
||||
// Haptic effect when swipe over threshold
|
||||
val swipeActionThresholdPx = with(density) { swipeActionThreshold.toPx() }
|
||||
snapshotFlow { swipeableActionsState.offset.value.absoluteValue > swipeActionThresholdPx }
|
||||
.collect { if (it) haptic.performHapticFeedback(HapticFeedbackType.LongPress) }
|
||||
}
|
||||
|
||||
SwipeableActionsBox(
|
||||
modifier = Modifier.clipToBounds(),
|
||||
state = swipeableActionsState,
|
||||
startActions = listOfNotNull(start),
|
||||
endActions = listOfNotNull(end),
|
||||
swipeThreshold = swipeActionThreshold,
|
||||
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||
Row(
|
||||
modifier = modifier
|
||||
.selectedBackground(selected)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
.padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.selectedBackground(selected)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
.padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
var textHeight by remember { mutableIntStateOf(0) }
|
||||
if (!read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
if (bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
onTextLayout = { textHeight = it.size.height },
|
||||
var textHeight by remember { mutableIntStateOf(0) }
|
||||
if (!read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
if (bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
onTextLayout = { textHeight = it.size.height },
|
||||
)
|
||||
}
|
||||
|
||||
Row {
|
||||
ProvideTextStyle(
|
||||
value = MaterialTheme.typography.bodyMedium.copy(
|
||||
fontSize = 12.sp,
|
||||
color = LocalContentColor.current.copy(alpha = textSubtitleAlpha),
|
||||
),
|
||||
) {
|
||||
if (date != null) {
|
||||
Text(
|
||||
text = date,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (
|
||||
readProgress != null ||
|
||||
scanlator != null/* SY --> */ ||
|
||||
sourceName != null/* SY <-- */
|
||||
) {
|
||||
DotSeparatorText()
|
||||
}
|
||||
}
|
||||
if (readProgress != null) {
|
||||
Text(
|
||||
text = readProgress,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
||||
)
|
||||
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
||||
}
|
||||
// SY -->
|
||||
if (sourceName != null) {
|
||||
Text(
|
||||
text = sourceName,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (scanlator != null) DotSeparatorText()
|
||||
}
|
||||
// SY <--
|
||||
if (scanlator != null) {
|
||||
Text(
|
||||
text = scanlator,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
Row {
|
||||
ProvideTextStyle(
|
||||
value = MaterialTheme.typography.bodyMedium.copy(
|
||||
fontSize = 12.sp,
|
||||
color = LocalContentColor.current.copy(alpha = textSubtitleAlpha),
|
||||
),
|
||||
) {
|
||||
if (date != null) {
|
||||
Text(
|
||||
text = date,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (readProgress != null || scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
||||
}
|
||||
if (readProgress != null) {
|
||||
Text(
|
||||
text = readProgress,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
||||
)
|
||||
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
||||
}
|
||||
// SY -->
|
||||
if (sourceName != null) {
|
||||
Text(
|
||||
text = sourceName,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
if (scanlator != null) DotSeparatorText()
|
||||
}
|
||||
// SY <--
|
||||
if (scanlator != null) {
|
||||
Text(
|
||||
text = scanlator,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChapterDownloadIndicator(
|
||||
enabled = downloadIndicatorEnabled,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
downloadStateProvider = downloadStateProvider,
|
||||
downloadProgressProvider = downloadProgressProvider,
|
||||
onClick = { onDownloadClick?.invoke(it) },
|
||||
)
|
||||
}
|
||||
|
||||
ChapterDownloadIndicator(
|
||||
enabled = downloadIndicatorEnabled,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
downloadStateProvider = downloadStateProvider,
|
||||
downloadProgressProvider = downloadProgressProvider,
|
||||
onClick = { onDownloadClick?.invoke(it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.painter.ColorPainter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import coil.compose.AsyncImage
|
||||
import coil3.compose.AsyncImage
|
||||
import eu.kanade.presentation.util.rememberResourceBitmapPainter
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.core.view.updatePadding
|
||||
import coil.imageLoader
|
||||
import coil.request.CachePolicy
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Size
|
||||
import coil3.imageLoader
|
||||
import coil3.request.CachePolicy
|
||||
import coil3.request.ImageRequest
|
||||
import coil3.size.Size
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
@@ -169,7 +169,9 @@ fun MangaCoverDialog(
|
||||
.data(coverDataProvider())
|
||||
.size(Size.ORIGINAL)
|
||||
.memoryCachePolicy(CachePolicy.DISABLED)
|
||||
.target { drawable ->
|
||||
.target { image ->
|
||||
val drawable = image.asDrawable(view.context.resources)
|
||||
|
||||
// Copy bitmap in case it came from memory cache
|
||||
// Because SSIV needs to thoroughly read the image
|
||||
val copy = (drawable as? BitmapDrawable)?.let {
|
||||
|
||||
@@ -73,7 +73,7 @@ import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import coil.compose.AsyncImage
|
||||
import coil3.compose.AsyncImage
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
@@ -44,7 +44,7 @@ fun MissingChapterCountListItem(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Surface {
|
||||
MissingChapterCountListItem(count = 42)
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.components.ChipBorder
|
||||
import eu.kanade.presentation.components.SuggestionChip
|
||||
import eu.kanade.presentation.components.SuggestionChipDefaults
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
@@ -173,10 +173,10 @@ fun TagsChip(
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
fun NamespaceTagsPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
Surface {
|
||||
val context = LocalContext.current
|
||||
NamespaceTags(
|
||||
|
||||
@@ -25,14 +25,13 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.compose.SubcomposeAsyncImageContent
|
||||
import coil3.compose.SubcomposeAsyncImage
|
||||
import coil3.compose.SubcomposeAsyncImageContent
|
||||
import eu.kanade.domain.manga.model.PagePreview
|
||||
import eu.kanade.presentation.manga.MangaScreenItem
|
||||
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
|
||||
@@ -102,6 +101,7 @@ fun PagePreviews(
|
||||
pagePreviewState: PagePreviewState,
|
||||
onOpenPage: (Int) -> Unit,
|
||||
onMorePreviewsClicked: () -> Unit,
|
||||
rowCount: Int,
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
var maxWidth by remember {
|
||||
@@ -113,7 +113,7 @@ fun PagePreviews(
|
||||
}
|
||||
pagePreviewState is PagePreviewState.Success -> {
|
||||
val itemPerRowCount = (maxWidth / 120.dp).floor()
|
||||
pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
||||
pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
||||
PagePreviewRow(
|
||||
onOpenPage = onOpenPage,
|
||||
items = remember(it) { it.toImmutableList() }
|
||||
@@ -132,7 +132,8 @@ fun LazyListScope.PagePreviewItems(
|
||||
onOpenPage: (Int) -> Unit,
|
||||
onMorePreviewsClicked: () -> Unit,
|
||||
maxWidth: Dp,
|
||||
setMaxWidth: (Dp) -> Unit
|
||||
setMaxWidth: (Dp) -> Unit,
|
||||
rowCount: Int,
|
||||
) {
|
||||
when {
|
||||
pagePreviewState is PagePreviewState.Loading || maxWidth == Dp.Hairline -> {
|
||||
@@ -148,7 +149,7 @@ fun LazyListScope.PagePreviewItems(
|
||||
items(
|
||||
key = { "${MangaScreenItem.CHAPTER_PREVIEW_ROW}-$it" },
|
||||
contentType = { MangaScreenItem.CHAPTER_PREVIEW_ROW },
|
||||
items = pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount),
|
||||
items = pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount),
|
||||
) {
|
||||
PagePreviewRow(
|
||||
onOpenPage = onOpenPage,
|
||||
|
||||
@@ -13,11 +13,13 @@ import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.automirrored.outlined.Label
|
||||
import androidx.compose.material.icons.automirrored.outlined.PlaylistAdd
|
||||
import androidx.compose.material.icons.outlined.CloudOff
|
||||
import androidx.compose.material.icons.outlined.Extension
|
||||
import androidx.compose.material.icons.outlined.GetApp
|
||||
import androidx.compose.material.icons.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.History
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material.icons.outlined.Label
|
||||
import androidx.compose.material.icons.outlined.NewReleases
|
||||
import androidx.compose.material.icons.outlined.PlaylistAdd
|
||||
import androidx.compose.material.icons.outlined.QueryStats
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.Storage
|
||||
@@ -32,7 +34,7 @@ import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
|
||||
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.more.DownloadQueueState
|
||||
import tachiyomi.core.Constants
|
||||
import tachiyomi.core.common.Constants
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
@@ -58,12 +60,9 @@ fun MoreScreen(
|
||||
onClickDataAndStorage: () -> Unit,
|
||||
onClickSettings: () -> Unit,
|
||||
onClickAbout: () -> Unit,
|
||||
// SY -->
|
||||
onClickBatchAdd: () -> Unit,
|
||||
onClickUpdates: () -> Unit,
|
||||
onClickHistory: () -> Unit,
|
||||
onClickRepos: () -> Unit,
|
||||
// SY <--
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
@@ -79,7 +78,7 @@ fun MoreScreen(
|
||||
textRes = MR.strings.fdroid_warning,
|
||||
modifier = Modifier.clickable {
|
||||
uriHandler.openUri(
|
||||
"https://tachiyomi.org/docs/faq/general#how-do-i-update-from-the-f-droid-builds",
|
||||
"https://mihon.app/docs/faq/general#how-do-i-update-from-the-f-droid-builds",
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -164,15 +163,6 @@ fun MoreScreen(
|
||||
onPreferenceClick = onClickDownloadQueue,
|
||||
)
|
||||
}
|
||||
// SY -->
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(MR.strings.label_extension_repos),
|
||||
icon = Icons.Outlined.Extension,
|
||||
onPreferenceClick = onClickRepos
|
||||
)
|
||||
}
|
||||
// SY <--
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(MR.strings.categories),
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.halilibo.richtext.markdown.Markdown
|
||||
import com.halilibo.richtext.ui.RichTextStyle
|
||||
import com.halilibo.richtext.ui.material3.RichText
|
||||
import com.halilibo.richtext.ui.string.RichTextStringStyle
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
@@ -69,7 +69,7 @@ fun NewUpdateScreen(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun NewUpdateScreenPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
NewUpdateScreen(
|
||||
versionName = "v0.99.9",
|
||||
changelogInfo = """
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
@@ -56,12 +56,12 @@ internal class GuidesStep(
|
||||
}
|
||||
}
|
||||
|
||||
const val GETTING_STARTED_URL = "https://tachiyomi.org/docs/guides/getting-started"
|
||||
const val GETTING_STARTED_URL = "https://mihon.app/docs/guides/getting-started"
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun GuidesStepPreview() {
|
||||
TachiyomiTheme {
|
||||
TachiyomiPreviewTheme {
|
||||
GuidesStep(
|
||||
onRestoreBackup = {},
|
||||
).Content()
|
||||
|
||||
@@ -8,7 +8,7 @@ import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.core.preference.Preference as PreferenceData
|
||||
import tachiyomi.core.common.preference.Preference as PreferenceData
|
||||
|
||||
sealed class Preference {
|
||||
abstract val title: String
|
||||
|
||||
@@ -18,7 +18,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withContext
|
||||
import tachiyomi.core.util.lang.launchUI
|
||||
import tachiyomi.core.common.util.lang.launchUI
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
|
||||
+5
-5
@@ -79,11 +79,11 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import okhttp3.Headers
|
||||
import tachiyomi.core.i18n.pluralStringResource
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.core.common.i18n.pluralStringResource
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
|
||||
import tachiyomi.domain.manga.interactor.GetAllManga
|
||||
|
||||
+20
-2
@@ -23,11 +23,12 @@ import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
|
||||
object SettingsAppearanceScreen : SearchableSettings {
|
||||
|
||||
@@ -106,7 +107,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val now = remember { Instant.now().toEpochMilli() }
|
||||
val now = remember { LocalDate.now() }
|
||||
|
||||
val dateFormat by uiPreferences.dateFormat().collectAsState()
|
||||
val formattedNow = remember(dateFormat) {
|
||||
@@ -157,6 +158,8 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
// SY -->
|
||||
@Composable
|
||||
fun getForkGroup(uiPreferences: UiPreferences): Preference.PreferenceGroup {
|
||||
val previewsRowCount by uiPreferences.previewsRowCount().collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
stringResource(SYMR.strings.pref_category_fork),
|
||||
preferenceItems = persistentListOf(
|
||||
@@ -174,6 +177,21 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
title = stringResource(SYMR.strings.put_merge_in_overflow),
|
||||
subtitle = stringResource(SYMR.strings.put_merge_in_overflow_summary),
|
||||
),
|
||||
Preference.PreferenceItem.SliderPreference(
|
||||
value = previewsRowCount,
|
||||
title = stringResource(SYMR.strings.pref_previews_row_count),
|
||||
subtitle = if (previewsRowCount > 0) pluralStringResource(
|
||||
SYMR.plurals.row_count,
|
||||
previewsRowCount,
|
||||
previewsRowCount,
|
||||
) else stringResource(MR.strings.disabled),
|
||||
min = 0,
|
||||
max = 10,
|
||||
onValueChanged = {
|
||||
uiPreferences.previewsRowCount().set(it)
|
||||
true
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user