Compare commits
177 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dea38912fc | |||
| 5243346356 | |||
| 6bb3ec5b8a | |||
| 7390e72045 | |||
| 64ff5cb9af | |||
| 82f011e48e | |||
| 8868a5db2b | |||
| a335feedfc | |||
| 90ff5e69ec | |||
| 68a1820695 | |||
| 292b551027 | |||
| e19c62a8ae | |||
| 348cb335c4 | |||
| c426d11d76 | |||
| 1965c0825d | |||
| 0124763fcd | |||
| b0d737592c | |||
| e14596465b | |||
| 5e52dfcc66 | |||
| a09643fc77 | |||
| 19bc08659b | |||
| 2cb8f8f872 | |||
| 23c7bb09d3 | |||
| bdb8553e28 | |||
| fbac29e0cd | |||
| b0aa2ffc42 | |||
| 45b5d9b8a4 | |||
| 91b98cdb82 | |||
| 7f544f7163 | |||
| 3705880a77 | |||
| 759fd4d4e3 | |||
| fc956fc791 | |||
| 9d7346157b | |||
| 0f0f4cf4a9 | |||
| 426ef65102 | |||
| 95c834581b | |||
| 71f2daf8f3 | |||
| 7ec14cd9f0 | |||
| c23c9491fc | |||
| 29f3766c87 | |||
| 07c89890bc | |||
| 64a54f55b3 | |||
| f7202e67cc | |||
| 155b03c176 | |||
| 6b0482576b | |||
| c137bafd68 | |||
| 49bdffdc28 | |||
| f1b32d531a | |||
| a5ec6c5cdd | |||
| 9c56cdb1c1 | |||
| 543de065a6 | |||
| 33296e1faf | |||
| d1a90c0bb7 | |||
| 9fa61d33be | |||
| 0e9dcc7855 | |||
| 6738c6072d | |||
| 29033c539c | |||
| eaa3413c37 | |||
| 73d9d1d46d | |||
| 94f9aaf351 | |||
| e21149cb37 | |||
| 11aad16f59 | |||
| 33a3918e86 | |||
| d655b8ecdf | |||
| 70a8bef7a5 | |||
| 999a8613cf | |||
| 5721a02bca | |||
| e303b88b90 | |||
| a62dd5821a | |||
| a0786d9b09 | |||
| 04580ce357 | |||
| b759f2f02a | |||
| 8ae8068ecd | |||
| eecd9367d4 | |||
| 55dee69838 | |||
| a730ca5444 | |||
| cebd8fe0a8 | |||
| 55a979c5f7 | |||
| 728f3fc349 | |||
| a9a3ed1d16 | |||
| 36f13a7c6a | |||
| 37a2ccc678 | |||
| bb39088dd7 | |||
| c5546e1095 | |||
| 2d12c670db | |||
| 3db4bccebc | |||
| 2f23ad6bfd | |||
| de1898a2c9 | |||
| eb135ec22d | |||
| bf6c646dc7 | |||
| 9ce16d5e1c | |||
| 619ff726c8 | |||
| 730ceaaf49 | |||
| 07b701cb3c | |||
| b64c6b78ea | |||
| 521bce5c08 | |||
| a719ed8c9e | |||
| f6fc2d7e2f | |||
| 48d43c4f07 | |||
| f4fa86b2dc | |||
| 37db0dc1f6 | |||
| 1ada03b07a | |||
| f4c1e7c2d5 | |||
| 6c5282c598 | |||
| 7899474a36 | |||
| 225b419bba | |||
| fa64103a1c | |||
| 57e0e99f06 | |||
| efde7afa8e | |||
| f929a4bc26 | |||
| d35141c1cc | |||
| 6988966019 | |||
| f6d8ebbb0a | |||
| ae45df9fcf | |||
| f332344681 | |||
| c6abb340ca | |||
| 99dbb16a7a | |||
| f62e8933d7 | |||
| ee3c2fd79c | |||
| 6b08b873a8 | |||
| a3f2f49ab8 | |||
| 524f5cc6ab | |||
| a35e084b9e | |||
| 78f7fba67b | |||
| 69d1db3018 | |||
| d1b317e5c8 | |||
| fff40e031f | |||
| 5be2ec51ba | |||
| 1c2a7af13e | |||
| 182158acb0 | |||
| 21f92bfb3a | |||
| a5522ef732 | |||
| 239793f7fd | |||
| 4e9cfe4602 | |||
| f548c85e7a | |||
| 576349c446 | |||
| 9b00e0458b | |||
| 6a1ff99441 | |||
| 0121fe9397 | |||
| 5c47c7a409 | |||
| 8bb4f33f2e | |||
| 5f5fd51668 | |||
| c7bbad93b2 | |||
| 1a4a2506f4 | |||
| 7b7a594ddb | |||
| c2eece0fff | |||
| d29a4ff381 | |||
| 31f967235f | |||
| 7d6e746257 | |||
| d306139047 | |||
| 7e6811692e | |||
| 8df0446020 | |||
| 8ccf8fc74d | |||
| 4deaa41c53 | |||
| c843789f66 | |||
| 78da81fa42 | |||
| 4fc96f263d | |||
| 6a12b54ecb | |||
| 8ffcd5efec | |||
| 26121efeb4 | |||
| 1ecf3a567b | |||
| 20fff5798d | |||
| 0ba580ba30 | |||
| aaf28ee4f1 | |||
| 8558c110a9 | |||
| 3865583c28 | |||
| b2cc61f6fd | |||
| 47dd58de2a | |||
| 67d42c9c2b | |||
| b97f322d6f | |||
| d8cc4f8b45 | |||
| f78752fbdf | |||
| d968d58cd6 | |||
| 54d5f9baaf | |||
| c1bf53e28a | |||
| 517fd3a8f4 | |||
| 089d1aba57 |
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"config:base"
|
||||||
|
],
|
||||||
|
"labels": ["Dependencies"],
|
||||||
|
"includePaths": [".github/workflows/*", "gradle/sy.versions.toml"],
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build app
|
name: Build app
|
||||||
@@ -27,19 +27,19 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: adopt
|
distribution: adopt
|
||||||
|
|
||||||
- name: Set up gradle
|
- name: Set up gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Build app
|
- name: Build app
|
||||||
run: ./gradlew detekt assembleDevDebug
|
run: ./gradlew spotlessCheck assembleDevDebug
|
||||||
|
|
||||||
- name: Upload APK
|
- name: Upload APK
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: TachiyomiSY-${{ github.sha }}.apk
|
name: TachiyomiSY-${{ github.sha }}.apk
|
||||||
path: app/build/outputs/apk/dev/debug/app-dev-debug.apk
|
path: app/build/outputs/apk/dev/debug/app-dev-debug.apk
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v2
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
- name: Setup Android SDK
|
- name: Setup Android SDK
|
||||||
run: |
|
run: |
|
||||||
@@ -31,18 +31,18 @@ jobs:
|
|||||||
distribution: adopt
|
distribution: adopt
|
||||||
|
|
||||||
- name: Set up gradle
|
- name: Set up gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
# SY <--
|
# SY <--
|
||||||
- name: Write google-services.json
|
- name: Write google-services.json
|
||||||
uses: DamianReeves/write-file-action@v1.2
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
with:
|
with:
|
||||||
path: app/google-services.json
|
path: app/google-services.json
|
||||||
contents: ${{ secrets.GOOGLE_SERVICES_TEXT }}
|
contents: ${{ secrets.GOOGLE_SERVICES_TEXT }}
|
||||||
write-mode: overwrite
|
write-mode: overwrite
|
||||||
|
|
||||||
- name: Write client_secrets.json
|
- name: Write client_secrets.json
|
||||||
uses: DamianReeves/write-file-action@v1.2
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
with:
|
with:
|
||||||
path: app/src/main/assets/client_secrets.json
|
path: app/src/main/assets/client_secrets.json
|
||||||
contents: ${{ secrets.CLIENT_SECRETS_TEXT }}
|
contents: ${{ secrets.CLIENT_SECRETS_TEXT }}
|
||||||
@@ -50,7 +50,7 @@ jobs:
|
|||||||
# SY -->
|
# SY -->
|
||||||
|
|
||||||
- name: Build app and run unit tests
|
- name: Build app and run unit tests
|
||||||
run: ./gradlew detekt assembleStandardRelease testStandardReleaseUnitTest --stacktrace
|
run: ./gradlew spotlessCheck assembleStandardRelease testStandardReleaseUnitTest --stacktrace
|
||||||
|
|
||||||
- name: Sign APK
|
- name: Sign APK
|
||||||
uses: r0adkll/sign-android-release@v1
|
uses: r0adkll/sign-android-release@v1
|
||||||
@@ -86,7 +86,7 @@ jobs:
|
|||||||
echo "APK_X86_64_SHA=$sha" >> $GITHUB_ENV
|
echo "APK_X86_64_SHA=$sha" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ github.run_number }}
|
tag_name: ${{ github.run_number }}
|
||||||
name: TachiyomiSY
|
name: TachiyomiSY
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ name: Remote Dispatch Action Initiator
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'preview'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
trigger_preview_build:
|
trigger_preview_build:
|
||||||
name: Trigger preview build
|
name: Trigger preview build
|
||||||
if: ${{ github.ref == 'refs/heads/master' }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -16,7 +15,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
- name: Create Tag
|
- name: Create Tag
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
name: Label PRs
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
label_pr:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check PR and Add Label
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const prAuthor = context.payload.pull_request.user.login;
|
||||||
|
|
||||||
|
if (prAuthor === 'weblate') {
|
||||||
|
const labels = ['Translations'];
|
||||||
|
await github.issues.addLabels({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.payload.pull_request.number,
|
||||||
|
labels: labels
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
.gradle
|
.gradle
|
||||||
|
.kotlin
|
||||||
/local.properties
|
/local.properties
|
||||||
/.idea/workspace.xml
|
/.idea/workspace.xml
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
+7
-14
@@ -1,4 +1,4 @@
|
|||||||
Looking to report an issue/bug or make a feature request? Please refer to the [README file](https://github.com/tachiyomiorg/tachiyomi#issues-feature-requests-and-contributing).
|
Looking to report an issue/bug or make a feature request? Please refer to the [README file](/README.md#issues-feature-requests-and-contributing).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ Thanks for your interest in contributing to Tachiyomi!
|
|||||||
|
|
||||||
Pull requests are welcome!
|
Pull requests are welcome!
|
||||||
|
|
||||||
If you're interested in taking on [an open issue](https://github.com/tachiyomiorg/tachiyomi/issues), please comment on it so others are aware.
|
If you're interested in taking on [an open issue](https://github.com/jobobby04/TachiyomiSY/issues), please comment on it so others are aware.
|
||||||
You do not need to ask for permission nor an assignment.
|
You do not need to ask for permission nor an assignment.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
@@ -24,34 +24,27 @@ Before you start, please note that the ability to use following technologies is
|
|||||||
- [Android Studio](https://developer.android.com/studio)
|
- [Android Studio](https://developer.android.com/studio)
|
||||||
- Emulator or phone with developer options enabled to test changes.
|
- Emulator or phone with developer options enabled to test changes.
|
||||||
|
|
||||||
## Linting
|
|
||||||
|
|
||||||
To auto-fix some linting errors, run the `ktlintFormat` Gradle task.
|
|
||||||
|
|
||||||
## Getting help
|
## Getting help
|
||||||
|
|
||||||
- Join [the Discord server](https://discord.gg/tachiyomi) for online help and to ask questions while developing.
|
- Join [the Discord server](https://discord.gg/mihon) for online help and to ask questions while developing.
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
|
|
||||||
Translations are done externally via Weblate. See [our website](https://tachiyomi.org/docs/contribute#translation) for more details.
|
Translations are done externally via Weblate. See [our website](https://mihon.app/docs/contribute#translation) for more details.
|
||||||
|
|
||||||
|
|
||||||
# Forks
|
# Forks
|
||||||
|
|
||||||
Forks are allowed so long as they abide by [the project's LICENSE](https://github.com/tachiyomiorg/tachiyomi/blob/master/LICENSE).
|
Forks are allowed so long as they abide by [the project's LICENSE](/LICENSE).
|
||||||
|
|
||||||
When creating a fork, remember to:
|
When creating a fork, remember to:
|
||||||
|
|
||||||
- To avoid confusion with the main app:
|
- To avoid confusion with the main app:
|
||||||
- Change the app name
|
- Change the app name
|
||||||
- Change the app icon
|
- Change the app icon
|
||||||
- Change or disable the [app update checker](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt)
|
- Change or disable the [app update checker](/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt)
|
||||||
- To avoid installation conflicts:
|
- To avoid installation conflicts:
|
||||||
- Change the `applicationId` in [`build.gradle.kts`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts)
|
- Change the `applicationId` in [`build.gradle.kts`](/app/build.gradle.kts)
|
||||||
- To avoid having your data polluting the main app's analytics and crash report services:
|
|
||||||
- If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/standard/google-services.json) with your own
|
|
||||||
- If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts) with your own
|
|
||||||
|
|
||||||
|
|
||||||
### Supporting Cloud Sync - Google Drive Implementation
|
### Supporting Cloud Sync - Google Drive Implementation
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Features of Mihon(original) include:
|
|||||||
* Online reading from a variety of sources
|
* Online reading from a variety of sources
|
||||||
* Local reading of downloaded content
|
* Local reading of downloaded content
|
||||||
* A configurable reader with multiple viewers, reading directions and other settings.
|
* A configurable reader with multiple viewers, reading directions and other settings.
|
||||||
* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.io/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), and [Bangumi](https://bgm.tv/) support
|
* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.app/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), and [Bangumi](https://bgm.tv/) support
|
||||||
* Categories to organize your library
|
* Categories to organize your library
|
||||||
* Light and dark themes
|
* Light and dark themes
|
||||||
* Schedule updating your library for new chapters
|
* Schedule updating your library for new chapters
|
||||||
@@ -67,13 +67,22 @@ Get the app from our [releases page](https://github.com/jobobby04/tachiyomisy/re
|
|||||||
|
|
||||||
If you want to try new features before they get to the stable release, you can download the preview version [here](https://github.com/jobobby04/tachiyomisypreview/releases).
|
If you want to try new features before they get to the stable release, you can download the preview version [here](https://github.com/jobobby04/tachiyomisypreview/releases).
|
||||||
|
|
||||||
|
## Translation
|
||||||
|
Feel free to translate the project on [Weblate](https://hosted.weblate.org/projects/mihon/tachiyomisy/)
|
||||||
|
|
||||||
|
<details><summary>Translation Progress</summary>
|
||||||
|
<a href="https://hosted.weblate.org/engage/mihon/">
|
||||||
|
<img src="https://hosted.weblate.org/widgets/mihon/-/tachiyomisy/multi-auto.svg" alt="Translation status" />
|
||||||
|
</a>
|
||||||
|
</details>
|
||||||
|
|
||||||
## Issues, Feature Requests and Contributing
|
## Issues, Feature Requests and Contributing
|
||||||
|
|
||||||
Please make sure to read the full guidelines. Your issue may be closed without warning if you do not.
|
Please make sure to read the full guidelines. Your issue may be closed without warning if you do not.
|
||||||
|
|
||||||
<details><summary>Issues</summary>
|
<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).**
|
1. **Before reporting a new issue, take a look at the [FAQ](https://mihon.app/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/mihon)
|
2. If you are unsure, ask here: [](https://discord.gg/mihon)
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@@ -88,9 +97,7 @@ Please make sure to read the full guidelines. Your issue may be closed without w
|
|||||||
* If it could be device-dependent, try reproducing on another device (if possible)
|
* If it could be device-dependent, try reproducing on another device (if possible)
|
||||||
* Don't group unrelated requests into one issue
|
* Don't group unrelated requests into one issue
|
||||||
|
|
||||||
DO: https://github.com/tachiyomiorg/tachiyomi/issues/24 https://github.com/tachiyomiorg/tachiyomi/issues/71
|
Use the [issue forms](https://github.com/jobobby04/TachiyomiSY/issues/new/choose) to submit a bug.
|
||||||
|
|
||||||
DON'T: https://github.com/tachiyomiorg/tachiyomi/issues/75
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
+12
-15
@@ -21,7 +21,7 @@ if (gradle.startParameter.taskRequests.toString().contains("Standard")) {
|
|||||||
|
|
||||||
// shortcutHelper.setFilePath("./shortcuts.xml")
|
// shortcutHelper.setFilePath("./shortcuts.xml")
|
||||||
|
|
||||||
val SUPPORTED_ABIS = setOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
val supportedAbis = setOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "eu.kanade.tachiyomi"
|
namespace = "eu.kanade.tachiyomi"
|
||||||
@@ -29,7 +29,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "eu.kanade.tachiyomi.sy"
|
applicationId = "eu.kanade.tachiyomi.sy"
|
||||||
|
|
||||||
versionCode = 67
|
versionCode = 69
|
||||||
versionName = "1.10.5"
|
versionName = "1.10.5"
|
||||||
|
|
||||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||||
@@ -38,7 +38,7 @@ android {
|
|||||||
buildConfigField("boolean", "INCLUDE_UPDATER", "false")
|
buildConfigField("boolean", "INCLUDE_UPDATER", "false")
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters += SUPPORTED_ABIS
|
abiFilters += supportedAbis
|
||||||
}
|
}
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ android {
|
|||||||
abi {
|
abi {
|
||||||
isEnable = true
|
isEnable = true
|
||||||
reset()
|
reset()
|
||||||
include(*SUPPORTED_ABIS.toTypedArray())
|
include(*supportedAbis.toTypedArray())
|
||||||
isUniversalApk = true
|
isUniversalApk = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,6 @@ dependencies {
|
|||||||
implementation(compose.activity)
|
implementation(compose.activity)
|
||||||
implementation(compose.foundation)
|
implementation(compose.foundation)
|
||||||
implementation(compose.material3.core)
|
implementation(compose.material3.core)
|
||||||
implementation(compose.material.core)
|
|
||||||
implementation(compose.material.icons)
|
implementation(compose.material.icons)
|
||||||
implementation(compose.animation)
|
implementation(compose.animation)
|
||||||
implementation(compose.animation.graphics)
|
implementation(compose.animation.graphics)
|
||||||
@@ -164,12 +163,14 @@ dependencies {
|
|||||||
implementation(compose.ui.util)
|
implementation(compose.ui.util)
|
||||||
implementation(compose.accompanist.systemuicontroller)
|
implementation(compose.accompanist.systemuicontroller)
|
||||||
|
|
||||||
|
implementation(androidx.interpolator)
|
||||||
|
|
||||||
implementation(androidx.paging.runtime)
|
implementation(androidx.paging.runtime)
|
||||||
implementation(androidx.paging.compose)
|
implementation(androidx.paging.compose)
|
||||||
|
|
||||||
implementation(libs.bundles.sqlite)
|
implementation(libs.bundles.sqlite)
|
||||||
// SY -->
|
// SY -->
|
||||||
implementation(libs.sqlcipher)
|
implementation(sylibs.sqlcipher)
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
implementation(kotlinx.reflect)
|
implementation(kotlinx.reflect)
|
||||||
@@ -211,10 +212,6 @@ dependencies {
|
|||||||
// Disk
|
// Disk
|
||||||
implementation(libs.disklrucache)
|
implementation(libs.disklrucache)
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.bundles.archive)
|
|
||||||
// SY -->
|
|
||||||
implementation(libs.zip4j)
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation(libs.preferencektx)
|
implementation(libs.preferencektx)
|
||||||
@@ -246,10 +243,6 @@ dependencies {
|
|||||||
implementation(libs.compose.webview)
|
implementation(libs.compose.webview)
|
||||||
implementation(libs.compose.grid)
|
implementation(libs.compose.grid)
|
||||||
|
|
||||||
|
|
||||||
implementation(libs.google.api.services.drive)
|
|
||||||
implementation(libs.google.api.client.oauth)
|
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
implementation(libs.logcat)
|
implementation(libs.logcat)
|
||||||
|
|
||||||
@@ -282,6 +275,10 @@ dependencies {
|
|||||||
// RatingBar (SY)
|
// RatingBar (SY)
|
||||||
implementation(sylibs.ratingbar)
|
implementation(sylibs.ratingbar)
|
||||||
implementation(sylibs.composeRatingbar)
|
implementation(sylibs.composeRatingbar)
|
||||||
|
|
||||||
|
// Google drive
|
||||||
|
implementation(sylibs.google.api.services.drive)
|
||||||
|
implementation(sylibs.google.api.client.oauth)
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents {
|
androidComponents {
|
||||||
@@ -303,7 +300,7 @@ androidComponents {
|
|||||||
tasks {
|
tasks {
|
||||||
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers)
|
// See https://kotlinlang.org/docs/reference/experimental.html#experimental-status-of-experimental-api(-markers)
|
||||||
withType<KotlinCompile> {
|
withType<KotlinCompile> {
|
||||||
kotlinOptions.freeCompilerArgs += listOf(
|
compilerOptions.freeCompilerArgs.addAll(
|
||||||
"-Xcontext-receivers",
|
"-Xcontext-receivers",
|
||||||
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||||
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
|
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
|
||||||
|
|||||||
Vendored
+4
-3
@@ -47,6 +47,10 @@
|
|||||||
-dontnote rx.internal.util.PlatformDependent
|
-dontnote rx.internal.util.PlatformDependent
|
||||||
##---------------End: proguard configuration for RxJava 1.x ----------
|
##---------------End: proguard configuration for RxJava 1.x ----------
|
||||||
|
|
||||||
|
##---------------Begin: proguard configuration for okhttp ----------
|
||||||
|
-keepclasseswithmembers class okhttp3.MultipartBody$Builder { *; }
|
||||||
|
##---------------End: proguard configuration for okhttp ----------
|
||||||
|
|
||||||
##---------------Begin: proguard configuration for kotlinx.serialization ----------
|
##---------------Begin: proguard configuration for kotlinx.serialization ----------
|
||||||
-keepattributes *Annotation*, InnerClasses
|
-keepattributes *Annotation*, InnerClasses
|
||||||
-dontnote kotlinx.serialization.** # core serialization annotations
|
-dontnote kotlinx.serialization.** # core serialization annotations
|
||||||
@@ -123,9 +127,6 @@
|
|||||||
# XmlUtil
|
# XmlUtil
|
||||||
-keep public enum nl.adaptivity.xmlutil.EventType { *; }
|
-keep public enum nl.adaptivity.xmlutil.EventType { *; }
|
||||||
|
|
||||||
# Apache Commons Compress
|
|
||||||
-keep class * extends org.apache.commons.compress.archivers.zip.ZipExtraField { <init>(); }
|
|
||||||
|
|
||||||
# Firebase
|
# Firebase
|
||||||
-keep class com.google.firebase.installations.** { *; }
|
-keep class com.google.firebase.installations.** { *; }
|
||||||
-keep interface com.google.firebase.installations.** { *; }
|
-keep interface com.google.firebase.installations.** { *; }
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import eu.kanade.domain.track.interactor.RefreshTracks
|
|||||||
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
|
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
|
||||||
import eu.kanade.domain.track.interactor.TrackChapter
|
import eu.kanade.domain.track.interactor.TrackChapter
|
||||||
import mihon.data.repository.ExtensionRepoRepositoryImpl
|
import mihon.data.repository.ExtensionRepoRepositoryImpl
|
||||||
|
import mihon.domain.chapter.interactor.FilterChaptersForDownload
|
||||||
import mihon.domain.extensionrepo.interactor.CreateExtensionRepo
|
import mihon.domain.extensionrepo.interactor.CreateExtensionRepo
|
||||||
import mihon.domain.extensionrepo.interactor.DeleteExtensionRepo
|
import mihon.domain.extensionrepo.interactor.DeleteExtensionRepo
|
||||||
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
||||||
@@ -152,6 +153,7 @@ class DomainModule : InjektModule {
|
|||||||
addFactory { ShouldUpdateDbChapter() }
|
addFactory { ShouldUpdateDbChapter() }
|
||||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) }
|
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) }
|
||||||
addFactory { GetAvailableScanlators(get()) }
|
addFactory { GetAvailableScanlators(get()) }
|
||||||
|
addFactory { FilterChaptersForDownload(get(), get(), get(), get()) }
|
||||||
|
|
||||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||||
addFactory { GetHistory(get()) }
|
addFactory { GetHistory(get()) }
|
||||||
|
|||||||
@@ -32,10 +32,11 @@ class GetEnabledSources(
|
|||||||
) { a, b, c -> Triple(a, b, c) },
|
) { a, b, c -> Triple(a, b, c) },
|
||||||
// SY <--
|
// SY <--
|
||||||
repository.getSources(),
|
repository.getSources(),
|
||||||
) { pinnedSourceIds,
|
) {
|
||||||
(enabledLanguages, disabledSources, lastUsedSource),
|
pinnedSourceIds,
|
||||||
(excludedFromDataSaver, sourcesInCategories, sourceCategoriesFilter),
|
(enabledLanguages, disabledSources, lastUsedSource),
|
||||||
sources,
|
(excludedFromDataSaver, sourcesInCategories, sourceCategoriesFilter),
|
||||||
|
sources,
|
||||||
->
|
->
|
||||||
|
|
||||||
val sourcesAndCategories = sourcesInCategories.map {
|
val sourcesAndCategories = sourcesInCategories.map {
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ class SourcePreferences(
|
|||||||
emptySet(),
|
emptySet(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun globalSearchFilterState() = preferenceStore.getBoolean(
|
||||||
|
Preference.appStateKey("has_filters_toggle_state"),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
fun enableSourceBlacklist() = preferenceStore.getBoolean("eh_enable_source_blacklist", true)
|
fun enableSourceBlacklist() = preferenceStore.getBoolean("eh_enable_source_blacklist", true)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class SyncPreferences(
|
|||||||
fun clientAPIKey() = preferenceStore.getString("sync_client_api_key", "")
|
fun clientAPIKey() = preferenceStore.getString("sync_client_api_key", "")
|
||||||
fun lastSyncTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_sync_timestamp"), 0L)
|
fun lastSyncTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_sync_timestamp"), 0L)
|
||||||
|
|
||||||
fun lastSyncEtag() = preferenceStore.getString("sync_etag", "")
|
fun lastSyncEtag() = preferenceStore.getString("sync_etag", "")
|
||||||
|
|
||||||
fun syncInterval() = preferenceStore.getInt("sync_interval", 0)
|
fun syncInterval() = preferenceStore.getInt("sync_interval", 0)
|
||||||
fun syncService() = preferenceStore.getInt("sync_service", 0)
|
fun syncService() = preferenceStore.getInt("sync_service", 0)
|
||||||
@@ -29,7 +29,7 @@ class SyncPreferences(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun uniqueDeviceID(): String {
|
fun uniqueDeviceID(): String {
|
||||||
val uniqueIDPreference = preferenceStore.getString("unique_device_id", "")
|
val uniqueIDPreference = preferenceStore.getString(Preference.appStateKey("unique_device_id"), "")
|
||||||
|
|
||||||
// Retrieve the current value of the preference
|
// Retrieve the current value of the preference
|
||||||
var uniqueID = uniqueIDPreference.get()
|
var uniqueID = uniqueIDPreference.get()
|
||||||
@@ -53,12 +53,14 @@ class SyncPreferences(
|
|||||||
tracking = preferenceStore.getBoolean("tracking", true).get(),
|
tracking = preferenceStore.getBoolean("tracking", true).get(),
|
||||||
history = preferenceStore.getBoolean("history", true).get(),
|
history = preferenceStore.getBoolean("history", true).get(),
|
||||||
appSettings = preferenceStore.getBoolean("appSettings", true).get(),
|
appSettings = preferenceStore.getBoolean("appSettings", true).get(),
|
||||||
|
extensionRepoSettings = preferenceStore.getBoolean("extensionRepoSettings", true).get(),
|
||||||
sourceSettings = preferenceStore.getBoolean("sourceSettings", true).get(),
|
sourceSettings = preferenceStore.getBoolean("sourceSettings", true).get(),
|
||||||
privateSettings = preferenceStore.getBoolean("privateSettings", true).get(),
|
privateSettings = preferenceStore.getBoolean("privateSettings", true).get(),
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = preferenceStore.getBoolean("customInfo", true).get(),
|
customInfo = preferenceStore.getBoolean("customInfo", true).get(),
|
||||||
readEntries = preferenceStore.getBoolean("readEntries", true).get()
|
readEntries = preferenceStore.getBoolean("readEntries", true).get(),
|
||||||
|
savedSearches = preferenceStore.getBoolean("savedSearches", true).get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -70,12 +72,14 @@ class SyncPreferences(
|
|||||||
preferenceStore.getBoolean("tracking", true).set(syncSettings.tracking)
|
preferenceStore.getBoolean("tracking", true).set(syncSettings.tracking)
|
||||||
preferenceStore.getBoolean("history", true).set(syncSettings.history)
|
preferenceStore.getBoolean("history", true).set(syncSettings.history)
|
||||||
preferenceStore.getBoolean("appSettings", true).set(syncSettings.appSettings)
|
preferenceStore.getBoolean("appSettings", true).set(syncSettings.appSettings)
|
||||||
|
preferenceStore.getBoolean("extensionRepoSettings", true).set(syncSettings.extensionRepoSettings)
|
||||||
preferenceStore.getBoolean("sourceSettings", true).set(syncSettings.sourceSettings)
|
preferenceStore.getBoolean("sourceSettings", true).set(syncSettings.sourceSettings)
|
||||||
preferenceStore.getBoolean("privateSettings", true).set(syncSettings.privateSettings)
|
preferenceStore.getBoolean("privateSettings", true).set(syncSettings.privateSettings)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
preferenceStore.getBoolean("customInfo", true).set(syncSettings.customInfo)
|
preferenceStore.getBoolean("customInfo", true).set(syncSettings.customInfo)
|
||||||
preferenceStore.getBoolean("readEntries", true).set(syncSettings.readEntries)
|
preferenceStore.getBoolean("readEntries", true).set(syncSettings.readEntries)
|
||||||
|
preferenceStore.getBoolean("savedSearches", true).set(syncSettings.savedSearches)
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ data class SyncSettings(
|
|||||||
val tracking: Boolean = true,
|
val tracking: Boolean = true,
|
||||||
val history: Boolean = true,
|
val history: Boolean = true,
|
||||||
val appSettings: Boolean = true,
|
val appSettings: Boolean = true,
|
||||||
|
val extensionRepoSettings: Boolean = true,
|
||||||
val sourceSettings: Boolean = true,
|
val sourceSettings: Boolean = true,
|
||||||
val privateSettings: Boolean = false,
|
val privateSettings: Boolean = false,
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val customInfo: Boolean = true,
|
val customInfo: Boolean = true,
|
||||||
val readEntries: Boolean = true
|
val readEntries: Boolean = true,
|
||||||
|
val savedSearches: Boolean = true,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,12 +18,20 @@ class UiPreferences(
|
|||||||
|
|
||||||
fun themeMode() = preferenceStore.getEnum(
|
fun themeMode() = preferenceStore.getEnum(
|
||||||
"pref_theme_mode_key",
|
"pref_theme_mode_key",
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ThemeMode.SYSTEM } else { ThemeMode.LIGHT },
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
ThemeMode.SYSTEM
|
||||||
|
} else {
|
||||||
|
ThemeMode.LIGHT
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun appTheme() = preferenceStore.getEnum(
|
fun appTheme() = preferenceStore.getEnum(
|
||||||
"pref_app_theme",
|
"pref_app_theme",
|
||||||
if (DeviceUtil.isDynamicColorAvailable) { AppTheme.MONET } else { AppTheme.DEFAULT },
|
if (DeviceUtil.isDynamicColorAvailable) {
|
||||||
|
AppTheme.MONET
|
||||||
|
} else {
|
||||||
|
AppTheme.DEFAULT
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
|
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ private fun DetailsHeader(
|
|||||||
Extension name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
|
Extension name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
|
||||||
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
|
||||||
NSFW: ${extension.isNsfw}
|
NSFW: ${extension.isNsfw}
|
||||||
""".trimIndent()
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (extension is Extension.Installed) {
|
if (extension is Extension.Installed) {
|
||||||
@@ -251,7 +251,7 @@ private fun DetailsHeader(
|
|||||||
Obsolete: ${extension.isObsolete}
|
Obsolete: ${extension.isObsolete}
|
||||||
Shared: ${extension.isShared}
|
Shared: ${extension.isShared}
|
||||||
Repository: ${extension.repoUrl}
|
Repository: ${extension.repoUrl}
|
||||||
""".trimIndent()
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,7 +219,9 @@ private fun ExtensionContent(
|
|||||||
when (it) {
|
when (it) {
|
||||||
is Extension.Available -> onInstallExtension(it)
|
is Extension.Available -> onInstallExtension(it)
|
||||||
is Extension.Installed -> onOpenExtension(it)
|
is Extension.Installed -> onOpenExtension(it)
|
||||||
is Extension.Untrusted -> { trustState = it }
|
is Extension.Untrusted -> {
|
||||||
|
trustState = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClickItem = onLongClickItem,
|
onLongClickItem = onLongClickItem,
|
||||||
@@ -241,7 +243,9 @@ private fun ExtensionContent(
|
|||||||
onOpenExtension(it)
|
onOpenExtension(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Extension.Untrusted -> { trustState = it }
|
is Extension.Untrusted -> {
|
||||||
|
trustState = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import tachiyomi.i18n.MR
|
|||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
@@ -179,7 +179,7 @@ private fun SourcePinButton(
|
|||||||
MaterialTheme.colorScheme.primary
|
MaterialTheme.colorScheme.primary
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.colorScheme.onBackground.copy(
|
MaterialTheme.colorScheme.onBackground.copy(
|
||||||
alpha = SecondaryItemAlpha,
|
alpha = SECONDARY_ALPHA,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
|
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.animation.togetherWith
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import cafe.adriel.voyager.core.annotation.InternalVoyagerApi
|
import cafe.adriel.voyager.core.annotation.InternalVoyagerApi
|
||||||
@@ -23,7 +21,6 @@ import tachiyomi.presentation.core.components.AdaptiveSheet as AdaptiveSheetImpl
|
|||||||
@Composable
|
@Composable
|
||||||
fun NavigatorAdaptiveSheet(
|
fun NavigatorAdaptiveSheet(
|
||||||
screen: Screen,
|
screen: Screen,
|
||||||
tonalElevation: Dp = 1.dp,
|
|
||||||
enableSwipeDismiss: (Navigator) -> Boolean = { true },
|
enableSwipeDismiss: (Navigator) -> Boolean = { true },
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -31,7 +28,6 @@ fun NavigatorAdaptiveSheet(
|
|||||||
screen = screen,
|
screen = screen,
|
||||||
content = { sheetNavigator ->
|
content = { sheetNavigator ->
|
||||||
AdaptiveSheet(
|
AdaptiveSheet(
|
||||||
tonalElevation = tonalElevation,
|
|
||||||
enableSwipeDismiss = enableSwipeDismiss(sheetNavigator),
|
enableSwipeDismiss = enableSwipeDismiss(sheetNavigator),
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
) {
|
) {
|
||||||
@@ -73,7 +69,6 @@ fun NavigatorAdaptiveSheet(
|
|||||||
fun AdaptiveSheet(
|
fun AdaptiveSheet(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
tonalElevation: Dp = 1.dp,
|
|
||||||
enableSwipeDismiss: Boolean = true,
|
enableSwipeDismiss: Boolean = true,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -86,7 +81,6 @@ fun AdaptiveSheet(
|
|||||||
AdaptiveSheetImpl(
|
AdaptiveSheetImpl(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
isTabletUi = isTabletUi,
|
isTabletUi = isTabletUi,
|
||||||
tonalElevation = tonalElevation,
|
|
||||||
enableSwipeDismiss = enableSwipeDismiss,
|
enableSwipeDismiss = enableSwipeDismiss,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.TextFieldDefaults
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
||||||
import androidx.compose.material.icons.outlined.Close
|
import androidx.compose.material.icons.outlined.Close
|
||||||
@@ -21,6 +20,7 @@ import androidx.compose.material3.LocalContentColor
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.PlainTooltip
|
import androidx.compose.material3.PlainTooltip
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.material3.TooltipBox
|
import androidx.compose.material3.TooltipBox
|
||||||
import androidx.compose.material3.TooltipDefaults
|
import androidx.compose.material3.TooltipDefaults
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
@@ -312,7 +312,7 @@ fun SearchToolbar(
|
|||||||
visualTransformation = visualTransformation,
|
visualTransformation = visualTransformation,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
decorationBox = { innerTextField ->
|
decorationBox = { innerTextField ->
|
||||||
TextFieldDefaults.TextFieldDecorationBox(
|
TextFieldDefaults.DecorationBox(
|
||||||
value = searchQuery,
|
value = searchQuery,
|
||||||
innerTextField = innerTextField,
|
innerTextField = innerTextField,
|
||||||
enabled = true,
|
enabled = true,
|
||||||
@@ -331,6 +331,7 @@ fun SearchToolbar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
container = {},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ fun TabbedDialog(
|
|||||||
PrimaryTabRow(
|
PrimaryTabRow(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
divider = {},
|
divider = {},
|
||||||
) {
|
) {
|
||||||
tabTitles.fastForEachIndexed { index, tab ->
|
tabTitles.fastForEachIndexed { index, tab ->
|
||||||
@@ -78,7 +79,7 @@ fun TabbedDialog(
|
|||||||
modifier = Modifier.animateContentSize(),
|
modifier = Modifier.animateContentSize(),
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
verticalAlignment = Alignment.Top,
|
verticalAlignment = Alignment.Top,
|
||||||
pageContent = { page -> content(page) }
|
pageContent = { page -> content(page) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ private fun ColumnScope.FilterPage(
|
|||||||
)
|
)
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
val trackers = remember { screenModel.trackers }
|
val trackers by screenModel.trackersFlow.collectAsState()
|
||||||
when (trackers.size) {
|
when (trackers.size) {
|
||||||
0 -> {
|
0 -> {
|
||||||
// No trackers
|
// No trackers
|
||||||
@@ -188,6 +188,7 @@ private fun ColumnScope.SortPage(
|
|||||||
category: Category?,
|
category: Category?,
|
||||||
screenModel: LibrarySettingsScreenModel,
|
screenModel: LibrarySettingsScreenModel,
|
||||||
) {
|
) {
|
||||||
|
val trackers by screenModel.trackersFlow.collectAsState()
|
||||||
// SY -->
|
// SY -->
|
||||||
val globalSortMode by screenModel.libraryPreferences.sortingMode().collectAsState()
|
val globalSortMode by screenModel.libraryPreferences.sortingMode().collectAsState()
|
||||||
val sortingMode = if (screenModel.grouping == LibraryGroup.BY_DEFAULT) {
|
val sortingMode = if (screenModel.grouping == LibraryGroup.BY_DEFAULT) {
|
||||||
@@ -206,12 +207,11 @@ private fun ColumnScope.SortPage(
|
|||||||
}.collectAsState(initial = screenModel.libraryPreferences.sortTagsForLibrary().get().isNotEmpty())
|
}.collectAsState(initial = screenModel.libraryPreferences.sortTagsForLibrary().get().isNotEmpty())
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
val trackerSortOption =
|
val trackerSortOption = if (trackers.isEmpty()) {
|
||||||
if (screenModel.trackers.isEmpty()) {
|
emptyList()
|
||||||
emptyList()
|
} else {
|
||||||
} else {
|
listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
|
||||||
listOf(MR.strings.action_sort_tracker_score to LibrarySort.Type.TrackerMean)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,
|
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,
|
||||||
@@ -346,12 +346,13 @@ private fun ColumnScope.GroupPage(
|
|||||||
screenModel: LibrarySettingsScreenModel,
|
screenModel: LibrarySettingsScreenModel,
|
||||||
hasCategories: Boolean,
|
hasCategories: Boolean,
|
||||||
) {
|
) {
|
||||||
val groups = remember(hasCategories, screenModel.trackers) {
|
val trackers by screenModel.trackersFlow.collectAsState()
|
||||||
|
val groups = remember(hasCategories, trackers) {
|
||||||
buildList {
|
buildList {
|
||||||
add(LibraryGroup.BY_DEFAULT)
|
add(LibraryGroup.BY_DEFAULT)
|
||||||
add(LibraryGroup.BY_SOURCE)
|
add(LibraryGroup.BY_SOURCE)
|
||||||
add(LibraryGroup.BY_STATUS)
|
add(LibraryGroup.BY_STATUS)
|
||||||
if (screenModel.trackers.isNotEmpty()) {
|
if (trackers.isNotEmpty()) {
|
||||||
add(LibraryGroup.BY_TRACK_STATUS)
|
add(LibraryGroup.BY_TRACK_STATUS)
|
||||||
}
|
}
|
||||||
if (hasCategories) {
|
if (hasCategories) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.graphics.Shadow
|
import androidx.compose.ui.graphics.Shadow
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import eu.kanade.presentation.manga.components.MangaCover
|
import eu.kanade.presentation.manga.components.MangaCover
|
||||||
@@ -42,19 +43,26 @@ import tachiyomi.i18n.MR
|
|||||||
import tachiyomi.presentation.core.components.BadgeGroup
|
import tachiyomi.presentation.core.components.BadgeGroup
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.selectedBackground
|
import tachiyomi.presentation.core.util.selectedBackground
|
||||||
|
import tachiyomi.domain.manga.model.MangaCover as MangaCoverModel
|
||||||
|
|
||||||
object CommonMangaItemDefaults {
|
object CommonMangaItemDefaults {
|
||||||
val GridHorizontalSpacer = 4.dp
|
val GridHorizontalSpacer = 4.dp
|
||||||
val GridVerticalSpacer = 4.dp
|
val GridVerticalSpacer = 4.dp
|
||||||
|
|
||||||
|
@Suppress("ConstPropertyName")
|
||||||
const val BrowseFavoriteCoverAlpha = 0.34f
|
const val BrowseFavoriteCoverAlpha = 0.34f
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ContinueReadingButtonSize = 28.dp
|
private val ContinueReadingButtonSizeSmall = 28.dp
|
||||||
|
private val ContinueReadingButtonSizeLarge = 32.dp
|
||||||
|
|
||||||
|
private val ContinueReadingButtonIconSizeSmall = 16.dp
|
||||||
|
private val ContinueReadingButtonIconSizeLarge = 20.dp
|
||||||
|
|
||||||
private val ContinueReadingButtonGridPadding = 6.dp
|
private val ContinueReadingButtonGridPadding = 6.dp
|
||||||
private val ContinueReadingButtonListSpacing = 8.dp
|
private val ContinueReadingButtonListSpacing = 8.dp
|
||||||
|
|
||||||
private const val GridSelectedCoverAlpha = 0.76f
|
private const val GRID_SELECTED_COVER_ALPHA = 0.76f
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout of grid list item with title overlaying the cover.
|
* Layout of grid list item with title overlaying the cover.
|
||||||
@@ -62,7 +70,7 @@ private const val GridSelectedCoverAlpha = 0.76f
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun MangaCompactGridItem(
|
fun MangaCompactGridItem(
|
||||||
coverData: tachiyomi.domain.manga.model.MangaCover,
|
coverData: MangaCoverModel,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
isSelected: Boolean = false,
|
isSelected: Boolean = false,
|
||||||
@@ -82,7 +90,7 @@ fun MangaCompactGridItem(
|
|||||||
MangaCover.Book(
|
MangaCover.Book(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha),
|
.alpha(if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha),
|
||||||
data = coverData,
|
data = coverData,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -96,10 +104,12 @@ fun MangaCompactGridItem(
|
|||||||
)
|
)
|
||||||
} else if (onClickContinueReading != null) {
|
} else if (onClickContinueReading != null) {
|
||||||
ContinueReadingButton(
|
ContinueReadingButton(
|
||||||
|
size = ContinueReadingButtonSizeLarge,
|
||||||
|
iconSize = ContinueReadingButtonIconSizeLarge,
|
||||||
|
onClick = onClickContinueReading,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(ContinueReadingButtonGridPadding)
|
.padding(ContinueReadingButtonGridPadding)
|
||||||
.align(Alignment.BottomEnd),
|
.align(Alignment.BottomEnd),
|
||||||
onClickContinueReading = onClickContinueReading,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -148,11 +158,13 @@ private fun BoxScope.CoverTextOverlay(
|
|||||||
)
|
)
|
||||||
if (onClickContinueReading != null) {
|
if (onClickContinueReading != null) {
|
||||||
ContinueReadingButton(
|
ContinueReadingButton(
|
||||||
|
size = ContinueReadingButtonSizeSmall,
|
||||||
|
iconSize = ContinueReadingButtonIconSizeSmall,
|
||||||
|
onClick = onClickContinueReading,
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
end = ContinueReadingButtonGridPadding,
|
end = ContinueReadingButtonGridPadding,
|
||||||
bottom = ContinueReadingButtonGridPadding,
|
bottom = ContinueReadingButtonGridPadding,
|
||||||
),
|
),
|
||||||
onClickContinueReading = onClickContinueReading,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,7 +175,7 @@ private fun BoxScope.CoverTextOverlay(
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun MangaComfortableGridItem(
|
fun MangaComfortableGridItem(
|
||||||
coverData: tachiyomi.domain.manga.model.MangaCover,
|
coverData: MangaCoverModel,
|
||||||
title: String,
|
title: String,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
@@ -185,7 +197,7 @@ fun MangaComfortableGridItem(
|
|||||||
MangaCover.Book(
|
MangaCover.Book(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.alpha(if (isSelected) GridSelectedCoverAlpha else coverAlpha),
|
.alpha(if (isSelected) GRID_SELECTED_COVER_ALPHA else coverAlpha),
|
||||||
data = coverData,
|
data = coverData,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -194,10 +206,12 @@ fun MangaComfortableGridItem(
|
|||||||
content = {
|
content = {
|
||||||
if (onClickContinueReading != null) {
|
if (onClickContinueReading != null) {
|
||||||
ContinueReadingButton(
|
ContinueReadingButton(
|
||||||
|
size = ContinueReadingButtonSizeLarge,
|
||||||
|
iconSize = ContinueReadingButtonIconSizeLarge,
|
||||||
|
onClick = onClickContinueReading,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(ContinueReadingButtonGridPadding)
|
.padding(ContinueReadingButtonGridPadding)
|
||||||
.align(Alignment.BottomEnd),
|
.align(Alignment.BottomEnd),
|
||||||
onClickContinueReading = onClickContinueReading,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -309,14 +323,14 @@ private fun GridItemSelectable(
|
|||||||
private fun Modifier.selectedOutline(
|
private fun Modifier.selectedOutline(
|
||||||
isSelected: Boolean,
|
isSelected: Boolean,
|
||||||
color: Color,
|
color: Color,
|
||||||
) = this then drawBehind { if (isSelected) drawRect(color = color) }
|
) = drawBehind { if (isSelected) drawRect(color = color) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout of list item.
|
* Layout of list item.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun MangaListItem(
|
fun MangaListItem(
|
||||||
coverData: tachiyomi.domain.manga.model.MangaCover,
|
coverData: MangaCoverModel,
|
||||||
title: String,
|
title: String,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: () -> Unit,
|
onLongClick: () -> Unit,
|
||||||
@@ -354,8 +368,10 @@ fun MangaListItem(
|
|||||||
BadgeGroup(content = badge)
|
BadgeGroup(content = badge)
|
||||||
if (onClickContinueReading != null) {
|
if (onClickContinueReading != null) {
|
||||||
ContinueReadingButton(
|
ContinueReadingButton(
|
||||||
|
size = ContinueReadingButtonSizeSmall,
|
||||||
|
iconSize = ContinueReadingButtonIconSizeSmall,
|
||||||
|
onClick = onClickContinueReading,
|
||||||
modifier = Modifier.padding(start = ContinueReadingButtonListSpacing),
|
modifier = Modifier.padding(start = ContinueReadingButtonListSpacing),
|
||||||
onClickContinueReading = onClickContinueReading,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,23 +379,25 @@ fun MangaListItem(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContinueReadingButton(
|
private fun ContinueReadingButton(
|
||||||
|
size: Dp,
|
||||||
|
iconSize: Dp,
|
||||||
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClickContinueReading: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
FilledIconButton(
|
FilledIconButton(
|
||||||
onClick = onClickContinueReading,
|
onClick = onClick,
|
||||||
modifier = Modifier.size(ContinueReadingButtonSize),
|
|
||||||
shape = MaterialTheme.shapes.small,
|
shape = MaterialTheme.shapes.small,
|
||||||
colors = IconButtonDefaults.filledIconButtonColors(
|
colors = IconButtonDefaults.filledIconButtonColors(
|
||||||
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.9f),
|
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.9f),
|
||||||
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
|
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
|
||||||
),
|
),
|
||||||
|
modifier = Modifier.size(size),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.PlayArrow,
|
imageVector = Icons.Filled.PlayArrow,
|
||||||
contentDescription = stringResource(MR.strings.action_resume),
|
contentDescription = stringResource(MR.strings.action_resume),
|
||||||
modifier = Modifier.size(16.dp),
|
modifier = Modifier.size(iconSize),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import eu.kanade.tachiyomi.source.online.english.Pururin
|
|||||||
import eu.kanade.tachiyomi.source.online.english.Tsumino
|
import eu.kanade.tachiyomi.source.online.english.Tsumino
|
||||||
import eu.kanade.tachiyomi.ui.manga.ChapterList
|
import eu.kanade.tachiyomi.ui.manga.ChapterList
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
|
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MergedMangaData
|
||||||
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
|
import eu.kanade.tachiyomi.ui.manga.PagePreviewState
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import exh.metadata.MetadataUtil
|
import exh.metadata.MetadataUtil
|
||||||
@@ -578,6 +579,7 @@ private fun MangaScreenSmallImpl(
|
|||||||
|
|
||||||
sharedChapterItems(
|
sharedChapterItems(
|
||||||
manga = state.manga,
|
manga = state.manga,
|
||||||
|
mergedData = state.mergedData,
|
||||||
chapters = listItem,
|
chapters = listItem,
|
||||||
isAnyChapterSelected = chapters.fastAny { it.selected },
|
isAnyChapterSelected = chapters.fastAny { it.selected },
|
||||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||||
@@ -880,6 +882,7 @@ fun MangaScreenLargeImpl(
|
|||||||
|
|
||||||
sharedChapterItems(
|
sharedChapterItems(
|
||||||
manga = state.manga,
|
manga = state.manga,
|
||||||
|
mergedData = state.mergedData,
|
||||||
chapters = listItem,
|
chapters = listItem,
|
||||||
isAnyChapterSelected = chapters.fastAny { it.selected },
|
isAnyChapterSelected = chapters.fastAny { it.selected },
|
||||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||||
@@ -944,6 +947,7 @@ private fun SharedMangaBottomActionMenu(
|
|||||||
|
|
||||||
private fun LazyListScope.sharedChapterItems(
|
private fun LazyListScope.sharedChapterItems(
|
||||||
manga: Manga,
|
manga: Manga,
|
||||||
|
mergedData: MergedMangaData?,
|
||||||
chapters: List<ChapterList>,
|
chapters: List<ChapterList>,
|
||||||
isAnyChapterSelected: Boolean,
|
isAnyChapterSelected: Boolean,
|
||||||
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
||||||
@@ -995,7 +999,9 @@ private fun LazyListScope.sharedChapterItems(
|
|||||||
// SY <--
|
// SY <--
|
||||||
},
|
},
|
||||||
readProgress = item.chapter.lastPageRead
|
readProgress = item.chapter.lastPageRead
|
||||||
.takeIf { /* SY --> */(!item.chapter.read || alwaysShowReadingProgress)/* SY <-- */ && it > 0L }
|
.takeIf {
|
||||||
|
/* SY --> */(!item.chapter.read || alwaysShowReadingProgress)/* SY <-- */ && it > 0L
|
||||||
|
}
|
||||||
?.let {
|
?.let {
|
||||||
stringResource(
|
stringResource(
|
||||||
MR.strings.chapter_progress,
|
MR.strings.chapter_progress,
|
||||||
@@ -1011,7 +1017,8 @@ private fun LazyListScope.sharedChapterItems(
|
|||||||
read = item.chapter.read,
|
read = item.chapter.read,
|
||||||
bookmark = item.chapter.bookmark,
|
bookmark = item.chapter.bookmark,
|
||||||
selected = item.selected,
|
selected = item.selected,
|
||||||
downloadIndicatorEnabled = !isAnyChapterSelected && !manga.isLocal(),
|
downloadIndicatorEnabled =
|
||||||
|
!isAnyChapterSelected && !(mergedData?.manga?.get(item.chapter.mangaId) ?: manga).isLocal(),
|
||||||
downloadStateProvider = { item.downloadState },
|
downloadStateProvider = { item.downloadState },
|
||||||
downloadProgressProvider = { item.downloadProgress },
|
downloadProgressProvider = { item.downloadProgress },
|
||||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
@@ -60,6 +60,6 @@ private fun MissingChaptersWarning(count: Int) {
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.error.copy(alpha = SecondaryItemAlpha),
|
color = MaterialTheme.colorScheme.error.copy(alpha = SECONDARY_ALPHA),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ fun MangaBottomActionMenu(
|
|||||||
Surface(
|
Surface(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = MaterialTheme.shapes.large.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
|
shape = MaterialTheme.shapes.large.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
|
||||||
tonalElevation = 3.dp,
|
color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
) {
|
) {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val confirm = remember { mutableStateListOf(false, false, false, false, false, false, false) }
|
val confirm = remember { mutableStateListOf(false, false, false, false, false, false, false) }
|
||||||
@@ -251,7 +251,7 @@ fun LibraryBottomActionMenu(
|
|||||||
Surface(
|
Surface(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = MaterialTheme.shapes.large.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
|
shape = MaterialTheme.shapes.large.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),
|
||||||
tonalElevation = 3.dp,
|
color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
) {
|
) {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val confirm =
|
val confirm =
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
@@ -41,8 +40,8 @@ import eu.kanade.tachiyomi.data.download.model.Download
|
|||||||
import me.saket.swipe.SwipeableActionsBox
|
import me.saket.swipe.SwipeableActionsBox
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences
|
import tachiyomi.domain.library.service.LibraryPreferences
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.selectedBackground
|
import tachiyomi.presentation.core.util.selectedBackground
|
||||||
|
|
||||||
@@ -69,9 +68,6 @@ fun MangaChapterListItem(
|
|||||||
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val textAlpha = if (read) ReadItemAlpha else 1f
|
|
||||||
val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha
|
|
||||||
|
|
||||||
val start = getSwipeAction(
|
val start = getSwipeAction(
|
||||||
action = chapterSwipeStartAction,
|
action = chapterSwipeStartAction,
|
||||||
read = read,
|
read = read,
|
||||||
@@ -136,29 +132,39 @@ fun MangaChapterListItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
onTextLayout = { textHeight = it.size.height },
|
onTextLayout = { textHeight = it.size.height },
|
||||||
|
color = LocalContentColor.current.copy(alpha = if (read) DISABLED_ALPHA else 1f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(modifier = Modifier.alpha(textSubtitleAlpha)) {
|
Row {
|
||||||
ProvideTextStyle(value = MaterialTheme.typography.bodySmall) {
|
val subtitleStyle = MaterialTheme.typography.bodySmall
|
||||||
|
.merge(
|
||||||
|
color = LocalContentColor.current
|
||||||
|
.copy(alpha = if (read) DISABLED_ALPHA else SECONDARY_ALPHA),
|
||||||
|
)
|
||||||
|
ProvideTextStyle(value = subtitleStyle) {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
Text(
|
Text(
|
||||||
text = date,
|
text = date,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
if (readProgress != null || scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
if (readProgress != null ||
|
||||||
|
scanlator != null/* SY --> */ ||
|
||||||
|
sourceName != null/* SY <-- */
|
||||||
|
) {
|
||||||
|
DotSeparatorText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (readProgress != null) {
|
if (readProgress != null) {
|
||||||
Text(
|
Text(
|
||||||
text = readProgress,
|
text = readProgress,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||||
)
|
)
|
||||||
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import androidx.compose.ui.viewinterop.AndroidView
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
|
import coil3.asDrawable
|
||||||
import coil3.imageLoader
|
import coil3.imageLoader
|
||||||
import coil3.request.CachePolicy
|
import coil3.request.CachePolicy
|
||||||
import coil3.request.ImageRequest
|
import coil3.request.ImageRequest
|
||||||
|
|||||||
@@ -102,9 +102,12 @@ fun SetIntervalDialog(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
Spacer(Modifier.height(MaterialTheme.padding.small))
|
Text(
|
||||||
|
stringResource(MR.strings.manga_interval_expected_update_null),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Spacer(Modifier.height(MaterialTheme.padding.small))
|
||||||
|
|
||||||
if (onValueChanged != null && (isDevFlavor || isPreviewBuildType)) {
|
if (onValueChanged != null && (isDevFlavor || isPreviewBuildType)) {
|
||||||
Text(stringResource(MR.strings.manga_interval_custom_amount))
|
Text(stringResource(MR.strings.manga_interval_custom_amount))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package eu.kanade.presentation.manga.components
|
|||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.animation.core.spring
|
||||||
import androidx.compose.animation.graphics.res.animatedVectorResource
|
import androidx.compose.animation.graphics.res.animatedVectorResource
|
||||||
import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
|
import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
|
||||||
import androidx.compose.animation.graphics.vector.AnimatedImageVector
|
import androidx.compose.animation.graphics.vector.AnimatedImageVector
|
||||||
@@ -81,6 +82,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
|
|||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.TextButton
|
import tachiyomi.presentation.core.components.material.TextButton
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
@@ -180,7 +182,7 @@ fun MangaActionRow(
|
|||||||
// SY <--
|
// SY <--
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = .38f)
|
val defaultActionButtonColor = MaterialTheme.colorScheme.onSurface.copy(alpha = DISABLED_ALPHA)
|
||||||
|
|
||||||
// TODO: show something better when using custom interval
|
// TODO: show something better when using custom interval
|
||||||
val nextUpdateDays = remember(nextUpdate) {
|
val nextUpdateDays = remember(nextUpdate) {
|
||||||
@@ -289,7 +291,8 @@ fun ExpandableMangaDescription(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = 8.dp)
|
.padding(top = 8.dp)
|
||||||
.padding(vertical = 12.dp)
|
.padding(vertical = 12.dp)
|
||||||
.animateContentSize(),
|
.animateContentSize(animationSpec = spring())
|
||||||
|
.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
var showMenu by remember { mutableStateOf(false) }
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
var tagSelected by remember { mutableStateOf("") }
|
var tagSelected by remember { mutableStateOf("") }
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PagePreviewLoading(
|
private fun PagePreviewLoading(
|
||||||
setMaxWidth: (Dp) -> Unit
|
setMaxWidth: (Dp) -> Unit,
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
Box(
|
Box(
|
||||||
@@ -63,7 +63,7 @@ private fun PagePreviewLoading(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun PagePreviewRow(
|
private fun PagePreviewRow(
|
||||||
onOpenPage: (Int) -> Unit,
|
onOpenPage: (Int) -> Unit,
|
||||||
items: ImmutableList<PagePreview>
|
items: ImmutableList<PagePreview>,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -88,7 +88,7 @@ private fun PagePreviewMore(
|
|||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
TextButton(onClick = onMorePreviewsClicked) {
|
TextButton(onClick = onMorePreviewsClicked) {
|
||||||
Text(stringResource(SYMR.strings.more_previews))
|
Text(stringResource(SYMR.strings.more_previews))
|
||||||
@@ -116,7 +116,7 @@ fun PagePreviews(
|
|||||||
pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
|
||||||
PagePreviewRow(
|
PagePreviewRow(
|
||||||
onOpenPage = onOpenPage,
|
onOpenPage = onOpenPage,
|
||||||
items = remember(it) { it.toImmutableList() }
|
items = remember(it) { it.toImmutableList() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ fun LazyListScope.PagePreviewItems(
|
|||||||
) {
|
) {
|
||||||
PagePreviewRow(
|
PagePreviewRow(
|
||||||
onOpenPage = onOpenPage,
|
onOpenPage = onOpenPage,
|
||||||
items = remember(it) { it.toImmutableList() }
|
items = remember(it) { it.toImmutableList() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item(
|
item(
|
||||||
|
|||||||
@@ -111,8 +111,14 @@ fun ScanlatorFilterDialog(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FlowRow {
|
FlowRow {
|
||||||
TextButton(onClick = mutableExcludedScanlators::clear) {
|
if (mutableExcludedScanlators.isEmpty()) {
|
||||||
Text(text = stringResource(MR.strings.action_reset))
|
TextButton(onClick = { mutableExcludedScanlators.addAll(availableScanlators) }) {
|
||||||
|
Text(text = stringResource(MR.strings.action_select_all))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TextButton(onClick = mutableExcludedScanlators::clear) {
|
||||||
|
Text(text = stringResource(MR.strings.action_reset))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.compositionLocalOf
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.structuralEqualityPolicy
|
import androidx.compose.runtime.structuralEqualityPolicy
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.domain.track.service.TrackPreferences
|
|
||||||
import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget
|
import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget
|
||||||
import eu.kanade.presentation.more.settings.widget.InfoWidget
|
import eu.kanade.presentation.more.settings.widget.InfoWidget
|
||||||
import eu.kanade.presentation.more.settings.widget.ListPreferenceWidget
|
import eu.kanade.presentation.more.settings.widget.ListPreferenceWidget
|
||||||
@@ -23,8 +23,6 @@ import eu.kanade.presentation.more.settings.widget.TrackingPreferenceWidget
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import tachiyomi.presentation.core.components.SliderItem
|
import tachiyomi.presentation.core.components.SliderItem
|
||||||
import tachiyomi.presentation.core.util.collectAsState
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
val LocalPreferenceHighlighted = compositionLocalOf(structuralEqualityPolicy()) { false }
|
val LocalPreferenceHighlighted = compositionLocalOf(structuralEqualityPolicy()) { false }
|
||||||
val LocalPreferenceMinHeight = compositionLocalOf(structuralEqualityPolicy()) { 56.dp }
|
val LocalPreferenceMinHeight = compositionLocalOf(structuralEqualityPolicy()) { 56.dp }
|
||||||
@@ -156,16 +154,14 @@ internal fun PreferenceItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
is Preference.PreferenceItem.TrackerPreference -> {
|
is Preference.PreferenceItem.TrackerPreference -> {
|
||||||
val uName by Injekt.get<TrackPreferences>()
|
val isLoggedIn by item.tracker.let { tracker ->
|
||||||
.trackUsername(item.tracker)
|
tracker.isLoggedInFlow.collectAsState(tracker.isLoggedIn)
|
||||||
.collectAsState()
|
|
||||||
item.tracker.run {
|
|
||||||
TrackingPreferenceWidget(
|
|
||||||
tracker = this,
|
|
||||||
checked = uName.isNotEmpty(),
|
|
||||||
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
TrackingPreferenceWidget(
|
||||||
|
tracker = item.tracker,
|
||||||
|
checked = isLoggedIn,
|
||||||
|
onClick = { if (isLoggedIn) item.logout() else item.login() },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
is Preference.PreferenceItem.InfoPreference -> {
|
is Preference.PreferenceItem.InfoPreference -> {
|
||||||
InfoWidget(text = item.title)
|
InfoWidget(text = item.title)
|
||||||
|
|||||||
+1
-2
@@ -3,7 +3,6 @@ package eu.kanade.presentation.more.settings.screen
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.webkit.WebStorage
|
import android.webkit.WebStorage
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
@@ -376,7 +375,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||||||
chooseColorProfile.launch(arrayOf("*/*"))
|
chooseColorProfile.launch(arrayOf("*/*"))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -180,11 +180,15 @@ object SettingsAppearanceScreen : SearchableSettings {
|
|||||||
Preference.PreferenceItem.SliderPreference(
|
Preference.PreferenceItem.SliderPreference(
|
||||||
value = previewsRowCount,
|
value = previewsRowCount,
|
||||||
title = stringResource(SYMR.strings.pref_previews_row_count),
|
title = stringResource(SYMR.strings.pref_previews_row_count),
|
||||||
subtitle = if (previewsRowCount > 0) pluralStringResource(
|
subtitle = if (previewsRowCount > 0) {
|
||||||
SYMR.plurals.row_count,
|
pluralStringResource(
|
||||||
previewsRowCount,
|
SYMR.plurals.row_count,
|
||||||
previewsRowCount,
|
previewsRowCount,
|
||||||
) else stringResource(MR.strings.disabled),
|
previewsRowCount,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(MR.strings.disabled)
|
||||||
|
},
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 10,
|
max = 10,
|
||||||
onValueChanged = {
|
onValueChanged = {
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ object SettingsBrowseScreen : SearchableSettings {
|
|||||||
pref = uiPreferences.feedTabInFront(),
|
pref = uiPreferences.feedTabInFront(),
|
||||||
title = stringResource(SYMR.strings.pref_feed_position),
|
title = stringResource(SYMR.strings.pref_feed_position),
|
||||||
subtitle = stringResource(SYMR.strings.pref_feed_position_summery),
|
subtitle = stringResource(SYMR.strings.pref_feed_position_summery),
|
||||||
enabled = hideFeedTab.not()
|
enabled = hideFeedTab.not(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+30
-4
@@ -127,7 +127,17 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
|
||||||
context.contentResolver.takePersistableUriPermission(uri, flags)
|
// For some reason InkBook devices do not implement the SAF properly. Persistable URI grants do not
|
||||||
|
// work. However, simply retrieving the URI and using it works fine for these devices. Access is not
|
||||||
|
// revoked after the app is closed or the device is restarted.
|
||||||
|
// This also holds for some Samsung devices. Thus, we simply execute inside of a try-catch block and
|
||||||
|
// ignore the exception if it is thrown.
|
||||||
|
try {
|
||||||
|
context.contentResolver.takePersistableUriPermission(uri, flags)
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
context.toast(MR.strings.file_picker_uri_permission_unsupported)
|
||||||
|
}
|
||||||
|
|
||||||
UniFile.fromUri(context, uri)?.let {
|
UniFile.fromUri(context, uri)?.let {
|
||||||
storageDirPref.set(it.uri.toString())
|
storageDirPref.set(it.uri.toString())
|
||||||
@@ -384,11 +394,23 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
syncServiceType: SyncManager.SyncService,
|
syncServiceType: SyncManager.SyncService,
|
||||||
syncPreferences: SyncPreferences,
|
syncPreferences: SyncPreferences,
|
||||||
): List<Preference> {
|
): List<Preference> {
|
||||||
return when (syncServiceType) {
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val preferences = when (syncServiceType) {
|
||||||
SyncManager.SyncService.NONE -> emptyList()
|
SyncManager.SyncService.NONE -> emptyList()
|
||||||
SyncManager.SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences)
|
SyncManager.SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences)
|
||||||
SyncManager.SyncService.GOOGLE_DRIVE -> getGoogleDrivePreferences()
|
SyncManager.SyncService.GOOGLE_DRIVE -> getGoogleDrivePreferences()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return if (syncServiceType != SyncManager.SyncService.NONE) {
|
||||||
|
preferences + Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_choose_what_to_sync),
|
||||||
|
onClick = {
|
||||||
|
navigator.push(SyncSettingsSelector())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
preferences
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -505,7 +527,7 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getSyncNowPref(): Preference.PreferenceGroup {
|
private fun getSyncNowPref(): Preference.PreferenceGroup {
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
val context = LocalContext.current
|
||||||
return Preference.PreferenceGroup(
|
return Preference.PreferenceGroup(
|
||||||
title = stringResource(SYMR.strings.pref_sync_now_group_title),
|
title = stringResource(SYMR.strings.pref_sync_now_group_title),
|
||||||
preferenceItems = persistentListOf(
|
preferenceItems = persistentListOf(
|
||||||
@@ -514,7 +536,11 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
title = stringResource(SYMR.strings.pref_sync_now),
|
title = stringResource(SYMR.strings.pref_sync_now),
|
||||||
subtitle = stringResource(SYMR.strings.pref_sync_now_subtitle),
|
subtitle = stringResource(SYMR.strings.pref_sync_now_subtitle),
|
||||||
onClick = {
|
onClick = {
|
||||||
navigator.push(SyncSettingsSelector())
|
if (!SyncDataJob.isRunning(context)) {
|
||||||
|
SyncDataJob.startNow(context)
|
||||||
|
} else {
|
||||||
|
context.toast(SYMR.strings.sync_in_progress)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+6
@@ -120,6 +120,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
|||||||
allCategories: List<Category>,
|
allCategories: List<Category>,
|
||||||
): Preference.PreferenceGroup {
|
): Preference.PreferenceGroup {
|
||||||
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters()
|
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters()
|
||||||
|
val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly()
|
||||||
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories()
|
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories()
|
||||||
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude()
|
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude()
|
||||||
|
|
||||||
@@ -152,6 +153,11 @@ object SettingsDownloadScreen : SearchableSettings {
|
|||||||
pref = downloadNewChaptersPref,
|
pref = downloadNewChaptersPref,
|
||||||
title = stringResource(MR.strings.pref_download_new),
|
title = stringResource(MR.strings.pref_download_new),
|
||||||
),
|
),
|
||||||
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
|
pref = downloadNewUnreadChaptersOnlyPref,
|
||||||
|
title = stringResource(MR.strings.pref_download_new_unread_chapters_only),
|
||||||
|
enabled = downloadNewChapters,
|
||||||
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(MR.strings.categories),
|
title = stringResource(MR.strings.categories),
|
||||||
subtitle = getCategoriesLabel(
|
subtitle = getCategoriesLabel(
|
||||||
|
|||||||
@@ -84,9 +84,6 @@ object SettingsLibraryScreen : SearchableSettings {
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size
|
val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size
|
||||||
|
|
||||||
val defaultCategory by libraryPreferences.defaultCategory().collectAsState()
|
|
||||||
val selectedCategory = allCategories.find { it.id == defaultCategory.toLong() }
|
|
||||||
|
|
||||||
// For default category
|
// For default category
|
||||||
val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) +
|
val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) +
|
||||||
allCategories.fastMap { it.id.toInt() }
|
allCategories.fastMap { it.id.toInt() }
|
||||||
@@ -108,7 +105,6 @@ object SettingsLibraryScreen : SearchableSettings {
|
|||||||
Preference.PreferenceItem.ListPreference(
|
Preference.PreferenceItem.ListPreference(
|
||||||
pref = libraryPreferences.defaultCategory(),
|
pref = libraryPreferences.defaultCategory(),
|
||||||
title = stringResource(MR.strings.default_category),
|
title = stringResource(MR.strings.default_category),
|
||||||
subtitle = selectedCategory?.visualName ?: stringResource(MR.strings.default_category_summary),
|
|
||||||
entries = ids.zip(labels).toMap().toImmutableMap(),
|
entries = ids.zip(labels).toMap().toImmutableMap(),
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
|
|||||||
+61
-5
@@ -17,6 +17,7 @@ import kotlinx.collections.immutable.persistentMapOf
|
|||||||
import kotlinx.collections.immutable.toImmutableMap
|
import kotlinx.collections.immutable.toImmutableMap
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.collectAsState
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
@@ -88,12 +89,8 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
title = stringResource(MR.strings.pref_page_transitions),
|
title = stringResource(MR.strings.pref_page_transitions),
|
||||||
),
|
),
|
||||||
SY <-- */
|
SY <-- */
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
|
||||||
pref = readerPref.flashOnPageChange(),
|
|
||||||
title = stringResource(MR.strings.pref_flash_page),
|
|
||||||
subtitle = stringResource(MR.strings.pref_flash_page_summ),
|
|
||||||
),
|
|
||||||
getDisplayGroup(readerPreferences = readerPref),
|
getDisplayGroup(readerPreferences = readerPref),
|
||||||
|
getEInkGroup(readerPreferences = readerPref),
|
||||||
getReadingGroup(readerPreferences = readerPref),
|
getReadingGroup(readerPreferences = readerPref),
|
||||||
getPagedGroup(readerPreferences = readerPref),
|
getPagedGroup(readerPreferences = readerPref),
|
||||||
getWebtoonGroup(readerPreferences = readerPref),
|
getWebtoonGroup(readerPreferences = readerPref),
|
||||||
@@ -156,6 +153,65 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getEInkGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||||
|
val flashPageState by readerPreferences.flashOnPageChange().collectAsState()
|
||||||
|
|
||||||
|
val flashMillisPref = readerPreferences.flashDurationMillis()
|
||||||
|
val flashMillis by flashMillisPref.collectAsState()
|
||||||
|
|
||||||
|
val flashIntervalPref = readerPreferences.flashPageInterval()
|
||||||
|
val flashInterval by flashIntervalPref.collectAsState()
|
||||||
|
|
||||||
|
val flashColorPref = readerPreferences.flashColor()
|
||||||
|
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = "E-Ink",
|
||||||
|
preferenceItems = persistentListOf(
|
||||||
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
|
pref = readerPreferences.flashOnPageChange(),
|
||||||
|
title = stringResource(MR.strings.pref_flash_page),
|
||||||
|
subtitle = stringResource(MR.strings.pref_flash_page_summ),
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.SliderPreference(
|
||||||
|
value = flashMillis / ReaderPreferences.MILLI_CONVERSION,
|
||||||
|
min = 1,
|
||||||
|
max = 15,
|
||||||
|
title = stringResource(MR.strings.pref_flash_duration),
|
||||||
|
subtitle = stringResource(MR.strings.pref_flash_duration_summary, flashMillis),
|
||||||
|
onValueChanged = {
|
||||||
|
flashMillisPref.set(it * ReaderPreferences.MILLI_CONVERSION)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
enabled = flashPageState,
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.SliderPreference(
|
||||||
|
value = flashInterval,
|
||||||
|
min = 1,
|
||||||
|
max = 10,
|
||||||
|
title = stringResource(MR.strings.pref_flash_page_interval),
|
||||||
|
subtitle = pluralStringResource(MR.plurals.pref_pages, flashInterval, flashInterval),
|
||||||
|
onValueChanged = {
|
||||||
|
flashIntervalPref.set(it)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
enabled = flashPageState,
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = flashColorPref,
|
||||||
|
title = stringResource(MR.strings.pref_flash_with),
|
||||||
|
entries = persistentMapOf(
|
||||||
|
ReaderPreferences.FlashColor.BLACK to stringResource(MR.strings.pref_flash_style_black),
|
||||||
|
ReaderPreferences.FlashColor.WHITE to stringResource(MR.strings.pref_flash_style_white),
|
||||||
|
ReaderPreferences.FlashColor.WHITE_BLACK
|
||||||
|
to stringResource(MR.strings.pref_flash_style_white_black),
|
||||||
|
),
|
||||||
|
enabled = flashPageState,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getReadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
private fun getReadingGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||||
return Preference.PreferenceGroup(
|
return Preference.PreferenceGroup(
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ class OpenSourceLicensesScreen : Screen() {
|
|||||||
name = it.name,
|
name = it.name,
|
||||||
website = it.website,
|
website = it.website,
|
||||||
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
+9
-2
@@ -8,6 +8,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoConfirmDialog
|
||||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoConflictDialog
|
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoConflictDialog
|
||||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoCreateDialog
|
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoCreateDialog
|
||||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoDeleteDialog
|
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionRepoDeleteDialog
|
||||||
@@ -32,7 +33,7 @@ class ExtensionReposScreen(
|
|||||||
val state by screenModel.state.collectAsState()
|
val state by screenModel.state.collectAsState()
|
||||||
|
|
||||||
LaunchedEffect(url) {
|
LaunchedEffect(url) {
|
||||||
url?.let { screenModel.createRepo(it) }
|
url?.let { screenModel.showDialog(RepoDialog.Confirm(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is RepoScreenState.Loading) {
|
if (state is RepoScreenState.Loading) {
|
||||||
@@ -67,7 +68,6 @@ class ExtensionReposScreen(
|
|||||||
repo = dialog.repo,
|
repo = dialog.repo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is RepoDialog.Conflict -> {
|
is RepoDialog.Conflict -> {
|
||||||
ExtensionRepoConflictDialog(
|
ExtensionRepoConflictDialog(
|
||||||
onDismissRequest = screenModel::dismissDialog,
|
onDismissRequest = screenModel::dismissDialog,
|
||||||
@@ -76,6 +76,13 @@ class ExtensionReposScreen(
|
|||||||
newRepo = dialog.newRepo,
|
newRepo = dialog.newRepo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is RepoDialog.Confirm -> {
|
||||||
|
ExtensionRepoConfirmDialog(
|
||||||
|
onDismissRequest = screenModel::dismissDialog,
|
||||||
|
onCreate = { screenModel.createRepo(dialog.url) },
|
||||||
|
repo = dialog.url,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
|||||||
+1
@@ -125,6 +125,7 @@ sealed class RepoDialog {
|
|||||||
data object Create : RepoDialog()
|
data object Create : RepoDialog()
|
||||||
data class Delete(val repo: String) : RepoDialog()
|
data class Delete(val repo: String) : RepoDialog()
|
||||||
data class Conflict(val oldRepo: ExtensionRepo, val newRepo: ExtensionRepo) : RepoDialog()
|
data class Conflict(val oldRepo: ExtensionRepo, val newRepo: ExtensionRepo) : RepoDialog()
|
||||||
|
data class Confirm(val url: String) : RepoDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class RepoScreenState {
|
sealed class RepoScreenState {
|
||||||
|
|||||||
+32
@@ -152,3 +152,35 @@ fun ExtensionRepoConflictDialog(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ExtensionRepoConfirmDialog(
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onCreate: () -> Unit,
|
||||||
|
repo: String,
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
title = {
|
||||||
|
Text(text = stringResource(MR.strings.action_add_repo))
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(text = stringResource(MR.strings.add_repo_confirmation, repo))
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onCreate()
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(MR.strings.action_add))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+2
-4
@@ -6,7 +6,6 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
@@ -27,7 +26,6 @@ import eu.kanade.tachiyomi.util.system.toast
|
|||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
|
||||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||||
import tachiyomi.presentation.core.components.SectionCard
|
import tachiyomi.presentation.core.components.SectionCard
|
||||||
@@ -69,7 +67,7 @@ class CreateBackupScreen : Screen() {
|
|||||||
LazyColumnWithAction(
|
LazyColumnWithAction(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
actionLabel = stringResource(MR.strings.action_create),
|
actionLabel = stringResource(MR.strings.action_create),
|
||||||
actionEnabled = state.options.anyEnabled(),
|
actionEnabled = state.options.canCreate(),
|
||||||
onClickAction = {
|
onClickAction = {
|
||||||
if (!BackupCreateJob.isManualJobRunning(context)) {
|
if (!BackupCreateJob.isManualJobRunning(context)) {
|
||||||
try {
|
try {
|
||||||
@@ -104,7 +102,7 @@ class CreateBackupScreen : Screen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.Options(
|
private fun Options(
|
||||||
options: ImmutableList<BackupOptions.Entry>,
|
options: ImmutableList<BackupOptions.Entry>,
|
||||||
state: CreateBackupScreenModel.State,
|
state: CreateBackupScreenModel.State,
|
||||||
model: CreateBackupScreenModel,
|
model: CreateBackupScreenModel,
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ class RestoreBackupScreen(
|
|||||||
LazyColumnWithAction(
|
LazyColumnWithAction(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
actionLabel = stringResource(MR.strings.action_restore),
|
actionLabel = stringResource(MR.strings.action_restore),
|
||||||
actionEnabled = state.canRestore && state.options.anyEnabled(),
|
actionEnabled = state.canRestore && state.options.canRestore(),
|
||||||
onClickAction = {
|
onClickAction = {
|
||||||
model.startRestore()
|
model.startRestore()
|
||||||
navigator.pop()
|
navigator.pop()
|
||||||
|
|||||||
+7
-11
@@ -5,7 +5,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
@@ -16,7 +15,6 @@ import eu.kanade.presentation.components.AppBar
|
|||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
|
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
|
||||||
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
@@ -32,7 +30,6 @@ import uy.kohesive.injekt.api.get
|
|||||||
class SyncSettingsSelector : Screen() {
|
class SyncSettingsSelector : Screen() {
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val context = LocalContext.current
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
val model = rememberScreenModel { SyncSettingsSelectorModel() }
|
val model = rememberScreenModel { SyncSettingsSelectorModel() }
|
||||||
val state by model.state.collectAsState()
|
val state by model.state.collectAsState()
|
||||||
@@ -48,15 +45,10 @@ class SyncSettingsSelector : Screen() {
|
|||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
LazyColumnWithAction(
|
LazyColumnWithAction(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
actionLabel = stringResource(SYMR.strings.label_sync),
|
actionLabel = stringResource(MR.strings.action_save),
|
||||||
actionEnabled = state.options.anyEnabled(),
|
actionEnabled = true,
|
||||||
onClickAction = {
|
onClickAction = {
|
||||||
if (!SyncDataJob.isRunning(context)) {
|
navigator.pop()
|
||||||
model.syncNow(context)
|
|
||||||
navigator.pop()
|
|
||||||
} else {
|
|
||||||
context.toast(SYMR.strings.sync_in_progress)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
@@ -122,12 +114,14 @@ private class SyncSettingsSelectorModel(
|
|||||||
tracking = syncSettings.tracking,
|
tracking = syncSettings.tracking,
|
||||||
history = syncSettings.history,
|
history = syncSettings.history,
|
||||||
appSettings = syncSettings.appSettings,
|
appSettings = syncSettings.appSettings,
|
||||||
|
extensionRepoSettings = syncSettings.extensionRepoSettings,
|
||||||
sourceSettings = syncSettings.sourceSettings,
|
sourceSettings = syncSettings.sourceSettings,
|
||||||
privateSettings = syncSettings.privateSettings,
|
privateSettings = syncSettings.privateSettings,
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = syncSettings.customInfo,
|
customInfo = syncSettings.customInfo,
|
||||||
readEntries = syncSettings.readEntries,
|
readEntries = syncSettings.readEntries,
|
||||||
|
savedSearches = syncSettings.savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -140,12 +134,14 @@ private class SyncSettingsSelectorModel(
|
|||||||
tracking = backupOptions.tracking,
|
tracking = backupOptions.tracking,
|
||||||
history = backupOptions.history,
|
history = backupOptions.history,
|
||||||
appSettings = backupOptions.appSettings,
|
appSettings = backupOptions.appSettings,
|
||||||
|
extensionRepoSettings = backupOptions.extensionRepoSettings,
|
||||||
sourceSettings = backupOptions.sourceSettings,
|
sourceSettings = backupOptions.sourceSettings,
|
||||||
privateSettings = backupOptions.privateSettings,
|
privateSettings = backupOptions.privateSettings,
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = backupOptions.customInfo,
|
customInfo = backupOptions.customInfo,
|
||||||
readEntries = backupOptions.readEntries,
|
readEntries = backupOptions.readEntries,
|
||||||
|
savedSearches = backupOptions.savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -28,7 +28,7 @@ import tachiyomi.presentation.core.i18n.stringResource
|
|||||||
class BackupSchemaScreen : Screen() {
|
class BackupSchemaScreen : Screen() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val title = "Backup file schema"
|
const val TITLE = "Backup file schema"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -41,7 +41,7 @@ class BackupSchemaScreen : Screen() {
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(
|
AppBar(
|
||||||
title = title,
|
title = TITLE,
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
actions = {
|
actions = {
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
@@ -50,7 +50,7 @@ class BackupSchemaScreen : Screen() {
|
|||||||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||||
icon = Icons.Default.ContentCopy,
|
icon = Icons.Default.ContentCopy,
|
||||||
onClick = {
|
onClick = {
|
||||||
context.copyToClipboard(title, schema)
|
context.copyToClipboard(TITLE, schema)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+2
-2
@@ -31,11 +31,11 @@ class DebugInfoScreen : Screen() {
|
|||||||
itemsProvider = {
|
itemsProvider = {
|
||||||
listOf(
|
listOf(
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = WorkerInfoScreen.title,
|
title = WorkerInfoScreen.TITLE,
|
||||||
onClick = { navigator.push(WorkerInfoScreen()) },
|
onClick = { navigator.push(WorkerInfoScreen()) },
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = BackupSchemaScreen.title,
|
title = BackupSchemaScreen.TITLE,
|
||||||
onClick = { navigator.push(BackupSchemaScreen()) },
|
onClick = { navigator.push(BackupSchemaScreen()) },
|
||||||
),
|
),
|
||||||
getAppInfoGroup(),
|
getAppInfoGroup(),
|
||||||
|
|||||||
+4
-4
@@ -49,7 +49,7 @@ import java.time.ZoneId
|
|||||||
class WorkerInfoScreen : Screen() {
|
class WorkerInfoScreen : Screen() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val title = "Worker info"
|
const val TITLE = "Worker info"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -65,7 +65,7 @@ class WorkerInfoScreen : Screen() {
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppBar(
|
AppBar(
|
||||||
title = title,
|
title = TITLE,
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
actions = {
|
actions = {
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
@@ -74,7 +74,7 @@ class WorkerInfoScreen : Screen() {
|
|||||||
title = stringResource(MR.strings.action_copy_to_clipboard),
|
title = stringResource(MR.strings.action_copy_to_clipboard),
|
||||||
icon = Icons.Default.ContentCopy,
|
icon = Icons.Default.ContentCopy,
|
||||||
onClick = {
|
onClick = {
|
||||||
context.copyToClipboard(title, enqueued + finished + running)
|
context.copyToClipboard(TITLE, enqueued + finished + running)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -159,7 +159,7 @@ class WorkerInfoScreen : Screen() {
|
|||||||
Injekt.get<UiPreferences>().dateFormat().get(),
|
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
appendLine("Next scheduled run: $timestamp",)
|
appendLine("Next scheduled run: $timestamp")
|
||||||
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
||||||
}
|
}
|
||||||
appendLine()
|
appendLine()
|
||||||
|
|||||||
+1
-2
@@ -223,13 +223,12 @@ fun AppThemePreviewItem(
|
|||||||
contentAlignment = Alignment.BottomCenter,
|
contentAlignment = Alignment.BottomCenter,
|
||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
tonalElevation = 3.dp,
|
color = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(32.dp)
|
.height(32.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.surfaceVariant)
|
|
||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ import tachiyomi.presentation.core.util.isScrolledToEnd
|
|||||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||||
|
|
||||||
private enum class State {
|
private enum class State {
|
||||||
CHECKED, INVERSED, UNCHECKED
|
CHECKED,
|
||||||
|
INVERSED,
|
||||||
|
UNCHECKED,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -73,7 +73,7 @@ private fun RowScope.BaseStatsItem(
|
|||||||
style = subtitleStyle
|
style = subtitleStyle
|
||||||
.copy(
|
.copy(
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
.copy(alpha = SecondaryItemAlpha),
|
.copy(alpha = SECONDARY_ALPHA),
|
||||||
),
|
),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ private fun ChapterText(
|
|||||||
Text(
|
Text(
|
||||||
text = buildAnnotatedString {
|
text = buildAnnotatedString {
|
||||||
if (downloaded) {
|
if (downloaded) {
|
||||||
appendInlineContent(DownloadedIconContentId)
|
appendInlineContent(DOWNLOADED_ICON_ID)
|
||||||
append(' ')
|
append(' ')
|
||||||
}
|
}
|
||||||
append(name)
|
append(name)
|
||||||
@@ -236,7 +236,7 @@ private fun ChapterText(
|
|||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
inlineContent = persistentMapOf(
|
inlineContent = persistentMapOf(
|
||||||
DownloadedIconContentId to InlineTextContent(
|
DOWNLOADED_ICON_ID to InlineTextContent(
|
||||||
Placeholder(
|
Placeholder(
|
||||||
width = 22.sp,
|
width = 22.sp,
|
||||||
height = 22.sp,
|
height = 22.sp,
|
||||||
@@ -273,7 +273,7 @@ private val CardColor: CardColors
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val VerticalSpacerSize = 24.dp
|
private val VerticalSpacerSize = 24.dp
|
||||||
private const val DownloadedIconContentId = "downloaded"
|
private const val DOWNLOADED_ICON_ID = "downloaded"
|
||||||
|
|
||||||
private fun previewChapter(name: String, scanlator: String, chapterNumber: Double) = Chapter.create().copy(
|
private fun previewChapter(name: String, scanlator: String, chapterNumber: Double) = Chapter.create().copy(
|
||||||
id = 0L,
|
id = 0L,
|
||||||
|
|||||||
@@ -7,19 +7,42 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
class DisplayRefreshHost {
|
class DisplayRefreshHost {
|
||||||
|
|
||||||
internal var currentDisplayRefresh by mutableStateOf(false)
|
internal var currentDisplayRefresh by mutableStateOf(false)
|
||||||
|
private val readerPreferences = Injekt.get<ReaderPreferences>()
|
||||||
|
|
||||||
|
internal val flashMillis = readerPreferences.flashDurationMillis()
|
||||||
|
internal val flashMode = readerPreferences.flashColor()
|
||||||
|
|
||||||
|
internal val flashIntervalPref = readerPreferences.flashPageInterval()
|
||||||
|
|
||||||
|
// Internal State for Flash
|
||||||
|
private var flashInterval = flashIntervalPref.get()
|
||||||
|
private var timesCalled = 0
|
||||||
|
|
||||||
fun flash() {
|
fun flash() {
|
||||||
currentDisplayRefresh = true
|
if (timesCalled % flashInterval == 0) {
|
||||||
|
currentDisplayRefresh = true
|
||||||
|
}
|
||||||
|
timesCalled += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setInterval(interval: Int) {
|
||||||
|
flashInterval = interval
|
||||||
|
timesCalled = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,18 +52,39 @@ fun DisplayRefreshHost(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val currentDisplayRefresh = hostState.currentDisplayRefresh
|
val currentDisplayRefresh = hostState.currentDisplayRefresh
|
||||||
|
val refreshDuration by hostState.flashMillis.collectAsState()
|
||||||
|
val flashMode by hostState.flashMode.collectAsState()
|
||||||
|
val flashInterval by hostState.flashIntervalPref.collectAsState()
|
||||||
|
|
||||||
|
var currentColor by remember { mutableStateOf<Color?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(currentDisplayRefresh) {
|
LaunchedEffect(currentDisplayRefresh) {
|
||||||
if (currentDisplayRefresh) {
|
if (!currentDisplayRefresh) {
|
||||||
delay(1.5.seconds)
|
currentColor = null
|
||||||
hostState.currentDisplayRefresh = false
|
return@LaunchedEffect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val refreshDurationHalf = refreshDuration.milliseconds / 2
|
||||||
|
currentColor = if (flashMode == ReaderPreferences.FlashColor.BLACK) {
|
||||||
|
Color.Black
|
||||||
|
} else {
|
||||||
|
Color.White
|
||||||
|
}
|
||||||
|
delay(refreshDurationHalf)
|
||||||
|
if (flashMode == ReaderPreferences.FlashColor.WHITE_BLACK) {
|
||||||
|
currentColor = Color.Black
|
||||||
|
}
|
||||||
|
delay(refreshDurationHalf)
|
||||||
|
hostState.currentDisplayRefresh = false
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(flashInterval) {
|
||||||
|
hostState.setInterval(flashInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas(
|
Canvas(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
if (currentDisplayRefresh) {
|
currentColor?.let { drawRect(it) }
|
||||||
drawRect(Color.Black)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.ContentCopy
|
||||||
import androidx.compose.material.icons.outlined.Photo
|
import androidx.compose.material.icons.outlined.Photo
|
||||||
import androidx.compose.material.icons.outlined.Save
|
import androidx.compose.material.icons.outlined.Save
|
||||||
import androidx.compose.material.icons.outlined.Share
|
import androidx.compose.material.icons.outlined.Share
|
||||||
@@ -31,9 +32,9 @@ fun ReaderPageActionsDialog(
|
|||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
// SY -->
|
// SY -->
|
||||||
onSetAsCover: (useExtraPage: Boolean) -> Unit,
|
onSetAsCover: (useExtraPage: Boolean) -> Unit,
|
||||||
onShare: (useExtraPage: Boolean) -> Unit,
|
onShare: (copy: Boolean, useExtraPage: Boolean) -> Unit,
|
||||||
onSave: (useExtraPage: Boolean) -> Unit,
|
onSave: (useExtraPage: Boolean) -> Unit,
|
||||||
onShareCombined: () -> Unit,
|
onShareCombined: (copy: Boolean) -> Unit,
|
||||||
onSaveCombined: () -> Unit,
|
onSaveCombined: () -> Unit,
|
||||||
hasExtraPage: Boolean,
|
hasExtraPage: Boolean,
|
||||||
// SY <--
|
// SY <--
|
||||||
@@ -43,9 +44,7 @@ fun ReaderPageActionsDialog(
|
|||||||
var useExtraPage by remember { mutableStateOf(false) }
|
var useExtraPage by remember { mutableStateOf(false) }
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
AdaptiveSheet(
|
AdaptiveSheet(onDismissRequest = onDismissRequest) {
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(vertical = 16.dp)) {
|
Column(modifier = Modifier.padding(vertical = 16.dp)) {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||||
@@ -64,6 +63,25 @@ fun ReaderPageActionsDialog(
|
|||||||
icon = Icons.Outlined.Photo,
|
icon = Icons.Outlined.Photo,
|
||||||
onClick = { showSetCoverDialog = true },
|
onClick = { showSetCoverDialog = true },
|
||||||
)
|
)
|
||||||
|
ActionButton(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
title = stringResource(
|
||||||
|
// SY -->
|
||||||
|
if (hasExtraPage) {
|
||||||
|
SYMR.strings.action_copy_first_page
|
||||||
|
} else {
|
||||||
|
MR.strings.action_copy_to_clipboard
|
||||||
|
},
|
||||||
|
// SY <--
|
||||||
|
),
|
||||||
|
icon = Icons.Outlined.ContentCopy,
|
||||||
|
onClick = {
|
||||||
|
// SY -->
|
||||||
|
onShare(true, false)
|
||||||
|
// SY <--
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
title = stringResource(
|
title = stringResource(
|
||||||
@@ -78,7 +96,7 @@ fun ReaderPageActionsDialog(
|
|||||||
icon = Icons.Outlined.Share,
|
icon = Icons.Outlined.Share,
|
||||||
onClick = {
|
onClick = {
|
||||||
// SY -->
|
// SY -->
|
||||||
onShare(false)
|
onShare(false, false)
|
||||||
// SY <--
|
// SY <--
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
},
|
},
|
||||||
@@ -116,12 +134,21 @@ fun ReaderPageActionsDialog(
|
|||||||
showSetCoverDialog = true
|
showSetCoverDialog = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
ActionButton(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
title = stringResource(SYMR.strings.action_copy_second_page),
|
||||||
|
icon = Icons.Outlined.ContentCopy,
|
||||||
|
onClick = {
|
||||||
|
onShare(true, true)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
title = stringResource(SYMR.strings.action_share_second_page),
|
title = stringResource(SYMR.strings.action_share_second_page),
|
||||||
icon = Icons.Outlined.Share,
|
icon = Icons.Outlined.Share,
|
||||||
onClick = {
|
onClick = {
|
||||||
onShare(true)
|
onShare(false, true)
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -138,12 +165,21 @@ fun ReaderPageActionsDialog(
|
|||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||||
) {
|
) {
|
||||||
|
ActionButton(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
title = stringResource(SYMR.strings.action_copy_combined_page),
|
||||||
|
icon = Icons.Outlined.ContentCopy,
|
||||||
|
onClick = {
|
||||||
|
onShareCombined(true)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
)
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
title = stringResource(SYMR.strings.action_share_combined_page),
|
title = stringResource(SYMR.strings.action_share_combined_page),
|
||||||
icon = Icons.Outlined.Share,
|
icon = Icons.Outlined.Share,
|
||||||
onClick = {
|
onClick = {
|
||||||
onShareCombined()
|
onShareCombined(false)
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ fun ExhUtils(
|
|||||||
modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(backgroundColor),
|
.background(backgroundColor),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(visible = isVisible) {
|
AnimatedVisibility(visible = isVisible) {
|
||||||
Column {
|
Column {
|
||||||
@@ -84,7 +84,7 @@ fun ExhUtils(
|
|||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(3f),
|
Modifier.weight(3f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(SYMR.strings.eh_autoscroll),
|
text = stringResource(SYMR.strings.eh_autoscroll),
|
||||||
@@ -93,17 +93,17 @@ fun ExhUtils(
|
|||||||
fontFamily = FontFamily.SansSerif,
|
fontFamily = FontFamily.SansSerif,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
modifier = Modifier.fillMaxWidth(0.75f),
|
modifier = Modifier.fillMaxWidth(0.75f),
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(1f),
|
Modifier.weight(1f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Switch(
|
Switch(
|
||||||
checked = isAutoScroll,
|
checked = isAutoScroll,
|
||||||
onCheckedChange = null,
|
onCheckedChange = null,
|
||||||
enabled = isAutoScrollEnabled
|
enabled = isAutoScrollEnabled,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ fun ExhUtils(
|
|||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(3f),
|
Modifier.weight(3f),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
var autoScrollFrequencyState by remember {
|
var autoScrollFrequencyState by remember {
|
||||||
mutableStateOf(autoScrollFrequency)
|
mutableStateOf(autoScrollFrequency)
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import androidx.compose.material3.FilterChip
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
import tachiyomi.presentation.core.components.SettingsChipRow
|
import tachiyomi.presentation.core.components.SettingsChipRow
|
||||||
|
import tachiyomi.presentation.core.components.SliderItem
|
||||||
|
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.collectAsState
|
import tachiyomi.presentation.core.util.collectAsState
|
||||||
|
|
||||||
@@ -20,9 +23,27 @@ private val themes = listOf(
|
|||||||
MR.strings.automatic_background to 3,
|
MR.strings.automatic_background to 3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val flashColors = listOf(
|
||||||
|
MR.strings.pref_flash_style_black to ReaderPreferences.FlashColor.BLACK,
|
||||||
|
MR.strings.pref_flash_style_white to ReaderPreferences.FlashColor.WHITE,
|
||||||
|
MR.strings.pref_flash_style_white_black to ReaderPreferences.FlashColor.WHITE_BLACK,
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
||||||
val readerTheme by screenModel.preferences.readerTheme().collectAsState()
|
val readerTheme by screenModel.preferences.readerTheme().collectAsState()
|
||||||
|
|
||||||
|
val flashPageState by screenModel.preferences.flashOnPageChange().collectAsState()
|
||||||
|
|
||||||
|
val flashMillisPref = screenModel.preferences.flashDurationMillis()
|
||||||
|
val flashMillis by flashMillisPref.collectAsState()
|
||||||
|
|
||||||
|
val flashIntervalPref = screenModel.preferences.flashPageInterval()
|
||||||
|
val flashInterval by flashIntervalPref.collectAsState()
|
||||||
|
|
||||||
|
val flashColorPref = screenModel.preferences.flashColor()
|
||||||
|
val flashColor by flashColorPref.collectAsState()
|
||||||
|
|
||||||
SettingsChipRow(MR.strings.pref_reader_theme) {
|
SettingsChipRow(MR.strings.pref_reader_theme) {
|
||||||
themes.map { (labelRes, value) ->
|
themes.map { (labelRes, value) ->
|
||||||
FilterChip(
|
FilterChip(
|
||||||
@@ -95,6 +116,35 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
|||||||
label = stringResource(MR.strings.pref_flash_page),
|
label = stringResource(MR.strings.pref_flash_page),
|
||||||
pref = screenModel.preferences.flashOnPageChange(),
|
pref = screenModel.preferences.flashOnPageChange(),
|
||||||
)
|
)
|
||||||
|
if (flashPageState) {
|
||||||
|
SliderItem(
|
||||||
|
value = flashMillis / ReaderPreferences.MILLI_CONVERSION,
|
||||||
|
label = stringResource(MR.strings.pref_flash_duration),
|
||||||
|
valueText = stringResource(MR.strings.pref_flash_duration_summary, flashMillis),
|
||||||
|
onChange = { flashMillisPref.set(it * ReaderPreferences.MILLI_CONVERSION) },
|
||||||
|
min = 1,
|
||||||
|
max = 15,
|
||||||
|
)
|
||||||
|
SliderItem(
|
||||||
|
value = flashInterval,
|
||||||
|
label = stringResource(MR.strings.pref_flash_page_interval),
|
||||||
|
valueText = pluralStringResource(MR.plurals.pref_pages, flashInterval, flashInterval),
|
||||||
|
onChange = {
|
||||||
|
flashIntervalPref.set(it)
|
||||||
|
},
|
||||||
|
min = 1,
|
||||||
|
max = 10,
|
||||||
|
)
|
||||||
|
SettingsChipRow(MR.strings.pref_flash_with) {
|
||||||
|
flashColors.map { (labelRes, value) ->
|
||||||
|
FilterChip(
|
||||||
|
selected = flashColor == value,
|
||||||
|
onClick = { flashColorPref.set(value) },
|
||||||
|
label = { Text(stringResource(labelRes)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
CheckboxItem(
|
CheckboxItem(
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ internal abstract class BaseColorScheme {
|
|||||||
abstract val darkScheme: ColorScheme
|
abstract val darkScheme: ColorScheme
|
||||||
abstract val lightScheme: ColorScheme
|
abstract val lightScheme: ColorScheme
|
||||||
|
|
||||||
|
// Cannot be pure black as there's content scrolling behind it
|
||||||
|
// https://m3.material.io/components/navigation-bar/guidelines#90615a71-607e-485e-9e09-778bfc080563
|
||||||
|
private val surfaceContainer = Color(0xFF0C0C0C)
|
||||||
|
private val surfaceContainerHigh = Color(0xFF131313)
|
||||||
|
private val surfaceContainerHighest = Color(0xFF1B1B1B)
|
||||||
|
|
||||||
fun getColorScheme(isDark: Boolean, isAmoled: Boolean): ColorScheme {
|
fun getColorScheme(isDark: Boolean, isAmoled: Boolean): ColorScheme {
|
||||||
if (!isDark) return lightScheme
|
if (!isDark) return lightScheme
|
||||||
|
|
||||||
@@ -18,6 +24,12 @@ internal abstract class BaseColorScheme {
|
|||||||
onBackground = Color.White,
|
onBackground = Color.White,
|
||||||
surface = Color.Black,
|
surface = Color.Black,
|
||||||
onSurface = Color.White,
|
onSurface = Color.White,
|
||||||
|
surfaceVariant = surfaceContainer, // Navigation bar background (ThemePrefWidget)
|
||||||
|
surfaceContainerLowest = surfaceContainer,
|
||||||
|
surfaceContainerLow = surfaceContainer,
|
||||||
|
surfaceContainer = surfaceContainer, // Navigation bar background
|
||||||
|
surfaceContainerHigh = surfaceContainerHigh,
|
||||||
|
surfaceContainerHighest = surfaceContainerHighest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-43
@@ -19,53 +19,77 @@ internal object GreenAppleColorScheme : BaseColorScheme() {
|
|||||||
|
|
||||||
override val darkScheme = darkColorScheme(
|
override val darkScheme = darkColorScheme(
|
||||||
primary = Color(0xFF7ADB8F),
|
primary = Color(0xFF7ADB8F),
|
||||||
onPrimary = Color(0xFF003915),
|
onPrimary = Color(0xFF003917),
|
||||||
primaryContainer = Color(0xFF005322),
|
primaryContainer = Color(0xFF017737),
|
||||||
onPrimaryContainer = Color(0xFF96F8A9),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFF006D2F),
|
secondary = Color(0xFF7ADB8F), // Unread badge
|
||||||
secondary = Color(0xFF7ADB8F),
|
onSecondary = Color(0xFF003917), // Unread badge text
|
||||||
onSecondary = Color(0xFF003915),
|
secondaryContainer = Color(0xFF017737), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
secondaryContainer = Color(0xFF005322),
|
onSecondaryContainer = Color(0xFFFFFFFF), // Navigation bar selected icon
|
||||||
onSecondaryContainer = Color(0xFF96F8A9),
|
tertiary = Color(0xFFFFB3AC), // Downloaded badge
|
||||||
tertiary = Color(0xFFFFB3AA),
|
onTertiary = Color(0xFF680008), // Downloaded badge text
|
||||||
onTertiary = Color(0xFF680006),
|
tertiaryContainer = Color(0xFFC7282A),
|
||||||
tertiaryContainer = Color(0xFF93000D),
|
onTertiaryContainer = Color(0xFFFFFFFF),
|
||||||
onTertiaryContainer = Color(0xFFFFDAD5),
|
error = Color(0xFFFFB4AB),
|
||||||
background = Color(0xFF1A1C19),
|
onError = Color(0xFF690005),
|
||||||
onBackground = Color(0xFFE1E3DD),
|
errorContainer = Color(0xFF93000A),
|
||||||
surface = Color(0xFF1A1C19),
|
onErrorContainer = Color(0xFFFFDAD6),
|
||||||
onSurface = Color(0xFFE1E3DD),
|
background = Color(0xFF0F1510),
|
||||||
surfaceVariant = Color(0xFF414941),
|
onBackground = Color(0xFFDFE4DB),
|
||||||
onSurfaceVariant = Color(0xFFC1C8BE),
|
surface = Color(0xFF0F1510),
|
||||||
surfaceTint = Color(0xFF7ADB8F),
|
onSurface = Color(0xFFDFE4DB),
|
||||||
inverseSurface = Color(0xFFE1E3DD),
|
surfaceVariant = Color(0xFF3F493F), // Navigation bar background (ThemePrefWidget)
|
||||||
inverseOnSurface = Color(0xFF1A1C19),
|
onSurfaceVariant = Color(0xFFBECABC),
|
||||||
outline = Color(0xFF8B9389),
|
outline = Color(0xFF889487),
|
||||||
|
outlineVariant = Color(0xFF3F493F),
|
||||||
|
scrim = Color(0xFF000000),
|
||||||
|
inverseSurface = Color(0xFFDFE4DB),
|
||||||
|
inverseOnSurface = Color(0xFF2C322C),
|
||||||
|
inversePrimary = Color(0xFF006D32),
|
||||||
|
surfaceDim = Color(0xFF0F1510),
|
||||||
|
surfaceBright = Color(0xFF353B35),
|
||||||
|
surfaceContainerLowest = Color(0xFF0A0F0B),
|
||||||
|
surfaceContainerLow = Color(0xFF181D18),
|
||||||
|
surfaceContainer = Color(0xFF1C211C), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF262B26),
|
||||||
|
surfaceContainerHighest = Color(0xFF313630),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
primary = Color(0xFF006D2F),
|
primary = Color(0xFF005927),
|
||||||
onPrimary = Color(0xFFFFFFFF),
|
onPrimary = Color(0xFFFFFFFF),
|
||||||
primaryContainer = Color(0xFF96F8A9),
|
primaryContainer = Color(0xFF188140),
|
||||||
onPrimaryContainer = Color(0xFF002109),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
|
secondary = Color(0xFF005927), // Unread badge
|
||||||
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
|
secondaryContainer = Color(0xFF97f7a9), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
|
onSecondaryContainer = Color(0xFF000000), // Navigation bar selected icon
|
||||||
|
tertiary = Color(0xFF9D0012), // Downloaded badge
|
||||||
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
|
tertiaryContainer = Color(0xFFD33131),
|
||||||
|
onTertiaryContainer = Color(0xFFFFFFFF),
|
||||||
|
error = Color(0xFFBA1A1A),
|
||||||
|
onError = Color(0xFFFFFFFF),
|
||||||
|
errorContainer = Color(0xFFFFDAD6),
|
||||||
|
onErrorContainer = Color(0xFF410002),
|
||||||
|
background = Color(0xFFF6FBF2),
|
||||||
|
onBackground = Color(0xFF181D18),
|
||||||
|
surface = Color(0xFFF6FBF2),
|
||||||
|
onSurface = Color(0xFF181D18),
|
||||||
|
surfaceVariant = Color(0xFFDAE6D7), // Navigation bar background (ThemePrefWidget)
|
||||||
|
onSurfaceVariant = Color(0xFF3F493F),
|
||||||
|
outline = Color(0xFF6F7A6E),
|
||||||
|
outlineVariant = Color(0xFFBECABC),
|
||||||
|
scrim = Color(0xFF000000),
|
||||||
|
inverseSurface = Color(0xFF2C322C),
|
||||||
|
inverseOnSurface = Color(0xFFEDF2E9),
|
||||||
inversePrimary = Color(0xFF7ADB8F),
|
inversePrimary = Color(0xFF7ADB8F),
|
||||||
secondary = Color(0xFF006D2F),
|
surfaceDim = Color(0xFFD6DCD3),
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
surfaceBright = Color(0xFFF6FBF2),
|
||||||
secondaryContainer = Color(0xFF96F8A9),
|
surfaceContainerLowest = Color(0xFFFFFFFF),
|
||||||
onSecondaryContainer = Color(0xFF002109),
|
surfaceContainerLow = Color(0xFFF0F5EC),
|
||||||
tertiary = Color(0xFFB91D22),
|
surfaceContainer = Color(0xFFEAEFE6), // Navigation bar background
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
surfaceContainerHigh = Color(0xFFE4EAE1),
|
||||||
tertiaryContainer = Color(0xFFFFDAD5),
|
surfaceContainerHighest = Color(0xFFDFE4DB),
|
||||||
onTertiaryContainer = Color(0xFF410003),
|
|
||||||
background = Color(0xFFFBFDF7),
|
|
||||||
onBackground = Color(0xFF1A1C19),
|
|
||||||
surface = Color(0xFFFBFDF7),
|
|
||||||
onSurface = Color(0xFF1A1C19),
|
|
||||||
surfaceVariant = Color(0xFFDDE5DA),
|
|
||||||
onSurfaceVariant = Color(0xFF414941),
|
|
||||||
surfaceTint = Color(0xFF006D2F),
|
|
||||||
inverseSurface = Color(0xFF2F312E),
|
|
||||||
inverseOnSurface = Color(0xFFF0F2EC),
|
|
||||||
outline = Color(0xFF717970),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,53 +18,77 @@ internal object LavenderColorScheme : BaseColorScheme() {
|
|||||||
|
|
||||||
override val darkScheme = darkColorScheme(
|
override val darkScheme = darkColorScheme(
|
||||||
primary = Color(0xFFA177FF),
|
primary = Color(0xFFA177FF),
|
||||||
onPrimary = Color(0xFF111129),
|
onPrimary = Color(0xFF3D0090),
|
||||||
primaryContainer = Color(0xFFA177FF),
|
primaryContainer = Color(0xFFA177FF),
|
||||||
onPrimaryContainer = Color(0xFF111129),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFF006D2F),
|
secondary = Color(0xFFA177FF), // Unread badge
|
||||||
secondary = Color(0xFFA177FF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
onSecondary = Color(0xFF111129),
|
secondaryContainer = Color(0xFF423271), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
secondaryContainer = Color(0xFFA177FF),
|
onSecondaryContainer = Color(0xFFA177FF), // Navigation bar selected icon
|
||||||
onSecondaryContainer = Color(0xFF111129),
|
tertiary = Color(0xFFCDBDFF), // Downloaded badge
|
||||||
tertiary = Color(0xFF5E25E1),
|
onTertiary = Color(0xFF360096), // Downloaded badge text
|
||||||
onTertiary = Color(0xFFE8E8E8),
|
tertiaryContainer = Color(0xFF5512D8),
|
||||||
tertiaryContainer = Color(0xFF111129),
|
onTertiaryContainer = Color(0xFFEFE6FF),
|
||||||
onTertiaryContainer = Color(0xFFDEE8FF),
|
error = Color(0xFFFFB4AB),
|
||||||
|
onError = Color(0xFF690005),
|
||||||
|
errorContainer = Color(0xFF93000A),
|
||||||
|
onErrorContainer = Color(0xFFFFDAD6),
|
||||||
background = Color(0xFF111129),
|
background = Color(0xFF111129),
|
||||||
onBackground = Color(0xFFDEE8FF),
|
onBackground = Color(0xFFE7E0EC),
|
||||||
surface = Color(0xFF111129),
|
surface = Color(0xFF111129),
|
||||||
onSurface = Color(0xFFDEE8FF),
|
onSurface = Color(0xFFE7E0EC),
|
||||||
surfaceVariant = Color(0x2CB6B6B6),
|
surfaceVariant = Color(0xFF3D2F6B), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFE8E8E8),
|
onSurfaceVariant = Color(0xFFCBC3D6),
|
||||||
surfaceTint = Color(0xFFA177FF),
|
outline = Color(0xFF958E9F),
|
||||||
inverseSurface = Color(0xFF221247),
|
outlineVariant = Color(0xFF4A4453),
|
||||||
inverseOnSurface = Color(0xFFDEE8FF),
|
scrim = Color(0xFF000000),
|
||||||
outline = Color(0xA8905FFF),
|
inverseSurface = Color(0xFFE7E0EC),
|
||||||
|
inverseOnSurface = Color(0xFF322F38),
|
||||||
|
inversePrimary = Color(0xFF6D41C8),
|
||||||
|
surfaceDim = Color(0xFF111129),
|
||||||
|
surfaceBright = Color(0xFF3B3841),
|
||||||
|
surfaceContainerLowest = Color(0xFF15132d),
|
||||||
|
surfaceContainerLow = Color(0xFF171531),
|
||||||
|
surfaceContainer = Color(0xFF1D193B), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF241f41),
|
||||||
|
surfaceContainerHighest = Color(0xFF282446),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
primary = Color(0xFF7B46AF),
|
primary = Color(0xFF6D41C8),
|
||||||
onPrimary = Color(0xFFEDE2FF),
|
onPrimary = Color(0xFFFFFFFF),
|
||||||
primaryContainer = Color(0xFF7B46AF),
|
primaryContainer = Color(0xFF7B46AF),
|
||||||
onPrimaryContainer = Color(0xFFEDE2FF),
|
onPrimaryContainer = Color(0xFF130038),
|
||||||
inversePrimary = Color(0xFFD6BAFF),
|
secondary = Color(0xFF7B46AF), // Unread badge
|
||||||
secondary = Color(0xFF7B46AF),
|
onSecondary = Color(0xFFEDE2FF), // Unread badge text
|
||||||
onSecondary = Color(0xFFEDE2FF),
|
secondaryContainer = Color(0xFFC9B0E6), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
secondaryContainer = Color(0xFF7B46AF),
|
onSecondaryContainer = Color(0xFF7B46AF), // Navigation bar selector icon
|
||||||
onSecondaryContainer = Color(0xFFEDE2FF),
|
tertiary = Color(0xFFEDE2FF), // Downloaded badge
|
||||||
tertiary = Color(0xFFEDE2FF),
|
onTertiary = Color(0xFF7B46AF), // Downloaded badge text
|
||||||
onTertiary = Color(0xFF7B46AF),
|
tertiaryContainer = Color(0xFF6D3BF0),
|
||||||
tertiaryContainer = Color(0xFFEDE2FF),
|
onTertiaryContainer = Color(0xFFFFFFFF),
|
||||||
onTertiaryContainer = Color(0xFF7B46AF),
|
error = Color(0xFFBA1A1A),
|
||||||
|
onError = Color(0xFFFFFFFF),
|
||||||
|
errorContainer = Color(0xFFFFDAD6),
|
||||||
|
onErrorContainer = Color(0xFF410002),
|
||||||
background = Color(0xFFEDE2FF),
|
background = Color(0xFFEDE2FF),
|
||||||
onBackground = Color(0xFF1B1B22),
|
onBackground = Color(0xFF1D1A22),
|
||||||
surface = Color(0xFFEDE2FF),
|
surface = Color(0xFFEDE2FF),
|
||||||
onSurface = Color(0xFF1B1B22),
|
onSurface = Color(0xFF1D1A22),
|
||||||
surfaceVariant = Color(0xFFB9B0CC),
|
surfaceVariant = Color(0xFFE4D5F8), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xD849454E),
|
onSurfaceVariant = Color(0xFF4A4453),
|
||||||
surfaceTint = Color(0xFF7B46AF),
|
outline = Color(0xFF7B7485),
|
||||||
inverseSurface = Color(0xFF313033),
|
outlineVariant = Color(0xFFCBC3D6),
|
||||||
inverseOnSurface = Color(0xFFF3EFF4),
|
scrim = Color(0xFF000000),
|
||||||
outline = Color(0xFF7B46AF),
|
inverseSurface = Color(0xFF322F38),
|
||||||
|
inverseOnSurface = Color(0xFFF5EEFA),
|
||||||
|
inversePrimary = Color(0xFFA177FF),
|
||||||
|
surfaceDim = Color(0xFFDED7E3),
|
||||||
|
surfaceBright = Color(0xFFEDE2FF),
|
||||||
|
surfaceContainerLowest = Color(0xFFDACCEC),
|
||||||
|
surfaceContainerLow = Color(0xFFDED0F1),
|
||||||
|
surfaceContainer = Color(0xFFE4D5F8), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFEADCFD),
|
||||||
|
surfaceContainerHighest = Color(0xFFEEE2FF),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-14
@@ -23,24 +23,29 @@ internal object MidnightDuskColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFBD1C5C),
|
primaryContainer = Color(0xFFBD1C5C),
|
||||||
onPrimaryContainer = Color(0xFFFFFFFF),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFFF02475),
|
inversePrimary = Color(0xFFF02475),
|
||||||
secondary = Color(0xFFF02475),
|
secondary = Color(0xFFF02475), // Unread badge
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFF16151D), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFF02475),
|
secondaryContainer = Color(0xFF66183C), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFFFFFFFF),
|
onSecondaryContainer = Color(0xFFF02475), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF55971C),
|
tertiary = Color(0xFF55971C), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFF16151D), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF386412),
|
tertiaryContainer = Color(0xFF386412),
|
||||||
onTertiaryContainer = Color(0xFFE5E1E5),
|
onTertiaryContainer = Color(0xFFE5E1E5),
|
||||||
background = Color(0xFF16151D),
|
background = Color(0xFF16151D),
|
||||||
onBackground = Color(0xFFE5E1E5),
|
onBackground = Color(0xFFE5E1E5),
|
||||||
surface = Color(0xFF16151D),
|
surface = Color(0xFF16151D),
|
||||||
onSurface = Color(0xFFE5E1E5),
|
onSurface = Color(0xFFE5E1E5),
|
||||||
surfaceVariant = Color(0xFF524346),
|
surfaceVariant = Color(0xFF281624), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFD6C1C4),
|
onSurfaceVariant = Color(0xFFD6C1C4),
|
||||||
surfaceTint = Color(0xFFF02475),
|
surfaceTint = Color(0xFFF02475),
|
||||||
inverseSurface = Color(0xFF333043),
|
inverseSurface = Color(0xFF333043),
|
||||||
inverseOnSurface = Color(0xFFFFFFFF),
|
inverseOnSurface = Color(0xFFFFFFFF),
|
||||||
outline = Color(0xFF9F8C8F),
|
outline = Color(0xFF9F8C8F),
|
||||||
|
surfaceContainerLowest = Color(0xFF221320),
|
||||||
|
surfaceContainerLow = Color(0xFF251522),
|
||||||
|
surfaceContainer = Color(0xFF281624), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF2D1C2A),
|
||||||
|
surfaceContainerHighest = Color(0xFF2F1F2C),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -49,23 +54,28 @@ internal object MidnightDuskColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFFFD9E1),
|
primaryContainer = Color(0xFFFFD9E1),
|
||||||
onPrimaryContainer = Color(0xFF3F0017),
|
onPrimaryContainer = Color(0xFF3F0017),
|
||||||
inversePrimary = Color(0xFFFFB1C4),
|
inversePrimary = Color(0xFFFFB1C4),
|
||||||
secondary = Color(0xFFBB0054),
|
secondary = Color(0xFFBB0054), // Unread badge
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFFFD9E1),
|
secondaryContainer = Color(0xFFEFBAD4), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF3F0017),
|
onSecondaryContainer = Color(0xFFD1377C), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF006638),
|
tertiary = Color(0xFF006638), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF00894b),
|
tertiaryContainer = Color(0xFF00894b),
|
||||||
onTertiaryContainer = Color(0xFF2D1600),
|
onTertiaryContainer = Color(0xFF2D1600),
|
||||||
background = Color(0xFFFFFBFF),
|
background = Color(0xFFFFFBFF),
|
||||||
onBackground = Color(0xFF1C1B1F),
|
onBackground = Color(0xFF1C1B1F),
|
||||||
surface = Color(0xFFFFFBFF),
|
surface = Color(0xFFFFFBFF),
|
||||||
onSurface = Color(0xFF1C1B1F),
|
onSurface = Color(0xFF1C1B1F),
|
||||||
surfaceVariant = Color(0xFFF3DDE0),
|
surfaceVariant = Color(0xFFF9E6F1), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF524346),
|
onSurfaceVariant = Color(0xFF524346),
|
||||||
surfaceTint = Color(0xFFBB0054),
|
surfaceTint = Color(0xFFBB0054),
|
||||||
inverseSurface = Color(0xFF313033),
|
inverseSurface = Color(0xFF313033),
|
||||||
inverseOnSurface = Color(0xFFF4F0F4),
|
inverseOnSurface = Color(0xFFF4F0F4),
|
||||||
outline = Color(0xFF847376),
|
outline = Color(0xFF847376),
|
||||||
|
surfaceContainerLowest = Color(0xFFDAC0CD),
|
||||||
|
surfaceContainerLow = Color(0xFFE8D1DD),
|
||||||
|
surfaceContainer = Color(0xFFF9E6F1), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFFCF3F8),
|
||||||
|
surfaceContainerHighest = Color(0xFFFEF9FC),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,19 +17,19 @@ internal object NordColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF88C0D0),
|
primaryContainer = Color(0xFF88C0D0),
|
||||||
onPrimaryContainer = Color(0xFF2E3440),
|
onPrimaryContainer = Color(0xFF2E3440),
|
||||||
inversePrimary = Color(0xFF397E91),
|
inversePrimary = Color(0xFF397E91),
|
||||||
secondary = Color(0xFF81A1C1),
|
secondary = Color(0xFF81A1C1), // Unread badge
|
||||||
onSecondary = Color(0xFF2E3440),
|
onSecondary = Color(0xFF2E3440), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF81A1C1),
|
secondaryContainer = Color(0xFF506275), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF2E3440),
|
onSecondaryContainer = Color(0xFF88C0D0), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF5E81AC),
|
tertiary = Color(0xFF5E81AC), // Downloaded badge
|
||||||
onTertiary = Color(0xFF000000),
|
onTertiary = Color(0xFF000000), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF5E81AC),
|
tertiaryContainer = Color(0xFF5E81AC),
|
||||||
onTertiaryContainer = Color(0xFF000000),
|
onTertiaryContainer = Color(0xFF000000),
|
||||||
background = Color(0xFF2E3440),
|
background = Color(0xFF2E3440),
|
||||||
onBackground = Color(0xFFECEFF4),
|
onBackground = Color(0xFFECEFF4),
|
||||||
surface = Color(0xFF3B4252),
|
surface = Color(0xFF2E3440),
|
||||||
onSurface = Color(0xFFECEFF4),
|
onSurface = Color(0xFFECEFF4),
|
||||||
surfaceVariant = Color(0xFF2E3440),
|
surfaceVariant = Color(0xFF414C5C), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFECEFF4),
|
onSurfaceVariant = Color(0xFFECEFF4),
|
||||||
surfaceTint = Color(0xFF88C0D0),
|
surfaceTint = Color(0xFF88C0D0),
|
||||||
inverseSurface = Color(0xFFD8DEE9),
|
inverseSurface = Color(0xFFD8DEE9),
|
||||||
@@ -39,6 +39,11 @@ internal object NordColorScheme : BaseColorScheme() {
|
|||||||
onError = Color(0xFF2E3440),
|
onError = Color(0xFF2E3440),
|
||||||
errorContainer = Color(0xFFBF616A),
|
errorContainer = Color(0xFFBF616A),
|
||||||
onErrorContainer = Color(0xFF000000),
|
onErrorContainer = Color(0xFF000000),
|
||||||
|
surfaceContainerLowest = Color(0xFF373F4D),
|
||||||
|
surfaceContainerLow = Color(0xFF3E4756),
|
||||||
|
surfaceContainer = Color(0xFF414C5C),
|
||||||
|
surfaceContainerHigh = Color(0xFF4E5766),
|
||||||
|
surfaceContainerHighest = Color(0xFF505968), // Navigation bar background
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -47,19 +52,19 @@ internal object NordColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF5E81AC),
|
primaryContainer = Color(0xFF5E81AC),
|
||||||
onPrimaryContainer = Color(0xFF000000),
|
onPrimaryContainer = Color(0xFF000000),
|
||||||
inversePrimary = Color(0xFF8CA8CD),
|
inversePrimary = Color(0xFF8CA8CD),
|
||||||
secondary = Color(0xFF81A1C1),
|
secondary = Color(0xFF81A1C1), // Unread badge
|
||||||
onSecondary = Color(0xFF2E3440),
|
onSecondary = Color(0xFF2E3440), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF81A1C1),
|
secondaryContainer = Color(0xFF91B4D7), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF2E3440),
|
onSecondaryContainer = Color(0xFF2E3440), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF88C0D0),
|
tertiary = Color(0xFF88C0D0), // Downloaded badge
|
||||||
onTertiary = Color(0xFF2E3440),
|
onTertiary = Color(0xFF2E3440), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF88C0D0),
|
tertiaryContainer = Color(0xFF88C0D0),
|
||||||
onTertiaryContainer = Color(0xFF2E3440),
|
onTertiaryContainer = Color(0xFF2E3440),
|
||||||
background = Color(0xFFECEFF4),
|
background = Color(0xFFECEFF4),
|
||||||
onBackground = Color(0xFF2E3440),
|
onBackground = Color(0xFF2E3440),
|
||||||
surface = Color(0xFFE5E9F0),
|
surface = Color(0xFFE5E9F0),
|
||||||
onSurface = Color(0xFF2E3440),
|
onSurface = Color(0xFF2E3440),
|
||||||
surfaceVariant = Color(0xFFffffff),
|
surfaceVariant = Color(0xFFDAE0EA), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF2E3440),
|
onSurfaceVariant = Color(0xFF2E3440),
|
||||||
surfaceTint = Color(0xFF5E81AC),
|
surfaceTint = Color(0xFF5E81AC),
|
||||||
inverseSurface = Color(0xFF3B4252),
|
inverseSurface = Color(0xFF3B4252),
|
||||||
@@ -68,5 +73,10 @@ internal object NordColorScheme : BaseColorScheme() {
|
|||||||
onError = Color(0xFFECEFF4),
|
onError = Color(0xFFECEFF4),
|
||||||
errorContainer = Color(0xFFBF616A),
|
errorContainer = Color(0xFFBF616A),
|
||||||
onErrorContainer = Color(0xFF000000),
|
onErrorContainer = Color(0xFF000000),
|
||||||
|
surfaceContainerLowest = Color(0xFFD1D7E0),
|
||||||
|
surfaceContainerLow = Color(0xFFD6DCE6),
|
||||||
|
surfaceContainer = Color(0xFFDAE0EA), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFE9EDF3),
|
||||||
|
surfaceContainerHighest = Color(0xFFF2F4F8),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-43
@@ -18,54 +18,78 @@ import androidx.compose.ui.graphics.Color
|
|||||||
internal object StrawberryColorScheme : BaseColorScheme() {
|
internal object StrawberryColorScheme : BaseColorScheme() {
|
||||||
|
|
||||||
override val darkScheme = darkColorScheme(
|
override val darkScheme = darkColorScheme(
|
||||||
primary = Color(0xFFFFB2B9),
|
primary = Color(0xFFFFB2B8),
|
||||||
onPrimary = Color(0xFF67001B),
|
onPrimary = Color(0xFF67001D),
|
||||||
primaryContainer = Color(0xFF91002A),
|
primaryContainer = Color(0xFFD53855),
|
||||||
onPrimaryContainer = Color(0xFFFFDADD),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFFB61E40),
|
secondary = Color(0xFFED4A65), // Unread badge
|
||||||
secondary = Color(0xFFFFB2B9),
|
onSecondary = Color(0xFF201A1A), // Unread badge text
|
||||||
onSecondary = Color(0xFF67001B),
|
secondaryContainer = Color(0xFF91002A), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
secondaryContainer = Color(0xFF91002A),
|
onSecondaryContainer = Color(0xFFFFFFFF), // Navigation bar selector icon
|
||||||
onSecondaryContainer = Color(0xFFFFDADD),
|
tertiary = Color(0xFFE8C08E), // Downloaded badge
|
||||||
tertiary = Color(0xFFE8C08E),
|
onTertiary = Color(0xFF201A1A), // Downloaded badge text
|
||||||
onTertiary = Color(0xFF432C06),
|
tertiaryContainer = Color(0xFF775930),
|
||||||
tertiaryContainer = Color(0xFF5D421B),
|
onTertiaryContainer = Color(0xFFFFF7F1),
|
||||||
onTertiaryContainer = Color(0xFFFFDDB1),
|
error = Color(0xFFFFB4AB),
|
||||||
|
onError = Color(0xFF690005),
|
||||||
|
errorContainer = Color(0xFF93000A),
|
||||||
|
onErrorContainer = Color(0xFFFFDAD6),
|
||||||
background = Color(0xFF201A1A),
|
background = Color(0xFF201A1A),
|
||||||
onBackground = Color(0xFFECDFDF),
|
onBackground = Color(0xFFF7DCDD),
|
||||||
surface = Color(0xFF201A1A),
|
surface = Color(0xFF201A1A),
|
||||||
onSurface = Color(0xFFECDFDF),
|
onSurface = Color(0xFFF7DCDD),
|
||||||
surfaceVariant = Color(0xFF534344),
|
surfaceVariant = Color(0xFF322727), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFD7C1C2),
|
onSurfaceVariant = Color(0xFFE1BEC0),
|
||||||
surfaceTint = Color(0xFFFFB2B9),
|
outline = Color(0xFFA9898B),
|
||||||
inverseSurface = Color(0xFFECDFDF),
|
outlineVariant = Color(0xFF594042),
|
||||||
inverseOnSurface = Color(0xFF201A1A),
|
scrim = Color(0xFF000000),
|
||||||
outline = Color(0xFFA08C8D),
|
inverseSurface = Color(0xFFF7DCDD),
|
||||||
|
inverseOnSurface = Color(0xFF3D2C2D),
|
||||||
|
inversePrimary = Color(0xFFB61F40),
|
||||||
|
surfaceDim = Color(0xFF1D1011),
|
||||||
|
surfaceBright = Color(0xFF463536),
|
||||||
|
surfaceContainerLowest = Color(0xFF2C2222),
|
||||||
|
surfaceContainerLow = Color(0xFF302525),
|
||||||
|
surfaceContainer = Color(0xFF322727), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF3C2F2F),
|
||||||
|
surfaceContainerHighest = Color(0xFF463737),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
primary = Color(0xFFB61E40),
|
primary = Color(0xFFA10833),
|
||||||
onPrimary = Color(0xFFFFFFFF),
|
onPrimary = Color(0xFFFFFFFF),
|
||||||
primaryContainer = Color(0xFFFFDADD),
|
primaryContainer = Color(0xFFD53855),
|
||||||
onPrimaryContainer = Color(0xFF40000D),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFFFFB2B9),
|
secondary = Color(0xFFA10833), // Unread badge
|
||||||
secondary = Color(0xFFB61E40),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
secondaryContainer = Color(0xFFD53855), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
secondaryContainer = Color(0xFFFFDADD),
|
onSecondaryContainer = Color(0xFFF6EAED), // Navigation bar selector icon
|
||||||
onSecondaryContainer = Color(0xFF40000D),
|
tertiary = Color(0xFF5F441D), // Downloaded badge
|
||||||
tertiary = Color(0xFF775930),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
tertiaryContainer = Color(0xFF87683D),
|
||||||
tertiaryContainer = Color(0xFFFFDDB1),
|
onTertiaryContainer = Color(0xFFFFFFFF),
|
||||||
onTertiaryContainer = Color(0xFF2A1800),
|
error = Color(0xFFBA1A1A),
|
||||||
background = Color(0xFFFCFCFC),
|
onError = Color(0xFFFFFFFF),
|
||||||
onBackground = Color(0xFF201A1A),
|
errorContainer = Color(0xFFFFDAD6),
|
||||||
surface = Color(0xFFFCFCFC),
|
onErrorContainer = Color(0xFF410002),
|
||||||
onSurface = Color(0xFF201A1A),
|
background = Color(0xFFFAFAFA),
|
||||||
surfaceVariant = Color(0xFFF4DDDD),
|
onBackground = Color(0xFF261819),
|
||||||
onSurfaceVariant = Color(0xFF534344),
|
surface = Color(0xFFFAFAFA),
|
||||||
surfaceTint = Color(0xFFB61E40),
|
onSurface = Color(0xFF261819),
|
||||||
inverseSurface = Color(0xFF362F2F),
|
surfaceVariant = Color(0xFFF6EAED), // Navigation bar background (ThemePrefWidget)
|
||||||
inverseOnSurface = Color(0xFFFBEDED),
|
onSurfaceVariant = Color(0xFF594042),
|
||||||
outline = Color(0xFF857374),
|
outline = Color(0xFF8D7071),
|
||||||
|
outlineVariant = Color(0xFFE1BEC0),
|
||||||
|
scrim = Color(0xFF000000),
|
||||||
|
inverseSurface = Color(0xFF3D2C2D),
|
||||||
|
inverseOnSurface = Color(0xFFFFECED),
|
||||||
|
inversePrimary = Color(0xFFFFB2B8),
|
||||||
|
surfaceDim = Color(0xFFEED4D5),
|
||||||
|
surfaceBright = Color(0xFFFFF8F7),
|
||||||
|
surfaceContainerLowest = Color(0xFFF7DCDD),
|
||||||
|
surfaceContainerLow = Color(0xFFFDE2E3),
|
||||||
|
surfaceContainer = Color(0xFFF6EAED), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFFFF0F0),
|
||||||
|
surfaceContainerHighest = Color(0xFFFFFFFF),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-14
@@ -22,19 +22,19 @@ internal object TachiyomiColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF00429B),
|
primaryContainer = Color(0xFF00429B),
|
||||||
onPrimaryContainer = Color(0xFFD9E2FF),
|
onPrimaryContainer = Color(0xFFD9E2FF),
|
||||||
inversePrimary = Color(0xFF0058CA),
|
inversePrimary = Color(0xFF0058CA),
|
||||||
secondary = Color(0xFFB0C6FF),
|
secondary = Color(0xFFB0C6FF), // Unread badge
|
||||||
onSecondary = Color(0xFF002D6E),
|
onSecondary = Color(0xFF002D6E), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF00429B),
|
secondaryContainer = Color(0xFF00429B), // Navigation bar selector pill & pro
|
||||||
onSecondaryContainer = Color(0xFFD9E2FF),
|
onSecondaryContainer = Color(0xFFD9E2FF), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF7ADC77),
|
tertiary = Color(0xFF7ADC77), // Downloaded badge
|
||||||
onTertiary = Color(0xFF003909),
|
onTertiary = Color(0xFF003909), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF005312),
|
tertiaryContainer = Color(0xFF005312),
|
||||||
onTertiaryContainer = Color(0xFF95F990),
|
onTertiaryContainer = Color(0xFF95F990),
|
||||||
background = Color(0xFF1B1B1F),
|
background = Color(0xFF1B1B1F),
|
||||||
onBackground = Color(0xFFE3E2E6),
|
onBackground = Color(0xFFE3E2E6),
|
||||||
surface = Color(0xFF1B1B1F),
|
surface = Color(0xFF1B1B1F),
|
||||||
onSurface = Color(0xFFE3E2E6),
|
onSurface = Color(0xFFE3E2E6),
|
||||||
surfaceVariant = Color(0xFF44464F),
|
surfaceVariant = Color(0xFF211F26), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFC5C6D0),
|
onSurfaceVariant = Color(0xFFC5C6D0),
|
||||||
surfaceTint = Color(0xFFB0C6FF),
|
surfaceTint = Color(0xFFB0C6FF),
|
||||||
inverseSurface = Color(0xFFE3E2E6),
|
inverseSurface = Color(0xFFE3E2E6),
|
||||||
@@ -45,6 +45,11 @@ internal object TachiyomiColorScheme : BaseColorScheme() {
|
|||||||
onErrorContainer = Color(0xFFFFDAD6),
|
onErrorContainer = Color(0xFFFFDAD6),
|
||||||
outline = Color(0xFF8F9099),
|
outline = Color(0xFF8F9099),
|
||||||
outlineVariant = Color(0xFF44464F),
|
outlineVariant = Color(0xFF44464F),
|
||||||
|
surfaceContainerLowest = Color(0xFF1A181D),
|
||||||
|
surfaceContainerLow = Color(0xFF1E1C22),
|
||||||
|
surfaceContainer = Color(0xFF211F26), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF292730),
|
||||||
|
surfaceContainerHighest = Color(0xFF302E38),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -53,19 +58,19 @@ internal object TachiyomiColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFD9E2FF),
|
primaryContainer = Color(0xFFD9E2FF),
|
||||||
onPrimaryContainer = Color(0xFF001945),
|
onPrimaryContainer = Color(0xFF001945),
|
||||||
inversePrimary = Color(0xFFB0C6FF),
|
inversePrimary = Color(0xFFB0C6FF),
|
||||||
secondary = Color(0xFF0058CA),
|
secondary = Color(0xFF0058CA), // Unread badge
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFD9E2FF),
|
secondaryContainer = Color(0xFFD9E2FF), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF001945),
|
onSecondaryContainer = Color(0xFF001945), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF006E1B),
|
tertiary = Color(0xFF006E1B), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF95F990),
|
tertiaryContainer = Color(0xFF95F990),
|
||||||
onTertiaryContainer = Color(0xFF002203),
|
onTertiaryContainer = Color(0xFF002203),
|
||||||
background = Color(0xFFFEFBFF),
|
background = Color(0xFFFEFBFF),
|
||||||
onBackground = Color(0xFF1B1B1F),
|
onBackground = Color(0xFF1B1B1F),
|
||||||
surface = Color(0xFFFEFBFF),
|
surface = Color(0xFFFEFBFF),
|
||||||
onSurface = Color(0xFF1B1B1F),
|
onSurface = Color(0xFF1B1B1F),
|
||||||
surfaceVariant = Color(0xFFE1E2EC),
|
surfaceVariant = Color(0xFFF3EDF7), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF44464F),
|
onSurfaceVariant = Color(0xFF44464F),
|
||||||
surfaceTint = Color(0xFF0058CA),
|
surfaceTint = Color(0xFF0058CA),
|
||||||
inverseSurface = Color(0xFF303034),
|
inverseSurface = Color(0xFF303034),
|
||||||
@@ -76,5 +81,10 @@ internal object TachiyomiColorScheme : BaseColorScheme() {
|
|||||||
onErrorContainer = Color(0xFF410002),
|
onErrorContainer = Color(0xFF410002),
|
||||||
outline = Color(0xFF757780),
|
outline = Color(0xFF757780),
|
||||||
outlineVariant = Color(0xFFC5C6D0),
|
outlineVariant = Color(0xFFC5C6D0),
|
||||||
|
surfaceContainerLowest = Color(0xFFF5F1F8),
|
||||||
|
surfaceContainerLow = Color(0xFFF7F2FA),
|
||||||
|
surfaceContainer = Color(0xFFF3EDF7), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFFCF7FF),
|
||||||
|
surfaceContainerHighest = Color(0xFFFCF7FF),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,24 +23,29 @@ internal object TakoColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFF3B375),
|
primaryContainer = Color(0xFFF3B375),
|
||||||
onPrimaryContainer = Color(0xFF38294E),
|
onPrimaryContainer = Color(0xFF38294E),
|
||||||
inversePrimary = Color(0xFF84531E),
|
inversePrimary = Color(0xFF84531E),
|
||||||
secondary = Color(0xFFF3B375),
|
secondary = Color(0xFFF3B375), // Unread badge
|
||||||
onSecondary = Color(0xFF38294E),
|
onSecondary = Color(0xFF38294E), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFF3B375),
|
secondaryContainer = Color(0xFF5C4D4B), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF38294E),
|
onSecondaryContainer = Color(0xFFF3B375), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF66577E),
|
tertiary = Color(0xFF66577E), // Downloaded badge
|
||||||
onTertiary = Color(0xFFF3B375),
|
onTertiary = Color(0xFFF3B375), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF4E4065),
|
tertiaryContainer = Color(0xFF4E4065),
|
||||||
onTertiaryContainer = Color(0xFFEDDCFF),
|
onTertiaryContainer = Color(0xFFEDDCFF),
|
||||||
background = Color(0xFF21212E),
|
background = Color(0xFF21212E),
|
||||||
onBackground = Color(0xFFE3E0F2),
|
onBackground = Color(0xFFE3E0F2),
|
||||||
surface = Color(0xFF21212E),
|
surface = Color(0xFF21212E),
|
||||||
onSurface = Color(0xFFE3E0F2),
|
onSurface = Color(0xFFE3E0F2),
|
||||||
surfaceVariant = Color(0xFF49454E),
|
surfaceVariant = Color(0xFF2A2A3C), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFCBC4CE),
|
onSurfaceVariant = Color(0xFFCBC4CE),
|
||||||
surfaceTint = Color(0xFF66577E),
|
surfaceTint = Color(0xFF66577E),
|
||||||
inverseSurface = Color(0xFFE5E1E6),
|
inverseSurface = Color(0xFFE5E1E6),
|
||||||
inverseOnSurface = Color(0xFF1B1B1E),
|
inverseOnSurface = Color(0xFF1B1B1E),
|
||||||
outline = Color(0xFF958F99),
|
outline = Color(0xFF958F99),
|
||||||
|
surfaceContainerLowest = Color(0xFF20202E),
|
||||||
|
surfaceContainerLow = Color(0xFF262636),
|
||||||
|
surfaceContainer = Color(0xFF2A2A3C), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF303044),
|
||||||
|
surfaceContainerHighest = Color(0xFF36364D),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -49,23 +54,28 @@ internal object TakoColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF66577E),
|
primaryContainer = Color(0xFF66577E),
|
||||||
onPrimaryContainer = Color(0xFFF3B375),
|
onPrimaryContainer = Color(0xFFF3B375),
|
||||||
inversePrimary = Color(0xFFD6BAFF),
|
inversePrimary = Color(0xFFD6BAFF),
|
||||||
secondary = Color(0xFF66577E),
|
secondary = Color(0xFF66577E), // Unread badge
|
||||||
onSecondary = Color(0xFFF3B375),
|
onSecondary = Color(0xFFF3B375), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF66577E),
|
secondaryContainer = Color(0xFFC8BED0), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFFF3B375),
|
onSecondaryContainer = Color(0xFF66577E), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFFF3B375),
|
tertiary = Color(0xFFF3B375), // Downloaded badge
|
||||||
onTertiary = Color(0xFF574360),
|
onTertiary = Color(0xFF574360), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFFFDD6B0),
|
tertiaryContainer = Color(0xFFFDD6B0),
|
||||||
onTertiaryContainer = Color(0xFF221437),
|
onTertiaryContainer = Color(0xFF221437),
|
||||||
background = Color(0xFFF7F5FF),
|
background = Color(0xFFF7F5FF),
|
||||||
onBackground = Color(0xFF1B1B22),
|
onBackground = Color(0xFF1B1B22),
|
||||||
surface = Color(0xFFF7F5FF),
|
surface = Color(0xFFF7F5FF),
|
||||||
onSurface = Color(0xFF1B1B22),
|
onSurface = Color(0xFF1B1B22),
|
||||||
surfaceVariant = Color(0xFFE8E0EB),
|
surfaceVariant = Color(0xFFE8E0EB), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF49454E),
|
onSurfaceVariant = Color(0xFF49454E),
|
||||||
surfaceTint = Color(0xFF66577E),
|
surfaceTint = Color(0xFF66577E),
|
||||||
inverseSurface = Color(0xFF313033),
|
inverseSurface = Color(0xFF313033),
|
||||||
inverseOnSurface = Color(0xFFF3EFF4),
|
inverseOnSurface = Color(0xFFF3EFF4),
|
||||||
outline = Color(0xFF7A757E),
|
outline = Color(0xFF7A757E),
|
||||||
|
surfaceContainerLowest = Color(0xFFD7D0DA),
|
||||||
|
surfaceContainerLow = Color(0xFFDFD8E2),
|
||||||
|
surfaceContainer = Color(0xFFE8E0EB), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFEEE6F1),
|
||||||
|
surfaceContainerHighest = Color(0xFFF7EEFA),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-14
@@ -15,24 +15,29 @@ internal object TealTurqoiseColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF40E0D0),
|
primaryContainer = Color(0xFF40E0D0),
|
||||||
onPrimaryContainer = Color(0xFF000000),
|
onPrimaryContainer = Color(0xFF000000),
|
||||||
inversePrimary = Color(0xFF008080),
|
inversePrimary = Color(0xFF008080),
|
||||||
secondary = Color(0xFF40E0D0),
|
secondary = Color(0xFF40E0D0), // Unread badge
|
||||||
onSecondary = Color(0xFF000000),
|
onSecondary = Color(0xFF000000), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF18544E),
|
secondaryContainer = Color(0xFF18544E), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF40E0D0),
|
onSecondaryContainer = Color(0xFF40E0D0), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFFBF1F2F),
|
tertiary = Color(0xFFBF1F2F), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF200508),
|
tertiaryContainer = Color(0xFF200508),
|
||||||
onTertiaryContainer = Color(0xFFBF1F2F),
|
onTertiaryContainer = Color(0xFFBF1F2F),
|
||||||
background = Color(0xFF202125),
|
background = Color(0xFF202125),
|
||||||
onBackground = Color(0xFFDFDEDA),
|
onBackground = Color(0xFFDFDEDA),
|
||||||
surface = Color(0xFF202125),
|
surface = Color(0xFF202125),
|
||||||
onSurface = Color(0xFFDFDEDA),
|
onSurface = Color(0xFFDFDEDA),
|
||||||
surfaceVariant = Color(0xFF3F4947),
|
surfaceVariant = Color(0xFF233133), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFDFDEDA),
|
onSurfaceVariant = Color(0xFFDFDEDA),
|
||||||
surfaceTint = Color(0xFF40E0D0),
|
surfaceTint = Color(0xFF40E0D0),
|
||||||
inverseSurface = Color(0xFFDFDEDA),
|
inverseSurface = Color(0xFFDFDEDA),
|
||||||
inverseOnSurface = Color(0xFF202125),
|
inverseOnSurface = Color(0xFF202125),
|
||||||
outline = Color(0xFF899391),
|
outline = Color(0xFF899391),
|
||||||
|
surfaceContainerLowest = Color(0xFF202C2E),
|
||||||
|
surfaceContainerLow = Color(0xFF222F31),
|
||||||
|
surfaceContainer = Color(0xFF233133), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF28383A),
|
||||||
|
surfaceContainerHighest = Color(0xFF2F4244),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -41,23 +46,28 @@ internal object TealTurqoiseColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF008080),
|
primaryContainer = Color(0xFF008080),
|
||||||
onPrimaryContainer = Color(0xFFFFFFFF),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFF40E0D0),
|
inversePrimary = Color(0xFF40E0D0),
|
||||||
secondary = Color(0xFF008080),
|
secondary = Color(0xFF008080), // Unread badge text
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFBFDFDF),
|
secondaryContainer = Color(0xFFCFE5E4), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF008080),
|
onSecondaryContainer = Color(0xFF008080), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFFFF7F7F),
|
tertiary = Color(0xFFFF7F7F), // Downloaded badge
|
||||||
onTertiary = Color(0xFF000000),
|
onTertiary = Color(0xFF000000), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF2A1616),
|
tertiaryContainer = Color(0xFF2A1616),
|
||||||
onTertiaryContainer = Color(0xFFFF7F7F),
|
onTertiaryContainer = Color(0xFFFF7F7F),
|
||||||
background = Color(0xFFFAFAFA),
|
background = Color(0xFFFAFAFA),
|
||||||
onBackground = Color(0xFF050505),
|
onBackground = Color(0xFF050505),
|
||||||
surface = Color(0xFFFAFAFA),
|
surface = Color(0xFFFAFAFA),
|
||||||
onSurface = Color(0xFF050505),
|
onSurface = Color(0xFF050505),
|
||||||
surfaceVariant = Color(0xFFDAE5E2),
|
surfaceVariant = Color(0xFFEBF3F1), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF050505),
|
onSurfaceVariant = Color(0xFF050505),
|
||||||
surfaceTint = Color(0xFFBFDFDF),
|
surfaceTint = Color(0xFFBFDFDF),
|
||||||
inverseSurface = Color(0xFF050505),
|
inverseSurface = Color(0xFF050505),
|
||||||
inverseOnSurface = Color(0xFFFAFAFA),
|
inverseOnSurface = Color(0xFFFAFAFA),
|
||||||
outline = Color(0xFF6F7977),
|
outline = Color(0xFF6F7977),
|
||||||
|
surfaceContainerLowest = Color(0xFFE1E9E7),
|
||||||
|
surfaceContainerLow = Color(0xFFE6EEEC),
|
||||||
|
surfaceContainer = Color(0xFFEBF3F1), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFF0F8F6),
|
||||||
|
surfaceContainerHighest = Color(0xFFF7FFFD),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-14
@@ -22,24 +22,29 @@ internal object TidalWaveColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF004d61),
|
primaryContainer = Color(0xFF004d61),
|
||||||
onPrimaryContainer = Color(0xFFb8eaff),
|
onPrimaryContainer = Color(0xFFb8eaff),
|
||||||
inversePrimary = Color(0xFFa12b03),
|
inversePrimary = Color(0xFFa12b03),
|
||||||
secondary = Color(0xFF5ed4fc),
|
secondary = Color(0xFF5ed4fc), // Unread badge
|
||||||
onSecondary = Color(0xFF003544),
|
onSecondary = Color(0xFF003544), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF004d61),
|
secondaryContainer = Color(0xFF004d61), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFFb8eaff),
|
onSecondaryContainer = Color(0xFFb8eaff), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF92f7bc),
|
tertiary = Color(0xFF92f7bc), // Downloaded badge
|
||||||
onTertiary = Color(0xFF001c3b),
|
onTertiary = Color(0xFF001c3b), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFFc3fada),
|
tertiaryContainer = Color(0xFFc3fada),
|
||||||
onTertiaryContainer = Color(0xFF78ffd6),
|
onTertiaryContainer = Color(0xFF78ffd6),
|
||||||
background = Color(0xFF001c3b),
|
background = Color(0xFF001c3b),
|
||||||
onBackground = Color(0xFFd5e3ff),
|
onBackground = Color(0xFFd5e3ff),
|
||||||
surface = Color(0xFF001c3b),
|
surface = Color(0xFF001c3b),
|
||||||
onSurface = Color(0xFFd5e3ff),
|
onSurface = Color(0xFFd5e3ff),
|
||||||
surfaceVariant = Color(0xFF40484c),
|
surfaceVariant = Color(0xFF082b4b), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFbfc8cc),
|
onSurfaceVariant = Color(0xFFbfc8cc),
|
||||||
surfaceTint = Color(0xFF5ed4fc),
|
surfaceTint = Color(0xFF5ed4fc),
|
||||||
inverseSurface = Color(0xFFffe3c4),
|
inverseSurface = Color(0xFFffe3c4),
|
||||||
inverseOnSurface = Color(0xFF001c3b),
|
inverseOnSurface = Color(0xFF001c3b),
|
||||||
outline = Color(0xFF8a9296),
|
outline = Color(0xFF8a9296),
|
||||||
|
surfaceContainerLowest = Color(0xFF072642),
|
||||||
|
surfaceContainerLow = Color(0xFF072947),
|
||||||
|
surfaceContainer = Color(0xFF082b4b), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF093257),
|
||||||
|
surfaceContainerHighest = Color(0xFF0A3861),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -48,23 +53,28 @@ internal object TidalWaveColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFB4D4DF),
|
primaryContainer = Color(0xFFB4D4DF),
|
||||||
onPrimaryContainer = Color(0xFF001f28),
|
onPrimaryContainer = Color(0xFF001f28),
|
||||||
inversePrimary = Color(0xFFff987f),
|
inversePrimary = Color(0xFFff987f),
|
||||||
secondary = Color(0xFF006780),
|
secondary = Color(0xFF006780), // Unread badge
|
||||||
onSecondary = Color(0xFFffffff),
|
onSecondary = Color(0xFFffffff), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFb8eaff),
|
secondaryContainer = Color(0xFF9AE1FF), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF001f28),
|
onSecondaryContainer = Color(0xFF001f28), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF92f7bc),
|
tertiary = Color(0xFF92f7bc), // Downloaded badge
|
||||||
onTertiary = Color(0xFF001c3b),
|
onTertiary = Color(0xFF001c3b), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFFc3fada),
|
tertiaryContainer = Color(0xFFc3fada),
|
||||||
onTertiaryContainer = Color(0xFF78ffd6),
|
onTertiaryContainer = Color(0xFF78ffd6),
|
||||||
background = Color(0xFFfdfbff),
|
background = Color(0xFFfdfbff),
|
||||||
onBackground = Color(0xFF001c3b),
|
onBackground = Color(0xFF001c3b),
|
||||||
surface = Color(0xFFfdfbff),
|
surface = Color(0xFFfdfbff),
|
||||||
onSurface = Color(0xFF001c3b),
|
onSurface = Color(0xFF001c3b),
|
||||||
surfaceVariant = Color(0xFFdce4e8),
|
surfaceVariant = Color(0xFFe8eff5), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF40484c),
|
onSurfaceVariant = Color(0xFF40484c),
|
||||||
surfaceTint = Color(0xFF006780),
|
surfaceTint = Color(0xFF006780),
|
||||||
inverseSurface = Color(0xFF020400),
|
inverseSurface = Color(0xFF020400),
|
||||||
inverseOnSurface = Color(0xFFffe3c4),
|
inverseOnSurface = Color(0xFFffe3c4),
|
||||||
outline = Color(0xFF70787c),
|
outline = Color(0xFF70787c),
|
||||||
|
surfaceContainerLowest = Color(0xFFe2e8ec),
|
||||||
|
surfaceContainerLow = Color(0xFFe5ecf1),
|
||||||
|
surfaceContainer = Color(0xFFe8eff5), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFedf4fA),
|
||||||
|
surfaceContainerHighest = Color(0xFFf5faff),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,29 @@ internal object YinYangColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFFFFFFF),
|
primaryContainer = Color(0xFFFFFFFF),
|
||||||
onPrimaryContainer = Color(0xFF000000),
|
onPrimaryContainer = Color(0xFF000000),
|
||||||
inversePrimary = Color(0xFFCECECE),
|
inversePrimary = Color(0xFFCECECE),
|
||||||
secondary = Color(0xFFFFFFFF),
|
secondary = Color(0xFFFFFFFF), // Unread badge
|
||||||
onSecondary = Color(0xFF5A5A5A),
|
onSecondary = Color(0xFF5A5A5A), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF717171),
|
secondaryContainer = Color(0xFF717171), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFFE4E4E4),
|
onSecondaryContainer = Color(0xFFE4E4E4), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF000000),
|
tertiary = Color(0xFF000000), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF00419E),
|
tertiaryContainer = Color(0xFF00419E),
|
||||||
onTertiaryContainer = Color(0xFFD8E2FF),
|
onTertiaryContainer = Color(0xFFD8E2FF),
|
||||||
background = Color(0xFF1E1E1E),
|
background = Color(0xFF1E1E1E),
|
||||||
onBackground = Color(0xFFE6E6E6),
|
onBackground = Color(0xFFE6E6E6),
|
||||||
surface = Color(0xFF1E1E1E),
|
surface = Color(0xFF1E1E1E),
|
||||||
onSurface = Color(0xFFE6E6E6),
|
onSurface = Color(0xFFE6E6E6),
|
||||||
surfaceVariant = Color(0xFF4E4E4E),
|
surfaceVariant = Color(0xFF313131), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFD1D1D1),
|
onSurfaceVariant = Color(0xFFD1D1D1),
|
||||||
surfaceTint = Color(0xFFFFFFFF),
|
surfaceTint = Color(0xFFFFFFFF),
|
||||||
inverseSurface = Color(0xFFE6E6E6),
|
inverseSurface = Color(0xFFE6E6E6),
|
||||||
inverseOnSurface = Color(0xFF1E1E1E),
|
inverseOnSurface = Color(0xFF1E1E1E),
|
||||||
outline = Color(0xFF999999),
|
outline = Color(0xFF999999),
|
||||||
|
surfaceContainerLowest = Color(0xFF2A2A2A),
|
||||||
|
surfaceContainerLow = Color(0xFF2D2D2D),
|
||||||
|
surfaceContainer = Color(0xFF313131), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF383838),
|
||||||
|
surfaceContainerHighest = Color(0xFF3F3F3F),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -43,23 +48,28 @@ internal object YinYangColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF000000),
|
primaryContainer = Color(0xFF000000),
|
||||||
onPrimaryContainer = Color(0xFFFFFFFF),
|
onPrimaryContainer = Color(0xFFFFFFFF),
|
||||||
inversePrimary = Color(0xFFA6A6A6),
|
inversePrimary = Color(0xFFA6A6A6),
|
||||||
secondary = Color(0xFF000000),
|
secondary = Color(0xFF000000), // Unread badge
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFDDDDDD),
|
secondaryContainer = Color(0xFFDDDDDD), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF0C0C0C),
|
onSecondaryContainer = Color(0xFF0C0C0C), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFFFFFFFF),
|
tertiary = Color(0xFFFFFFFF), // Downloaded badge
|
||||||
onTertiary = Color(0xFF000000),
|
onTertiary = Color(0xFF000000), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFFD8E2FF),
|
tertiaryContainer = Color(0xFFD8E2FF),
|
||||||
onTertiaryContainer = Color(0xFF001947),
|
onTertiaryContainer = Color(0xFF001947),
|
||||||
background = Color(0xFFFDFDFD),
|
background = Color(0xFFFDFDFD),
|
||||||
onBackground = Color(0xFF222222),
|
onBackground = Color(0xFF222222),
|
||||||
surface = Color(0xFFFDFDFD),
|
surface = Color(0xFFFDFDFD),
|
||||||
onSurface = Color(0xFF222222),
|
onSurface = Color(0xFF222222),
|
||||||
surfaceVariant = Color(0xFFEDEDED),
|
surfaceVariant = Color(0xFFE8E8E8), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF515151),
|
onSurfaceVariant = Color(0xFF515151),
|
||||||
surfaceTint = Color(0xFF000000),
|
surfaceTint = Color(0xFF000000),
|
||||||
inverseSurface = Color(0xFF333333),
|
inverseSurface = Color(0xFF333333),
|
||||||
inverseOnSurface = Color(0xFFF4F4F4),
|
inverseOnSurface = Color(0xFFF4F4F4),
|
||||||
outline = Color(0xFF838383),
|
outline = Color(0xFF838383),
|
||||||
|
surfaceContainerLowest = Color(0xFFCFCFCF),
|
||||||
|
surfaceContainerLow = Color(0xFFDADADA),
|
||||||
|
surfaceContainer = Color(0xFFE8E8E8), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFECECEC),
|
||||||
|
surfaceContainerHighest = Color(0xFFEFEFEF),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,24 +23,29 @@ internal object YotsubaColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFF862200),
|
primaryContainer = Color(0xFF862200),
|
||||||
onPrimaryContainer = Color(0xFFFFDBCF),
|
onPrimaryContainer = Color(0xFFFFDBCF),
|
||||||
inversePrimary = Color(0xFFAE3200),
|
inversePrimary = Color(0xFFAE3200),
|
||||||
secondary = Color(0xFFFFB59D),
|
secondary = Color(0xFFFFB59D), // Unread badge
|
||||||
onSecondary = Color(0xFF5F1600),
|
onSecondary = Color(0xFF5F1600), // Unread badge text
|
||||||
secondaryContainer = Color(0xFF862200),
|
secondaryContainer = Color(0xFF862200), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFFFFDBCF),
|
onSecondaryContainer = Color(0xFFFFDBCF), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFFD7C68D),
|
tertiary = Color(0xFFD7C68D), // Downloaded badge
|
||||||
onTertiary = Color(0xFF3A2F05),
|
onTertiary = Color(0xFF3A2F05), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFF524619),
|
tertiaryContainer = Color(0xFF524619),
|
||||||
onTertiaryContainer = Color(0xFFF5E2A7),
|
onTertiaryContainer = Color(0xFFF5E2A7),
|
||||||
background = Color(0xFF211A18),
|
background = Color(0xFF211A18),
|
||||||
onBackground = Color(0xFFEDE0DD),
|
onBackground = Color(0xFFEDE0DD),
|
||||||
surface = Color(0xFF211A18),
|
surface = Color(0xFF211A18),
|
||||||
onSurface = Color(0xFFEDE0DD),
|
onSurface = Color(0xFFEDE0DD),
|
||||||
surfaceVariant = Color(0xFF53433F),
|
surfaceVariant = Color(0xFF332723), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFFD8C2BC),
|
onSurfaceVariant = Color(0xFFD8C2BC),
|
||||||
surfaceTint = Color(0xFFFFB59D),
|
surfaceTint = Color(0xFFFFB59D),
|
||||||
inverseSurface = Color(0xFFEDE0DD),
|
inverseSurface = Color(0xFFEDE0DD),
|
||||||
inverseOnSurface = Color(0xFF211A18),
|
inverseOnSurface = Color(0xFF211A18),
|
||||||
outline = Color(0xFFA08C87),
|
outline = Color(0xFFA08C87),
|
||||||
|
surfaceContainerLowest = Color(0xFF2E221F),
|
||||||
|
surfaceContainerLow = Color(0xFF312521),
|
||||||
|
surfaceContainer = Color(0xFF332723), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFF413531),
|
||||||
|
surfaceContainerHighest = Color(0xFF4C403D),
|
||||||
)
|
)
|
||||||
|
|
||||||
override val lightScheme = lightColorScheme(
|
override val lightScheme = lightColorScheme(
|
||||||
@@ -49,23 +54,28 @@ internal object YotsubaColorScheme : BaseColorScheme() {
|
|||||||
primaryContainer = Color(0xFFFFDBCF),
|
primaryContainer = Color(0xFFFFDBCF),
|
||||||
onPrimaryContainer = Color(0xFF3B0A00),
|
onPrimaryContainer = Color(0xFF3B0A00),
|
||||||
inversePrimary = Color(0xFFFFB59D),
|
inversePrimary = Color(0xFFFFB59D),
|
||||||
secondary = Color(0xFFAE3200),
|
secondary = Color(0xFFAE3200), // Unread badge
|
||||||
onSecondary = Color(0xFFFFFFFF),
|
onSecondary = Color(0xFFFFFFFF), // Unread badge text
|
||||||
secondaryContainer = Color(0xFFFFDBCF),
|
secondaryContainer = Color(0xFFEBCDC2), // Navigation bar selector pill & progress indicator (remaining)
|
||||||
onSecondaryContainer = Color(0xFF3B0A00),
|
onSecondaryContainer = Color(0xFF3B0A00), // Navigation bar selector icon
|
||||||
tertiary = Color(0xFF6B5E2F),
|
tertiary = Color(0xFF6B5E2F), // Downloaded badge
|
||||||
onTertiary = Color(0xFFFFFFFF),
|
onTertiary = Color(0xFFFFFFFF), // Downloaded badge text
|
||||||
tertiaryContainer = Color(0xFFF5E2A7),
|
tertiaryContainer = Color(0xFFF5E2A7),
|
||||||
onTertiaryContainer = Color(0xFF231B00),
|
onTertiaryContainer = Color(0xFF231B00),
|
||||||
background = Color(0xFFFCFCFC),
|
background = Color(0xFFFCFCFC),
|
||||||
onBackground = Color(0xFF211A18),
|
onBackground = Color(0xFF211A18),
|
||||||
surface = Color(0xFFFCFCFC),
|
surface = Color(0xFFFCFCFC),
|
||||||
onSurface = Color(0xFF211A18),
|
onSurface = Color(0xFF211A18),
|
||||||
surfaceVariant = Color(0xFFF5DED8),
|
surfaceVariant = Color(0xFFF6EBE7), // Navigation bar background (ThemePrefWidget)
|
||||||
onSurfaceVariant = Color(0xFF53433F),
|
onSurfaceVariant = Color(0xFF53433F),
|
||||||
surfaceTint = Color(0xFFAE3200),
|
surfaceTint = Color(0xFFAE3200),
|
||||||
inverseSurface = Color(0xFF362F2D),
|
inverseSurface = Color(0xFF362F2D),
|
||||||
inverseOnSurface = Color(0xFFFBEEEB),
|
inverseOnSurface = Color(0xFFFBEEEB),
|
||||||
outline = Color(0xFF85736E),
|
outline = Color(0xFF85736E),
|
||||||
|
surfaceContainerLowest = Color(0xFFECE3E0),
|
||||||
|
surfaceContainerLow = Color(0xFFF1E7E4),
|
||||||
|
surfaceContainer = Color(0xFFF6EBE7), // Navigation bar background
|
||||||
|
surfaceContainerHigh = Color(0xFFFAF4F2),
|
||||||
|
surfaceContainerHighest = Color(0xFFFBF6F4),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
@@ -58,8 +57,6 @@ import tachiyomi.i18n.MR
|
|||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
private const val UnsetStatusTextAlpha = 0.5F
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrackInfoDialogHome(
|
fun TrackInfoDialogHome(
|
||||||
trackItems: List<TrackItem>,
|
trackItems: List<TrackItem>,
|
||||||
@@ -72,6 +69,7 @@ fun TrackInfoDialogHome(
|
|||||||
onNewSearch: (TrackItem) -> Unit,
|
onNewSearch: (TrackItem) -> Unit,
|
||||||
onOpenInBrowser: (TrackItem) -> Unit,
|
onOpenInBrowser: (TrackItem) -> Unit,
|
||||||
onRemoved: (TrackItem) -> Unit,
|
onRemoved: (TrackItem) -> Unit,
|
||||||
|
onCopyLink: (TrackItem) -> Unit,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -116,6 +114,7 @@ fun TrackInfoDialogHome(
|
|||||||
onNewSearch = { onNewSearch(item) },
|
onNewSearch = { onNewSearch(item) },
|
||||||
onOpenInBrowser = { onOpenInBrowser(item) },
|
onOpenInBrowser = { onOpenInBrowser(item) },
|
||||||
onRemoved = { onRemoved(item) },
|
onRemoved = { onRemoved(item) },
|
||||||
|
onCopyLink = { onCopyLink(item) },
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
TrackInfoItemEmpty(
|
TrackInfoItemEmpty(
|
||||||
@@ -144,6 +143,7 @@ private fun TrackInfoItem(
|
|||||||
onNewSearch: () -> Unit,
|
onNewSearch: () -> Unit,
|
||||||
onOpenInBrowser: () -> Unit,
|
onOpenInBrowser: () -> Unit,
|
||||||
onRemoved: () -> Unit,
|
onRemoved: () -> Unit,
|
||||||
|
onCopyLink: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
Column {
|
Column {
|
||||||
@@ -153,6 +153,7 @@ private fun TrackInfoItem(
|
|||||||
TrackLogoIcon(
|
TrackLogoIcon(
|
||||||
tracker = tracker,
|
tracker = tracker,
|
||||||
onClick = onOpenInBrowser,
|
onClick = onOpenInBrowser,
|
||||||
|
onLongClick = onCopyLink,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -179,6 +180,7 @@ private fun TrackInfoItem(
|
|||||||
TrackInfoItemMenu(
|
TrackInfoItemMenu(
|
||||||
onOpenInBrowser = onOpenInBrowser,
|
onOpenInBrowser = onOpenInBrowser,
|
||||||
onRemoved = onRemoved,
|
onRemoved = onRemoved,
|
||||||
|
onCopyLink = onCopyLink,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +188,7 @@ private fun TrackInfoItem(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = 12.dp)
|
.padding(top = 12.dp)
|
||||||
.clip(MaterialTheme.shapes.medium)
|
.clip(MaterialTheme.shapes.medium)
|
||||||
.background(MaterialTheme.colorScheme.surface)
|
.background(MaterialTheme.colorScheme.surfaceContainerHighest)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
.clip(RoundedCornerShape(6.dp)),
|
.clip(RoundedCornerShape(6.dp)),
|
||||||
) {
|
) {
|
||||||
@@ -206,10 +208,9 @@ private fun TrackInfoItem(
|
|||||||
if (onScoreClick != null) {
|
if (onScoreClick != null) {
|
||||||
VerticalDivider()
|
VerticalDivider()
|
||||||
TrackDetailsItem(
|
TrackDetailsItem(
|
||||||
modifier = Modifier
|
modifier = Modifier.weight(1f),
|
||||||
.weight(1f)
|
text = score,
|
||||||
.alpha(if (score == null) UnsetStatusTextAlpha else 1f),
|
placeholder = stringResource(MR.strings.score),
|
||||||
text = score ?: stringResource(MR.strings.score),
|
|
||||||
onClick = onScoreClick,
|
onClick = onScoreClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -238,6 +239,8 @@ private fun TrackInfoItem(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val UNSET_TEXT_ALPHA = 0.5F
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TrackDetailsItem(
|
private fun TrackDetailsItem(
|
||||||
text: String?,
|
text: String?,
|
||||||
@@ -258,7 +261,7 @@ private fun TrackDetailsItem(
|
|||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = if (text == null) UnsetStatusTextAlpha else 1f),
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = if (text == null) UNSET_TEXT_ALPHA else 1f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,6 +290,7 @@ private fun TrackInfoItemEmpty(
|
|||||||
private fun TrackInfoItemMenu(
|
private fun TrackInfoItemMenu(
|
||||||
onOpenInBrowser: () -> Unit,
|
onOpenInBrowser: () -> Unit,
|
||||||
onRemoved: () -> Unit,
|
onRemoved: () -> Unit,
|
||||||
|
onCopyLink: () -> Unit,
|
||||||
) {
|
) {
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
Box(modifier = Modifier.wrapContentSize(Alignment.TopStart)) {
|
Box(modifier = Modifier.wrapContentSize(Alignment.TopStart)) {
|
||||||
@@ -307,6 +311,13 @@ private fun TrackInfoItemMenu(
|
|||||||
expanded = false
|
expanded = false
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(MR.strings.action_copy_link)) },
|
||||||
|
onClick = {
|
||||||
|
onCopyLink()
|
||||||
|
expanded = false
|
||||||
|
},
|
||||||
|
)
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
text = { Text(stringResource(MR.strings.action_remove)) },
|
text = { Text(stringResource(MR.strings.action_remove)) },
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ internal class TrackInfoDialogHomePreviewProvider :
|
|||||||
onNewSearch = {},
|
onNewSearch = {},
|
||||||
onOpenInBrowser = {},
|
onOpenInBrowser = {},
|
||||||
onRemoved = {},
|
onRemoved = {},
|
||||||
|
onCopyLink = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ internal class TrackInfoDialogHomePreviewProvider :
|
|||||||
onNewSearch = {},
|
onNewSearch = {},
|
||||||
onOpenInBrowser = {},
|
onOpenInBrowser = {},
|
||||||
onRemoved = {},
|
onRemoved = {},
|
||||||
|
onCopyLink = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ private fun SearchResultItem(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val clipboardManager: ClipboardManager = LocalClipboardManager.current
|
val clipboardManager: ClipboardManager = LocalClipboardManager.current
|
||||||
|
val focusManager = LocalFocusManager.current
|
||||||
val type = trackSearch.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current)
|
val type = trackSearch.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current)
|
||||||
val status = trackSearch.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current)
|
val status = trackSearch.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current)
|
||||||
val description = trackSearch.summary.trim()
|
val description = trackSearch.summary.trim()
|
||||||
@@ -243,7 +244,10 @@ private fun SearchResultItem(
|
|||||||
)
|
)
|
||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
onLongClick = { dropDownMenuExpanded = true },
|
onLongClick = { dropDownMenuExpanded = true },
|
||||||
onClick = onClick,
|
onClick = {
|
||||||
|
focusManager.clearFocus()
|
||||||
|
onClick()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.padding(12.dp),
|
.padding(12.dp),
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ import tachiyomi.presentation.core.util.clickableNoIndication
|
|||||||
fun TrackLogoIcon(
|
fun TrackLogoIcon(
|
||||||
tracker: Tracker,
|
tracker: Tracker,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onLongClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val modifier = if (onClick != null) {
|
val modifier = if (onClick != null) {
|
||||||
Modifier.clickableNoIndication(onClick = onClick)
|
Modifier.clickableNoIndication(onClick = onClick, onLongClick = onLongClick)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
}
|
}
|
||||||
@@ -53,6 +54,7 @@ private fun TrackLogoIconPreviews(
|
|||||||
TrackLogoIcon(
|
TrackLogoIcon(
|
||||||
tracker = tracker,
|
tracker = tracker,
|
||||||
onClick = null,
|
onClick = null,
|
||||||
|
onLongClick = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
|||||||
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.ListGroupHeader
|
import tachiyomi.presentation.core.components.ListGroupHeader
|
||||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import tachiyomi.presentation.core.util.selectedBackground
|
import tachiyomi.presentation.core.util.selectedBackground
|
||||||
@@ -107,8 +107,10 @@ internal fun LazyListScope.updatesUiItems(
|
|||||||
readProgress = updatesItem.update.lastPageRead
|
readProgress = updatesItem.update.lastPageRead
|
||||||
.takeIf {
|
.takeIf {
|
||||||
/* SY --> */(
|
/* SY --> */(
|
||||||
!updatesItem.update.read || (preserveReadingPosition && updatesItem.isEhBasedUpdate())
|
!updatesItem.update.read ||
|
||||||
)/* SY <-- */ && it > 0L
|
(preserveReadingPosition && updatesItem.isEhBasedUpdate())
|
||||||
|
)/* SY <-- */ &&
|
||||||
|
it > 0L
|
||||||
}
|
}
|
||||||
?.let {
|
?.let {
|
||||||
stringResource(
|
stringResource(
|
||||||
@@ -152,7 +154,7 @@ private fun UpdatesUiItem(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val haptic = LocalHapticFeedback.current
|
val haptic = LocalHapticFeedback.current
|
||||||
val textAlpha = if (update.read) ReadItemAlpha else 1f
|
val textAlpha = if (update.read) DISABLED_ALPHA else 1f
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@@ -226,7 +228,7 @@ private fun UpdatesUiItem(
|
|||||||
Text(
|
Text(
|
||||||
text = readProgress,
|
text = readProgress,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
|
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.presentation.util
|
package eu.kanade.presentation.util
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||||
import androidx.compose.animation.ContentTransform
|
import androidx.compose.animation.ContentTransform
|
||||||
@@ -28,7 +27,6 @@ import soup.compose.material.motion.animation.rememberSlideDistance
|
|||||||
/**
|
/**
|
||||||
* For invoking back press to the parent activity
|
* For invoking back press to the parent activity
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ComposeCompositionLocalUsage")
|
|
||||||
val LocalBackPress: ProvidableCompositionLocal<(() -> Unit)?> = staticCompositionLocalOf { null }
|
val LocalBackPress: ProvidableCompositionLocal<(() -> Unit)?> = staticCompositionLocalOf { null }
|
||||||
|
|
||||||
interface Tab : cafe.adriel.voyager.navigator.tab.Tab {
|
interface Tab : cafe.adriel.voyager.navigator.tab.Tab {
|
||||||
|
|||||||
@@ -174,8 +174,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
|||||||
|
|
||||||
val syncPreferences: SyncPreferences = Injekt.get()
|
val syncPreferences: SyncPreferences = Injekt.get()
|
||||||
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
||||||
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppStart
|
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppStart) {
|
||||||
) {
|
|
||||||
SyncDataJob.startNow(this@App)
|
SyncDataJob.startNow(this@App)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,26 +202,34 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
|||||||
return ImageLoader.Builder(this).apply {
|
return ImageLoader.Builder(this).apply {
|
||||||
val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().client }
|
val callFactoryLazy = lazy { Injekt.get<NetworkHelper>().client }
|
||||||
components {
|
components {
|
||||||
|
// NetworkFetcher.Factory
|
||||||
add(OkHttpNetworkFetcherFactory(callFactoryLazy::value))
|
add(OkHttpNetworkFetcherFactory(callFactoryLazy::value))
|
||||||
|
// Decoder.Factory
|
||||||
add(TachiyomiImageDecoder.Factory())
|
add(TachiyomiImageDecoder.Factory())
|
||||||
add(MangaCoverFetcher.MangaFactory(callFactoryLazy))
|
// Fetcher.Factory
|
||||||
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy))
|
|
||||||
add(MangaKeyer())
|
|
||||||
add(MangaCoverKeyer())
|
|
||||||
add(BufferedSourceFetcher.Factory())
|
add(BufferedSourceFetcher.Factory())
|
||||||
|
add(MangaCoverFetcher.MangaCoverFactory(callFactoryLazy))
|
||||||
|
add(MangaCoverFetcher.MangaFactory(callFactoryLazy))
|
||||||
// SY -->
|
// SY -->
|
||||||
add(PagePreviewKeyer())
|
|
||||||
add(PagePreviewFetcher.Factory(callFactoryLazy))
|
add(PagePreviewFetcher.Factory(callFactoryLazy))
|
||||||
// SY <--
|
// SY <--
|
||||||
|
// Keyer
|
||||||
|
add(MangaCoverKeyer())
|
||||||
|
add(MangaKeyer())
|
||||||
|
// SY -->
|
||||||
|
add(PagePreviewKeyer())
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
crossfade((300 * this@App.animatorDurationScale).toInt())
|
crossfade((300 * this@App.animatorDurationScale).toInt())
|
||||||
allowRgb565(DeviceUtil.isLowRamDevice(this@App))
|
allowRgb565(DeviceUtil.isLowRamDevice(this@App))
|
||||||
if (networkPreferences.verboseLogging().get()) logger(DebugLogger())
|
if (networkPreferences.verboseLogging().get()) logger(DebugLogger())
|
||||||
|
|
||||||
// Coil spawns a new thread for every image load by default
|
// Coil spawns a new thread for every image load by default
|
||||||
fetcherDispatcher(Dispatchers.IO.limitedParallelism(8))
|
fetcherCoroutineContext(Dispatchers.IO.limitedParallelism(8))
|
||||||
decoderDispatcher(Dispatchers.IO.limitedParallelism(2))
|
decoderCoroutineContext(Dispatchers.IO.limitedParallelism(3))
|
||||||
}.build()
|
}
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart(owner: LifecycleOwner) {
|
override fun onStart(owner: LifecycleOwner) {
|
||||||
@@ -230,8 +237,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
|||||||
|
|
||||||
val syncPreferences: SyncPreferences = Injekt.get()
|
val syncPreferences: SyncPreferences = Injekt.get()
|
||||||
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
val syncTriggerOpt = syncPreferences.getSyncTriggerOptions()
|
||||||
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppResume
|
if (syncPreferences.isSyncEnabled() && syncTriggerOpt.syncOnAppResume) {
|
||||||
) {
|
|
||||||
SyncDataJob.startNow(this@App)
|
SyncDataJob.startNow(this@App)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,21 @@ package eu.kanade.tachiyomi.data.backup
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
import okio.buffer
|
import okio.buffer
|
||||||
import okio.gzip
|
import okio.gzip
|
||||||
import okio.source
|
import okio.source
|
||||||
|
import tachiyomi.core.common.i18n.stringResource
|
||||||
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
class BackupDecoder(
|
class BackupDecoder(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val parser: ProtoBuf = Injekt.get(),
|
private val parser: ProtoBuf = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a potentially-gzipped backup.
|
* Decode a potentially-gzipped backup.
|
||||||
*/
|
*/
|
||||||
@@ -27,13 +29,25 @@ class BackupDecoder(
|
|||||||
require(2)
|
require(2)
|
||||||
}
|
}
|
||||||
val id1id2 = peeked.readShort()
|
val id1id2 = peeked.readShort()
|
||||||
val backupString = if (id1id2.toInt() == 0x1f8b) { // 0x1f8b is gzip magic bytes
|
val backupString = when (id1id2.toInt()) {
|
||||||
source.gzip().buffer()
|
0x1f8b -> source.gzip().buffer() // 0x1f8b is gzip magic bytes
|
||||||
} else {
|
MAGIC_JSON_SIGNATURE1, MAGIC_JSON_SIGNATURE2, MAGIC_JSON_SIGNATURE3 -> {
|
||||||
source
|
throw IOException(context.stringResource(MR.strings.invalid_backup_file_json))
|
||||||
|
}
|
||||||
|
else -> source
|
||||||
}.use { it.readByteArray() }
|
}.use { it.readByteArray() }
|
||||||
|
|
||||||
parser.decodeFromByteArray(BackupSerializer, backupString)
|
try {
|
||||||
|
parser.decodeFromByteArray(Backup.serializer(), backupString)
|
||||||
|
} catch (_: SerializationException) {
|
||||||
|
throw IOException(context.stringResource(MR.strings.invalid_backup_file_unknown))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MAGIC_JSON_SIGNATURE1 = 0x7b7d // `{}`
|
||||||
|
private const val MAGIC_JSON_SIGNATURE2 = 0x7b22 // `{"`
|
||||||
|
private const val MAGIC_JSON_SIGNATURE3 = 0x7b0a // `{\n`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ import com.hippo.unifile.UniFile
|
|||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||||
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
|
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
|
||||||
|
import eu.kanade.tachiyomi.data.backup.create.creators.ExtensionRepoBackupCreator
|
||||||
import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator
|
import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator
|
||||||
import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator
|
import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator
|
||||||
import eu.kanade.tachiyomi.data.backup.create.creators.SavedSearchBackupCreator
|
import eu.kanade.tachiyomi.data.backup.create.creators.SavedSearchBackupCreator
|
||||||
import eu.kanade.tachiyomi.data.backup.create.creators.SourcesBackupCreator
|
import eu.kanade.tachiyomi.data.backup.create.creators.SourcesBackupCreator
|
||||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
|
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
@@ -51,58 +52,61 @@ class BackupCreator(
|
|||||||
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
|
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
|
||||||
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
|
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
|
||||||
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
|
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
|
||||||
|
private val extensionRepoBackupCreator: ExtensionRepoBackupCreator = ExtensionRepoBackupCreator(),
|
||||||
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
|
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
|
||||||
// SY -->
|
// SY -->
|
||||||
private val savedSearchBackupCreator: SavedSearchBackupCreator = SavedSearchBackupCreator(),
|
private val savedSearchBackupCreator: SavedSearchBackupCreator = SavedSearchBackupCreator(),
|
||||||
private val getMergedManga: GetMergedManga = Injekt.get(),
|
private val getMergedManga: GetMergedManga = Injekt.get(),
|
||||||
private val handler: DatabaseHandler = Injekt.get()
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun backup(uri: Uri, options: BackupOptions): String {
|
suspend fun backup(uri: Uri, options: BackupOptions): String {
|
||||||
var file: UniFile? = null
|
var file: UniFile? = null
|
||||||
try {
|
try {
|
||||||
file = (
|
file = if (isAutoBackup) {
|
||||||
if (isAutoBackup) {
|
// Get dir of file and create
|
||||||
// Get dir of file and create
|
val dir = UniFile.fromUri(context, uri)
|
||||||
val dir = UniFile.fromUri(context, uri)
|
|
||||||
|
|
||||||
// Delete older backups
|
// Delete older backups
|
||||||
dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
|
dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
.sortedByDescending { it.name }
|
.sortedByDescending { it.name }
|
||||||
.drop(MAX_AUTO_BACKUPS - 1)
|
.drop(MAX_AUTO_BACKUPS - 1)
|
||||||
.forEach { it.delete() }
|
.forEach { it.delete() }
|
||||||
|
|
||||||
// Create new file to place backup
|
// Create new file to place backup
|
||||||
dir?.createFile(getFilename())
|
dir?.createFile(getFilename())
|
||||||
} else {
|
} else {
|
||||||
UniFile.fromUri(context, uri)
|
UniFile.fromUri(context, uri)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
if (file == null || !file.isFile) {
|
if (file == null || !file.isFile) {
|
||||||
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
|
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
|
||||||
}
|
}
|
||||||
|
|
||||||
val databaseManga = getFavorites.await() /* SY --> */ +
|
val backupManga = backupMangas(
|
||||||
if (options.readEntries) {
|
getFavorites.await() /* SY --> */ +
|
||||||
handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
if (options.readEntries) {
|
||||||
} else {
|
handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
||||||
emptyList()
|
} else {
|
||||||
} + getMergedManga.await() // SY <--
|
emptyList()
|
||||||
|
} + getMergedManga.await(), // SY <--
|
||||||
|
options,
|
||||||
|
)
|
||||||
val backup = Backup(
|
val backup = Backup(
|
||||||
backupManga = backupMangas(databaseManga, options),
|
backupManga = backupManga,
|
||||||
backupCategories = backupCategories(options),
|
backupCategories = backupCategories(options),
|
||||||
backupSources = backupSources(databaseManga),
|
backupSources = backupSources(backupManga),
|
||||||
backupPreferences = backupAppPreferences(options),
|
backupPreferences = backupAppPreferences(options),
|
||||||
|
backupExtensionRepo = backupExtensionRepos(options),
|
||||||
backupSourcePreferences = backupSourcePreferences(options),
|
backupSourcePreferences = backupSourcePreferences(options),
|
||||||
// SY -->
|
// SY -->
|
||||||
backupSavedSearches = backupSavedSearches(),
|
backupSavedSearches = backupSavedSearches(options),
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
val byteArray = parser.encodeToByteArray(BackupSerializer, backup)
|
val byteArray = parser.encodeToByteArray(Backup.serializer(), backup)
|
||||||
if (byteArray.isEmpty()) {
|
if (byteArray.isEmpty()) {
|
||||||
throw IllegalStateException(context.stringResource(MR.strings.empty_backup_error))
|
throw IllegalStateException(context.stringResource(MR.strings.empty_backup_error))
|
||||||
}
|
}
|
||||||
@@ -135,32 +139,42 @@ class BackupCreator(
|
|||||||
suspend fun backupCategories(options: BackupOptions): List<BackupCategory> {
|
suspend fun backupCategories(options: BackupOptions): List<BackupCategory> {
|
||||||
if (!options.categories) return emptyList()
|
if (!options.categories) return emptyList()
|
||||||
|
|
||||||
return categoriesBackupCreator.backupCategories()
|
return categoriesBackupCreator()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||||
return mangaBackupCreator.backupMangas(mangas, options)
|
if (!options.libraryEntries) return emptyList()
|
||||||
|
|
||||||
|
return mangaBackupCreator(mangas, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun backupSources(mangas: List<Manga>): List<BackupSource> {
|
fun backupSources(mangas: List<BackupManga>): List<BackupSource> {
|
||||||
return sourcesBackupCreator.backupSources(mangas)
|
return sourcesBackupCreator(mangas)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun backupAppPreferences(options: BackupOptions): List<BackupPreference> {
|
fun backupAppPreferences(options: BackupOptions): List<BackupPreference> {
|
||||||
if (!options.appSettings) return emptyList()
|
if (!options.appSettings) return emptyList()
|
||||||
|
|
||||||
return preferenceBackupCreator.backupAppPreferences(includePrivatePreferences = options.privateSettings)
|
return preferenceBackupCreator.createApp(includePrivatePreferences = options.privateSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun backupSourcePreferences(options: BackupOptions): List<BackupSourcePreferences> {
|
fun backupSourcePreferences(options: BackupOptions): List<BackupSourcePreferences> {
|
||||||
if (!options.sourceSettings) return emptyList()
|
if (!options.sourceSettings) return emptyList()
|
||||||
|
|
||||||
return preferenceBackupCreator.backupSourcePreferences(includePrivatePreferences = options.privateSettings)
|
return preferenceBackupCreator.createSource(includePrivatePreferences = options.privateSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun backupExtensionRepos(options: BackupOptions): List<BackupExtensionRepos> {
|
||||||
|
if (!options.extensionRepoSettings) return emptyList()
|
||||||
|
|
||||||
|
return extensionRepoBackupCreator()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
suspend fun backupSavedSearches(): List<BackupSavedSearch> {
|
suspend fun backupSavedSearches(options: BackupOptions): List<BackupSavedSearch> {
|
||||||
return savedSearchBackupCreator.backupSavedSearches()
|
if (!options.savedSearches) return emptyList()
|
||||||
|
|
||||||
|
return savedSearchBackupCreator()
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ data class BackupOptions(
|
|||||||
val tracking: Boolean = true,
|
val tracking: Boolean = true,
|
||||||
val history: Boolean = true,
|
val history: Boolean = true,
|
||||||
val appSettings: Boolean = true,
|
val appSettings: Boolean = true,
|
||||||
|
val extensionRepoSettings: Boolean = true,
|
||||||
val sourceSettings: Boolean = true,
|
val sourceSettings: Boolean = true,
|
||||||
val privateSettings: Boolean = false,
|
val privateSettings: Boolean = false,
|
||||||
// SY -->
|
// SY -->
|
||||||
val customInfo: Boolean = true,
|
val customInfo: Boolean = true,
|
||||||
val readEntries: Boolean = true,
|
val readEntries: Boolean = true,
|
||||||
|
val savedSearches: Boolean = true,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -27,15 +29,18 @@ data class BackupOptions(
|
|||||||
tracking,
|
tracking,
|
||||||
history,
|
history,
|
||||||
appSettings,
|
appSettings,
|
||||||
|
extensionRepoSettings,
|
||||||
sourceSettings,
|
sourceSettings,
|
||||||
privateSettings,
|
privateSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo,
|
customInfo,
|
||||||
readEntries,
|
readEntries,
|
||||||
|
savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
fun anyEnabled() = libraryEntries || appSettings || sourceSettings
|
fun canCreate() =
|
||||||
|
libraryEntries || categories || appSettings || extensionRepoSettings || sourceSettings || savedSearches
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val libraryOptions = persistentListOf(
|
val libraryOptions = persistentListOf(
|
||||||
@@ -44,12 +49,6 @@ data class BackupOptions(
|
|||||||
getter = BackupOptions::libraryEntries,
|
getter = BackupOptions::libraryEntries,
|
||||||
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
|
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
|
||||||
),
|
),
|
||||||
Entry(
|
|
||||||
label = MR.strings.categories,
|
|
||||||
getter = BackupOptions::categories,
|
|
||||||
setter = { options, enabled -> options.copy(categories = enabled) },
|
|
||||||
enabled = { it.libraryEntries },
|
|
||||||
),
|
|
||||||
Entry(
|
Entry(
|
||||||
label = MR.strings.chapters,
|
label = MR.strings.chapters,
|
||||||
getter = BackupOptions::chapters,
|
getter = BackupOptions::chapters,
|
||||||
@@ -68,6 +67,11 @@ data class BackupOptions(
|
|||||||
setter = { options, enabled -> options.copy(history = enabled) },
|
setter = { options, enabled -> options.copy(history = enabled) },
|
||||||
enabled = { it.libraryEntries },
|
enabled = { it.libraryEntries },
|
||||||
),
|
),
|
||||||
|
Entry(
|
||||||
|
label = MR.strings.categories,
|
||||||
|
getter = BackupOptions::categories,
|
||||||
|
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||||
|
),
|
||||||
// SY -->
|
// SY -->
|
||||||
Entry(
|
Entry(
|
||||||
label = SYMR.strings.custom_entry_info,
|
label = SYMR.strings.custom_entry_info,
|
||||||
@@ -81,6 +85,11 @@ data class BackupOptions(
|
|||||||
setter = { options, enabled -> options.copy(readEntries = enabled) },
|
setter = { options, enabled -> options.copy(readEntries = enabled) },
|
||||||
enabled = { it.libraryEntries },
|
enabled = { it.libraryEntries },
|
||||||
),
|
),
|
||||||
|
Entry(
|
||||||
|
label = SYMR.strings.saved_searches,
|
||||||
|
getter = BackupOptions::savedSearches,
|
||||||
|
setter = { options, enabled -> options.copy(savedSearches = enabled) },
|
||||||
|
),
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,6 +99,11 @@ data class BackupOptions(
|
|||||||
getter = BackupOptions::appSettings,
|
getter = BackupOptions::appSettings,
|
||||||
setter = { options, enabled -> options.copy(appSettings = enabled) },
|
setter = { options, enabled -> options.copy(appSettings = enabled) },
|
||||||
),
|
),
|
||||||
|
Entry(
|
||||||
|
label = MR.strings.extensionRepo_settings,
|
||||||
|
getter = BackupOptions::extensionRepoSettings,
|
||||||
|
setter = { options, enabled -> options.copy(extensionRepoSettings = enabled) },
|
||||||
|
),
|
||||||
Entry(
|
Entry(
|
||||||
label = MR.strings.source_settings,
|
label = MR.strings.source_settings,
|
||||||
getter = BackupOptions::sourceSettings,
|
getter = BackupOptions::sourceSettings,
|
||||||
@@ -110,11 +124,13 @@ data class BackupOptions(
|
|||||||
tracking = array[3],
|
tracking = array[3],
|
||||||
history = array[4],
|
history = array[4],
|
||||||
appSettings = array[5],
|
appSettings = array[5],
|
||||||
sourceSettings = array[6],
|
extensionRepoSettings = array[6],
|
||||||
privateSettings = array[7],
|
sourceSettings = array[7],
|
||||||
|
privateSettings = array[8],
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = array[8],
|
customInfo = array[9],
|
||||||
readEntries = array[9],
|
readEntries = array[10],
|
||||||
|
savedSearches = array[11],
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ class CategoriesBackupCreator(
|
|||||||
private val getCategories: GetCategories = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun backupCategories(): List<BackupCategory> {
|
suspend operator fun invoke(): List<BackupCategory> {
|
||||||
return getCategories.await()
|
return getCategories.await()
|
||||||
.filterNot(Category::isSystemCategory)
|
.filterNot(Category::isSystemCategory)
|
||||||
.map(backupCategoryMapper)
|
.map(backupCategoryMapper)
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.backupExtensionReposMapper
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class ExtensionRepoBackupCreator(
|
||||||
|
private val getExtensionRepos: GetExtensionRepo = Injekt.get(),
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend operator fun invoke(): List<BackupExtensionRepos> {
|
||||||
|
return getExtensionRepos.getAll()
|
||||||
|
.map(backupExtensionReposMapper)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -34,7 +34,7 @@ class MangaBackupCreator(
|
|||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun backupMangas(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
suspend operator fun invoke(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
|
||||||
return mangas.map {
|
return mangas.map {
|
||||||
backupManga(it, options)
|
backupManga(it, options)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -22,12 +22,12 @@ class PreferenceBackupCreator(
|
|||||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun backupAppPreferences(includePrivatePreferences: Boolean): List<BackupPreference> {
|
fun createApp(includePrivatePreferences: Boolean): List<BackupPreference> {
|
||||||
return preferenceStore.getAll().toBackupPreferences()
|
return preferenceStore.getAll().toBackupPreferences()
|
||||||
.withPrivatePreferences(includePrivatePreferences)
|
.withPrivatePreferences(includePrivatePreferences)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun backupSourcePreferences(includePrivatePreferences: Boolean): List<BackupSourcePreferences> {
|
fun createSource(includePrivatePreferences: Boolean): List<BackupSourcePreferences> {
|
||||||
return sourceManager.getCatalogueSources()
|
return sourceManager.getCatalogueSources()
|
||||||
.filterIsInstance<ConfigurableSource>()
|
.filterIsInstance<ConfigurableSource>()
|
||||||
.map {
|
.map {
|
||||||
|
|||||||
+2
-2
@@ -7,10 +7,10 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class SavedSearchBackupCreator(
|
class SavedSearchBackupCreator(
|
||||||
private val handler: DatabaseHandler = Injekt.get()
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun backupSavedSearches(): List<BackupSavedSearch> {
|
suspend operator fun invoke(): List<BackupSavedSearch> {
|
||||||
return handler.awaitList { saved_searchQueries.selectAll(backupSavedSearchMapper) }
|
return handler.awaitList { saved_searchQueries.selectAll(backupSavedSearchMapper) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.create.creators
|
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import tachiyomi.domain.manga.model.Manga
|
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@@ -11,10 +11,10 @@ class SourcesBackupCreator(
|
|||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun backupSources(mangas: List<Manga>): List<BackupSource> {
|
operator fun invoke(mangas: List<BackupManga>): List<BackupSource> {
|
||||||
return mangas
|
return mangas
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.map(Manga::source)
|
.map(BackupManga::source)
|
||||||
.distinct()
|
.distinct()
|
||||||
.map(sourceManager::getOrStub)
|
.map(sourceManager::getOrStub)
|
||||||
.map { it.toBackupSource() }
|
.map { it.toBackupSource() }
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.models
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Serializer
|
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
@Serializer(forClass = Backup::class)
|
|
||||||
object BackupSerializer
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Backup(
|
data class Backup(
|
||||||
@ProtoNumber(1) val backupManga: List<BackupManga>,
|
@ProtoNumber(1) val backupManga: List<BackupManga>,
|
||||||
@ProtoNumber(2) var backupCategories: List<BackupCategory> = emptyList(),
|
@ProtoNumber(2) var backupCategories: List<BackupCategory> = emptyList(),
|
||||||
@ProtoNumber(100) var backupBrokenSources: List<BrokenBackupSource> = emptyList(),
|
// @ProtoNumber(100) var backupBrokenSources, legacy source model with non-compliant proto number,
|
||||||
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
||||||
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
|
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
|
||||||
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
|
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
|
||||||
|
@ProtoNumber(106) var backupExtensionRepo: List<BackupExtensionRepos> = emptyList(),
|
||||||
// SY specific values
|
// SY specific values
|
||||||
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
import tachiyomi.domain.chapter.model.Chapter
|
import tachiyomi.domain.chapter.model.Chapter
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BackupChapter(
|
data class BackupChapter(
|
||||||
// in 1.x some of these values have different names
|
// in 1.x some of these values have different names
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.backup.models
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
import mihon.domain.extensionrepo.model.ExtensionRepo
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class BackupExtensionRepos(
|
||||||
|
@ProtoNumber(1) var baseUrl: String,
|
||||||
|
@ProtoNumber(2) var name: String,
|
||||||
|
@ProtoNumber(3) var shortName: String?,
|
||||||
|
@ProtoNumber(4) var website: String,
|
||||||
|
@ProtoNumber(5) var signingKeyFingerprint: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
val backupExtensionReposMapper = { repo: ExtensionRepo ->
|
||||||
|
BackupExtensionRepos(
|
||||||
|
baseUrl = repo.baseUrl,
|
||||||
|
name = repo.name,
|
||||||
|
shortName = repo.shortName,
|
||||||
|
website = repo.website,
|
||||||
|
signingKeyFingerprint = repo.signingKeyFingerprint,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -18,15 +18,3 @@ data class BackupHistory(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Replaced with BackupHistory. This is retained for legacy reasons.")
|
|
||||||
@Serializable
|
|
||||||
data class BrokenBackupHistory(
|
|
||||||
@ProtoNumber(0) var url: String,
|
|
||||||
@ProtoNumber(1) var lastRead: Long,
|
|
||||||
@ProtoNumber(2) var readDuration: Long = 0,
|
|
||||||
) {
|
|
||||||
fun toBackupHistory(): BackupHistory {
|
|
||||||
return BackupHistory(url, lastRead, readDuration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,13 +3,9 @@ package eu.kanade.tachiyomi.data.backup.models
|
|||||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
import tachiyomi.domain.manga.model.CustomMangaInfo
|
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
|
||||||
@Suppress(
|
@Suppress("DEPRECATION")
|
||||||
"DEPRECATION",
|
|
||||||
"MagicNumber",
|
|
||||||
)
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BackupManga(
|
data class BackupManga(
|
||||||
// in 1.x some of these values have different names
|
// in 1.x some of these values have different names
|
||||||
@@ -36,7 +32,7 @@ data class BackupManga(
|
|||||||
// Bump by 100 for values that are not saved/implemented in 1.x but are used in 0.x
|
// Bump by 100 for values that are not saved/implemented in 1.x but are used in 0.x
|
||||||
@ProtoNumber(100) var favorite: Boolean = true,
|
@ProtoNumber(100) var favorite: Boolean = true,
|
||||||
@ProtoNumber(101) var chapterFlags: Int = 0,
|
@ProtoNumber(101) var chapterFlags: Int = 0,
|
||||||
@ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(),
|
// @ProtoNumber(102) var brokenHistory, legacy history model with non-compliant proto number
|
||||||
@ProtoNumber(103) var viewer_flags: Int? = null,
|
@ProtoNumber(103) var viewer_flags: Int? = null,
|
||||||
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
||||||
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
|
|||||||
+2
-1
@@ -36,7 +36,8 @@ data class BackupMergedMangaReference(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val backupMergedMangaReferenceMapper =
|
val backupMergedMangaReferenceMapper =
|
||||||
{ _: Long,
|
{
|
||||||
|
_: Long,
|
||||||
isInfoManga: Boolean,
|
isInfoManga: Boolean,
|
||||||
getChapterUpdates: Boolean,
|
getChapterUpdates: Boolean,
|
||||||
chapterSortMode: Long,
|
chapterSortMode: Long,
|
||||||
|
|||||||
@@ -8,11 +8,3 @@ data class BackupSource(
|
|||||||
@ProtoNumber(1) var name: String = "",
|
@ProtoNumber(1) var name: String = "",
|
||||||
@ProtoNumber(2) var sourceId: Long,
|
@ProtoNumber(2) var sourceId: Long,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class BrokenBackupSource(
|
|
||||||
@ProtoNumber(0) var name: String = "",
|
|
||||||
@ProtoNumber(1) var sourceId: Long,
|
|
||||||
) {
|
|
||||||
fun toBackupSource() = BackupSource(name, sourceId)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -53,7 +53,20 @@ data class BackupTracking(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val backupTrackMapper = {
|
val backupTrackMapper = {
|
||||||
_: Long, _: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastChapterRead: Double, totalChapters: Long, status: Long, score: Double, remoteUrl: String, startDate: Long, finishDate: Long ->
|
_: Long,
|
||||||
|
_: Long,
|
||||||
|
syncId: Long,
|
||||||
|
mediaId: Long,
|
||||||
|
libraryId: Long?,
|
||||||
|
title: String,
|
||||||
|
lastChapterRead: Double,
|
||||||
|
totalChapters: Long,
|
||||||
|
status: Long,
|
||||||
|
score: Double,
|
||||||
|
remoteUrl: String,
|
||||||
|
startDate: Long,
|
||||||
|
finishDate: Long,
|
||||||
|
->
|
||||||
BackupTracking(
|
BackupTracking(
|
||||||
syncId = syncId.toInt(),
|
syncId = syncId.toInt(),
|
||||||
mediaId = mediaId,
|
mediaId = mediaId,
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import android.net.Uri
|
|||||||
import eu.kanade.tachiyomi.data.backup.BackupDecoder
|
import eu.kanade.tachiyomi.data.backup.BackupDecoder
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
import eu.kanade.tachiyomi.data.backup.BackupNotifier
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||||
import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesRestorer
|
import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesRestorer
|
||||||
|
import eu.kanade.tachiyomi.data.backup.restore.restorers.ExtensionRepoRestorer
|
||||||
import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer
|
import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer
|
||||||
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
|
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
|
||||||
import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer
|
import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer
|
||||||
@@ -34,6 +36,7 @@ class BackupRestorer(
|
|||||||
|
|
||||||
private val categoriesRestorer: CategoriesRestorer = CategoriesRestorer(),
|
private val categoriesRestorer: CategoriesRestorer = CategoriesRestorer(),
|
||||||
private val preferenceRestorer: PreferenceRestorer = PreferenceRestorer(context),
|
private val preferenceRestorer: PreferenceRestorer = PreferenceRestorer(context),
|
||||||
|
private val extensionRepoRestorer: ExtensionRepoRestorer = ExtensionRepoRestorer(),
|
||||||
private val mangaRestorer: MangaRestorer = MangaRestorer(isSync),
|
private val mangaRestorer: MangaRestorer = MangaRestorer(isSync),
|
||||||
// SY -->
|
// SY -->
|
||||||
private val savedSearchRestorer: SavedSearchRestorer = SavedSearchRestorer(),
|
private val savedSearchRestorer: SavedSearchRestorer = SavedSearchRestorer(),
|
||||||
@@ -71,11 +74,14 @@ class BackupRestorer(
|
|||||||
val backup = BackupDecoder(context).decode(uri)
|
val backup = BackupDecoder(context).decode(uri)
|
||||||
|
|
||||||
// Store source mapping for error messages
|
// Store source mapping for error messages
|
||||||
val backupMaps = backup.backupSources + backup.backupBrokenSources.map { it.toBackupSource() }
|
val backupMaps = backup.backupSources
|
||||||
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
||||||
|
|
||||||
if (options.library) {
|
if (options.libraryEntries) {
|
||||||
restoreAmount += backup.backupManga.size + 1 // +1 for categories
|
restoreAmount += backup.backupManga.size
|
||||||
|
}
|
||||||
|
if (options.categories) {
|
||||||
|
restoreAmount += 1
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
if (options.savedSearches) {
|
if (options.savedSearches) {
|
||||||
@@ -85,12 +91,15 @@ class BackupRestorer(
|
|||||||
if (options.appSettings) {
|
if (options.appSettings) {
|
||||||
restoreAmount += 1
|
restoreAmount += 1
|
||||||
}
|
}
|
||||||
|
if (options.extensionRepoSettings) {
|
||||||
|
restoreAmount += backup.backupExtensionRepo.size
|
||||||
|
}
|
||||||
if (options.sourceSettings) {
|
if (options.sourceSettings) {
|
||||||
restoreAmount += 1
|
restoreAmount += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
if (options.library) {
|
if (options.categories) {
|
||||||
restoreCategories(backup.backupCategories)
|
restoreCategories(backup.backupCategories)
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
@@ -104,8 +113,11 @@ class BackupRestorer(
|
|||||||
if (options.sourceSettings) {
|
if (options.sourceSettings) {
|
||||||
restoreSourcePreferences(backup.backupSourcePreferences)
|
restoreSourcePreferences(backup.backupSourcePreferences)
|
||||||
}
|
}
|
||||||
if (options.library) {
|
if (options.libraryEntries) {
|
||||||
restoreManga(backup.backupManga, backup.backupCategories)
|
restoreManga(backup.backupManga, if (options.categories) backup.backupCategories else emptyList())
|
||||||
|
}
|
||||||
|
if (options.extensionRepoSettings) {
|
||||||
|
restoreExtensionRepos(backup.backupExtensionRepo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: optionally trigger online library + tracker update
|
// TODO: optionally trigger online library + tracker update
|
||||||
@@ -114,7 +126,7 @@ class BackupRestorer(
|
|||||||
|
|
||||||
private fun CoroutineScope.restoreCategories(backupCategories: List<BackupCategory>) = launch {
|
private fun CoroutineScope.restoreCategories(backupCategories: List<BackupCategory>) = launch {
|
||||||
ensureActive()
|
ensureActive()
|
||||||
categoriesRestorer.restoreCategories(backupCategories)
|
categoriesRestorer(backupCategories)
|
||||||
|
|
||||||
restoreProgress += 1
|
restoreProgress += 1
|
||||||
notifier.showRestoreProgress(
|
notifier.showRestoreProgress(
|
||||||
@@ -150,7 +162,7 @@ class BackupRestorer(
|
|||||||
ensureActive()
|
ensureActive()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mangaRestorer.restoreManga(it, backupCategories)
|
mangaRestorer.restore(it, backupCategories)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
val sourceName = sourceMapping[it.source] ?: it.source.toString()
|
val sourceName = sourceMapping[it.source] ?: it.source.toString()
|
||||||
errors.add(Date() to "${it.title} [$sourceName]: ${e.message}")
|
errors.add(Date() to "${it.title} [$sourceName]: ${e.message}")
|
||||||
@@ -163,7 +175,7 @@ class BackupRestorer(
|
|||||||
|
|
||||||
private fun CoroutineScope.restoreAppPreferences(preferences: List<BackupPreference>) = launch {
|
private fun CoroutineScope.restoreAppPreferences(preferences: List<BackupPreference>) = launch {
|
||||||
ensureActive()
|
ensureActive()
|
||||||
preferenceRestorer.restoreAppPreferences(preferences)
|
preferenceRestorer.restoreApp(preferences)
|
||||||
|
|
||||||
restoreProgress += 1
|
restoreProgress += 1
|
||||||
notifier.showRestoreProgress(
|
notifier.showRestoreProgress(
|
||||||
@@ -176,7 +188,7 @@ class BackupRestorer(
|
|||||||
|
|
||||||
private fun CoroutineScope.restoreSourcePreferences(preferences: List<BackupSourcePreferences>) = launch {
|
private fun CoroutineScope.restoreSourcePreferences(preferences: List<BackupSourcePreferences>) = launch {
|
||||||
ensureActive()
|
ensureActive()
|
||||||
preferenceRestorer.restoreSourcePreferences(preferences)
|
preferenceRestorer.restoreSource(preferences)
|
||||||
|
|
||||||
restoreProgress += 1
|
restoreProgress += 1
|
||||||
notifier.showRestoreProgress(
|
notifier.showRestoreProgress(
|
||||||
@@ -187,10 +199,33 @@ class BackupRestorer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.restoreExtensionRepos(
|
||||||
|
backupExtensionRepo: List<BackupExtensionRepos>,
|
||||||
|
) = launch {
|
||||||
|
backupExtensionRepo
|
||||||
|
.forEach {
|
||||||
|
ensureActive()
|
||||||
|
|
||||||
|
try {
|
||||||
|
extensionRepoRestorer(it)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
errors.add(Date() to "Error Adding Repo: ${it.name} : ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreProgress += 1
|
||||||
|
notifier.showRestoreProgress(
|
||||||
|
context.stringResource(MR.strings.extensionRepo_settings),
|
||||||
|
restoreProgress,
|
||||||
|
restoreAmount,
|
||||||
|
isSync,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun writeErrorLog(): File {
|
private fun writeErrorLog(): File {
|
||||||
try {
|
try {
|
||||||
if (errors.isNotEmpty()) {
|
if (errors.isNotEmpty()) {
|
||||||
val file = context.createFileInCacheDir("tachiyomi_restore.txt")
|
val file = context.createFileInCacheDir("mihon_restore_error.txt")
|
||||||
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
|
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault())
|
||||||
|
|
||||||
file.bufferedWriter().use { out ->
|
file.bufferedWriter().use { out ->
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import tachiyomi.i18n.MR
|
|||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
|
||||||
data class RestoreOptions(
|
data class RestoreOptions(
|
||||||
val library: Boolean = true,
|
val libraryEntries: Boolean = true,
|
||||||
|
val categories: Boolean = true,
|
||||||
val appSettings: Boolean = true,
|
val appSettings: Boolean = true,
|
||||||
|
val extensionRepoSettings: Boolean = true,
|
||||||
val sourceSettings: Boolean = true,
|
val sourceSettings: Boolean = true,
|
||||||
// SY -->
|
// SY -->
|
||||||
val savedSearches: Boolean = true,
|
val savedSearches: Boolean = true,
|
||||||
@@ -15,28 +17,46 @@ data class RestoreOptions(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun asBooleanArray() = booleanArrayOf(
|
fun asBooleanArray() = booleanArrayOf(
|
||||||
library,
|
libraryEntries,
|
||||||
|
categories,
|
||||||
appSettings,
|
appSettings,
|
||||||
|
extensionRepoSettings,
|
||||||
sourceSettings,
|
sourceSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
savedSearches
|
savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
fun anyEnabled() = library || appSettings || sourceSettings /* SY --> */ || savedSearches /* SY <-- */
|
fun canRestore() =
|
||||||
|
libraryEntries ||
|
||||||
|
categories ||
|
||||||
|
appSettings ||
|
||||||
|
extensionRepoSettings ||
|
||||||
|
sourceSettings /* SY --> */ ||
|
||||||
|
savedSearches /* SY <-- */
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val options = persistentListOf(
|
val options = persistentListOf(
|
||||||
Entry(
|
Entry(
|
||||||
label = MR.strings.label_library,
|
label = MR.strings.label_library,
|
||||||
getter = RestoreOptions::library,
|
getter = RestoreOptions::libraryEntries,
|
||||||
setter = { options, enabled -> options.copy(library = enabled) },
|
setter = { options, enabled -> options.copy(libraryEntries = enabled) },
|
||||||
|
),
|
||||||
|
Entry(
|
||||||
|
label = MR.strings.categories,
|
||||||
|
getter = RestoreOptions::categories,
|
||||||
|
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||||
),
|
),
|
||||||
Entry(
|
Entry(
|
||||||
label = MR.strings.app_settings,
|
label = MR.strings.app_settings,
|
||||||
getter = RestoreOptions::appSettings,
|
getter = RestoreOptions::appSettings,
|
||||||
setter = { options, enabled -> options.copy(appSettings = enabled) },
|
setter = { options, enabled -> options.copy(appSettings = enabled) },
|
||||||
),
|
),
|
||||||
|
Entry(
|
||||||
|
label = MR.strings.extensionRepo_settings,
|
||||||
|
getter = RestoreOptions::extensionRepoSettings,
|
||||||
|
setter = { options, enabled -> options.copy(extensionRepoSettings = enabled) },
|
||||||
|
),
|
||||||
Entry(
|
Entry(
|
||||||
label = MR.strings.source_settings,
|
label = MR.strings.source_settings,
|
||||||
getter = RestoreOptions::sourceSettings,
|
getter = RestoreOptions::sourceSettings,
|
||||||
@@ -52,11 +72,13 @@ data class RestoreOptions(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun fromBooleanArray(array: BooleanArray) = RestoreOptions(
|
fun fromBooleanArray(array: BooleanArray) = RestoreOptions(
|
||||||
library = array[0],
|
libraryEntries = array[0],
|
||||||
appSettings = array[1],
|
categories = array[1],
|
||||||
sourceSettings = array[2],
|
appSettings = array[2],
|
||||||
|
extensionRepoSettings = array[3],
|
||||||
|
sourceSettings = array[4],
|
||||||
// SY -->
|
// SY -->
|
||||||
savedSearches = array[3]
|
savedSearches = array[5],
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-8
@@ -13,7 +13,7 @@ class CategoriesRestorer(
|
|||||||
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
private val libraryPreferences: LibraryPreferences = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
suspend operator fun invoke(backupCategories: List<BackupCategory>) {
|
||||||
if (backupCategories.isNotEmpty()) {
|
if (backupCategories.isNotEmpty()) {
|
||||||
val dbCategories = getCategories.await()
|
val dbCategories = getCategories.await()
|
||||||
val dbCategoriesByName = dbCategories.associateBy { it.name }
|
val dbCategoriesByName = dbCategories.associateBy { it.name }
|
||||||
@@ -21,14 +21,15 @@ class CategoriesRestorer(
|
|||||||
|
|
||||||
val categories = backupCategories
|
val categories = backupCategories
|
||||||
.sortedBy { it.order }
|
.sortedBy { it.order }
|
||||||
.distinctBy { it.name }
|
|
||||||
.map {
|
.map {
|
||||||
val newOrder = nextOrder++
|
val dbCategory = dbCategoriesByName[it.name]
|
||||||
dbCategoriesByName[it.name]
|
if (dbCategory != null) return@map dbCategory
|
||||||
?: handler.awaitOneExecutable {
|
val order = nextOrder++
|
||||||
categoriesQueries.insert(it.name, newOrder, it.flags)
|
handler.awaitOneExecutable {
|
||||||
categoriesQueries.selectLastInsertedRowId()
|
categoriesQueries.insert(it.name, order, it.flags)
|
||||||
}.let { id -> it.toCategory(id).copy(order = newOrder) }
|
categoriesQueries.selectLastInsertedRowId()
|
||||||
|
}
|
||||||
|
.let { id -> it.toCategory(id).copy(order = order) }
|
||||||
}
|
}
|
||||||
|
|
||||||
libraryPreferences.categorizedDisplaySettings().set(
|
libraryPreferences.categorizedDisplaySettings().set(
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
||||||
|
import tachiyomi.data.DatabaseHandler
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class ExtensionRepoRestorer(
|
||||||
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
|
private val getExtensionRepos: GetExtensionRepo = Injekt.get(),
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend operator fun invoke(
|
||||||
|
backupRepo: BackupExtensionRepos,
|
||||||
|
) {
|
||||||
|
val dbRepos = getExtensionRepos.getAll()
|
||||||
|
val existingReposBySHA = dbRepos.associateBy { it.signingKeyFingerprint }
|
||||||
|
val existingReposByUrl = dbRepos.associateBy { it.baseUrl }
|
||||||
|
|
||||||
|
val urlExists = existingReposByUrl[backupRepo.baseUrl]
|
||||||
|
val shaExists = existingReposBySHA[backupRepo.signingKeyFingerprint]
|
||||||
|
|
||||||
|
if (urlExists != null && urlExists.signingKeyFingerprint != backupRepo.signingKeyFingerprint) {
|
||||||
|
error("Already Exists with different signing key fingerprint")
|
||||||
|
} else if (shaExists != null) {
|
||||||
|
error("${shaExists.name} has the same signing key fingerprint")
|
||||||
|
} else {
|
||||||
|
handler.await {
|
||||||
|
extension_reposQueries.insert(
|
||||||
|
backupRepo.baseUrl,
|
||||||
|
backupRepo.name,
|
||||||
|
backupRepo.shortName,
|
||||||
|
backupRepo.website,
|
||||||
|
backupRepo.signingKeyFingerprint,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -68,7 +68,7 @@ class MangaRestorer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun restoreManga(
|
suspend fun restore(
|
||||||
backupManga: BackupManga,
|
backupManga: BackupManga,
|
||||||
backupCategories: List<BackupCategory>,
|
backupCategories: List<BackupCategory>,
|
||||||
) {
|
) {
|
||||||
@@ -89,7 +89,7 @@ class MangaRestorer(
|
|||||||
chapters = backupManga.chapters,
|
chapters = backupManga.chapters,
|
||||||
categories = backupManga.categories,
|
categories = backupManga.categories,
|
||||||
backupCategories = backupCategories,
|
backupCategories = backupCategories,
|
||||||
history = backupManga.history + backupManga.brokenHistory.map { it.toBackupHistory() },
|
history = backupManga.history,
|
||||||
tracks = backupManga.tracking,
|
tracks = backupManga.tracking,
|
||||||
excludedScanlators = backupManga.excludedScanlators,
|
excludedScanlators = backupManga.excludedScanlators,
|
||||||
// SY -->
|
// SY -->
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user