Compare commits
313 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 | |||
| 46bf139f01 | |||
| c3fb5c0bec | |||
| 000a4ffc3f | |||
| 7b0b879d65 | |||
| 8a622f6c7d | |||
| 253060a3bc | |||
| b6b33e8c00 | |||
| 2e4f811090 | |||
| 215a1908f7 | |||
| 082acf000c | |||
| 2d1240b274 | |||
| 1e98709cc3 | |||
| 5550ddad4e | |||
| f9148c0c5e | |||
| 089e6268e7 | |||
| 712cd1493f | |||
| bbc8adc3e8 | |||
| 077b673c0a | |||
| 49eacf5178 | |||
| 98d1dddf4a | |||
| 37a616f3db | |||
| ad18696a1a | |||
| 34bb012a1c | |||
| 08c4989aa3 | |||
| 14dae420f5 | |||
| 65ed3c5ae6 | |||
| 5ae3508665 | |||
| e32eb0e009 | |||
| e0812ab5c8 | |||
| df9f79c120 | |||
| 990eb33b98 | |||
| e1bab1172a | |||
| aeeff72bed | |||
| 5895e78b39 | |||
| b24719a3e9 | |||
| d551619d9d | |||
| 06ad6c2e16 | |||
| df7e470e08 | |||
| 03f32ebffd | |||
| ed20d25452 | |||
| 596a8d002f | |||
| 206d824ed2 | |||
| 97ed4e55ad | |||
| 739f7bc848 | |||
| e866e60b19 | |||
| f135daeca5 | |||
| d80c19eb03 | |||
| 2d47147172 | |||
| de3570107e | |||
| 5480495619 | |||
| 694ef5f285 | |||
| 472c97c580 | |||
| 8b098b38f8 | |||
| 5e0585d724 | |||
| 3e438a9e87 | |||
| 8046c1a540 | |||
| 1f3f6cd4df | |||
| a62a5ed650 | |||
| a320903bc0 | |||
| a6c4f01c74 | |||
| a657c65261 | |||
| 5455daf96b | |||
| d40bc2b41b | |||
| 527ca85c39 | |||
| 189714eaf1 | |||
| 90d5104bdc | |||
| ceff887a10 | |||
| 2197bd0451 | |||
| 861a810961 | |||
| 81984c25df | |||
| b21d685a37 | |||
| fb4d9209f8 | |||
| 9ee0034c9a | |||
| 268b483182 | |||
| 2af6e7be32 | |||
| 3ecf86ae35 | |||
| 41bb0e08ba | |||
| 0bb1eb2da1 | |||
| 919df9a7cf | |||
| 2ea488bff5 | |||
| ec30ccccc2 | |||
| 780bdcbe55 | |||
| a90bc4c7fa | |||
| 5e421c6f0e | |||
| 742fdc19ca | |||
| 74505565ef | |||
| f041ed5b2a | |||
| 8762b20ab6 | |||
| 5a71889679 | |||
| a4983eb004 | |||
| 818bc7f75a | |||
| 7de6fa8c23 | |||
| edca9039e5 | |||
| fb1649125c | |||
| 0767526f18 | |||
| 5d1b1408eb | |||
| 2f54f00bf7 | |||
| 87feb58055 | |||
| 28edaca869 | |||
| d14f012bbb | |||
| adc6bbf54f | |||
| 2b064baca1 | |||
| 983a80ba42 | |||
| 911e959fcf | |||
| a425cae73b | |||
| d12a9d329b | |||
| 9018757496 | |||
| b0d91fa83f | |||
| 1caa929aa0 | |||
| 04e5be12e1 | |||
| 1136644a57 | |||
| d70258b956 | |||
| 54cb379a50 | |||
| 0e959c4594 | |||
| 6719f22eff | |||
| 45711cd394 | |||
| 334e9fb680 | |||
| 6e0bc981a6 | |||
| b7e55bc9f8 | |||
| a069e577ba | |||
| 0eb622643b | |||
| d93d0eea89 | |||
| 82846205b2 | |||
| 4a4fecb1e8 | |||
| ee6bc20f27 | |||
| 446a5cd5b3 | |||
| cdb07c893b | |||
| a4d88515fb | |||
| 345d0821c6 | |||
| a9fd1f8811 | |||
| 31e5ba4caf | |||
| 202900edf0 | |||
| f79959c7bc | |||
| 237d8d6b33 | |||
| 117e0d5792 | |||
| 64bbe941a4 |
@@ -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 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,19 +31,26 @@ 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
|
||||||
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
|
with:
|
||||||
|
path: app/src/main/assets/client_secrets.json
|
||||||
|
contents: ${{ secrets.CLIENT_SECRETS_TEXT }}
|
||||||
|
write-mode: overwrite
|
||||||
# SY -->
|
# SY -->
|
||||||
|
|
||||||
- name: Build app and run unit tests
|
- name: Build app and run unit tests
|
||||||
run: ./gradlew 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
|
||||||
@@ -79,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,15 +15,12 @@ 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: TAG - Bump version and push tag
|
- name: Create Tag
|
||||||
uses: anothrNick/github-tag-action@1.67.0
|
run: |
|
||||||
env:
|
git tag "preview-${{ github.run_number }}"
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
git push origin "preview-${{ github.run_number }}"
|
||||||
WITH_V: true
|
|
||||||
RELEASE_BRANCHES: master
|
|
||||||
DEFAULT_BUMP: patch
|
|
||||||
|
|
||||||
- name: PING - Dispatch initiating repository event
|
- name: PING - Dispatch initiating repository event
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ jobs:
|
|||||||
"ignoreCase": true,
|
"ignoreCase": true,
|
||||||
"labels": ["Cloudflare protected"],
|
"labels": ["Cloudflare protected"],
|
||||||
"message": "Refer to the **Solving Cloudflare issues** section at https://mihon.app/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
|
"message": "Refer to the **Solving Cloudflare issues** section at https://mihon.app/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "both",
|
||||||
|
"regex": "^.*(myanimelist|mal).*$",
|
||||||
|
"ignoreCase": true,
|
||||||
|
"message": "For issues with linking MyAnimeList, please follow these steps:\n1. Update Mihon to version 0.16.4 or newer\n2. Change your default User-Agent (`More → Settings → Advanced → Default user agent string`)\n3. Close and restart Mihon\n4. Attempt to link MyAnimeList again\n\nIf you had MyAnimeList linked before, try to unlink it first before trying these steps."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
auto-close-ignore-label: do-not-autoclose
|
auto-close-ignore-label: do-not-autoclose
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -22,3 +23,4 @@ TODO.md
|
|||||||
CHANGELOG.md
|
CHANGELOG.md
|
||||||
/captures
|
/captures
|
||||||
build.sh
|
build.sh
|
||||||
|
/app/src/main/assets/client_secrets.json
|
||||||
|
|||||||
+24
-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,31 +24,41 @@ 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
|
||||||
|
1. Go to [Google Cloud Console](https://console.cloud.google.com)
|
||||||
|
2. Create a new project
|
||||||
|
3. Go to API & Services -> Library -> Google Drive API and click enable
|
||||||
|
4. Go to API & Services -> Oauth consent screen
|
||||||
|
5. Create it, fill in the app name, user support email, and developer contact information
|
||||||
|
6. In the next screen, click add or remove scopes, and add the `.../auth/drive.appdata` and `.../auth/drive.file` scopes
|
||||||
|
7. Don't add any test users and go back to the dashboard
|
||||||
|
8. Click publish
|
||||||
|
9. Go to API & Services -> Credentials
|
||||||
|
10. Click Create credentials -> Oauth client ID
|
||||||
|
11. Select Android, give it a name, and set `eu.kanade.google.oauth` as the package name
|
||||||
|
12. To get the SHA-1 key, run `keytool -printcert -jarfile app-standard-universal-release.apk` on your apk, and copy the listed SHA-1
|
||||||
|
13. Expand advanced settings, and enable Custom URL scheme
|
||||||
|
14. After that just download the json, name it to `client_secrets.json` and put it in `app/src/main/assets/`
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
| Preview Builds | Release Builds | Tachiyomi Support Server |
|
| Preview Builds | Release Builds | Mihon Support Server |
|
||||||
|-------|----------|----------|
|
|-------|----------|----------|
|
||||||
| [](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [](https://github.com/jobobby04/tachiyomisy/releases/latest) | [](https://discord.gg/mihon) |
|
| [](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [](https://github.com/jobobby04/tachiyomisy/releases/latest) | [](https://discord.gg/mihon) |
|
||||||
|
|
||||||
|
|
||||||
# TachiyomiSY
|
# TachiyomiSY
|
||||||
Tachiyomi is a free and open source manga reader for Android 6.0 and above. This version of Tachiyomi, TachiyomiSY was based off TachiyomiAZ. This version is meant to push forward in the ways of usability and features. TachiyomiSY tries to push forward where it can, but staying in a place where it can easily grab updates and features from the main app, it tries to make new features, or take features from other forks like J2K and Neko.
|
Mihon is a free and open source manga reader for Android 6.0 and above. This version of Mihon, TachiyomiSY was based off TachiyomiAZ. This version is meant to push forward in the ways of usability and features. TachiyomiSY tries to push forward where it can, but staying in a place where it can easily grab updates and features from the main app, it tries to make new features, or take features from other forks like J2K and Neko.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
Features of Tachiyomi(original) include:
|
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
|
||||||
@@ -42,7 +42,6 @@ Features of TachiyomiSY include:
|
|||||||
* Page preload customization
|
* Page preload customization
|
||||||
* Customize image cache size
|
* Customize image cache size
|
||||||
* Batch import of custom sources and featured extensions
|
* Batch import of custom sources and featured extensions
|
||||||
* Automatic CAPTCHA solving
|
|
||||||
* Advanced source settings page, searching, enable/disable all
|
* Advanced source settings page, searching, enable/disable all
|
||||||
* Click tag for local search, long click tag for global search
|
* Click tag for local search, long click tag for global search
|
||||||
* Merge multiple of the same manga from different sources
|
* Merge multiple of the same manga from different sources
|
||||||
@@ -68,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>
|
||||||
@@ -89,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>
|
||||||
|
|
||||||
@@ -116,4 +122,4 @@ See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
|
|||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
[See our website.](https://mihon.app/)
|
[See our website.](https://mihon.app/)
|
||||||
You can also reach out to us on [Discord](https://discord.gg/mihon).
|
You can also reach out to us on [Discord](https://discord.gg/mihon).
|
||||||
|
|||||||
+21
-41
@@ -1,9 +1,12 @@
|
|||||||
|
import mihon.buildlogic.getBuildTime
|
||||||
|
import mihon.buildlogic.getCommitCount
|
||||||
|
import mihon.buildlogic.getGitSha
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("mihon.android.application")
|
||||||
|
id("mihon.android.application.compose")
|
||||||
id("com.mikepenz.aboutlibraries.plugin")
|
id("com.mikepenz.aboutlibraries.plugin")
|
||||||
kotlin("android")
|
|
||||||
kotlin("plugin.parcelize")
|
kotlin("plugin.parcelize")
|
||||||
kotlin("plugin.serialization")
|
kotlin("plugin.serialization")
|
||||||
// id("com.github.zellius.shortcut-helper")
|
// id("com.github.zellius.shortcut-helper")
|
||||||
@@ -18,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"
|
||||||
@@ -26,7 +29,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "eu.kanade.tachiyomi.sy"
|
applicationId = "eu.kanade.tachiyomi.sy"
|
||||||
|
|
||||||
versionCode = 65
|
versionCode = 69
|
||||||
versionName = "1.10.5"
|
versionName = "1.10.5"
|
||||||
|
|
||||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||||
@@ -35,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"
|
||||||
}
|
}
|
||||||
@@ -44,7 +47,7 @@ android {
|
|||||||
abi {
|
abi {
|
||||||
isEnable = true
|
isEnable = true
|
||||||
reset()
|
reset()
|
||||||
include(*SUPPORTED_ABIS.toTypedArray())
|
include(*supportedAbis.toTypedArray())
|
||||||
isUniversalApk = true
|
isUniversalApk = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,7 +123,6 @@ android {
|
|||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
compose = true
|
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
|
|
||||||
// Disable some unused things
|
// Disable some unused things
|
||||||
@@ -133,10 +135,6 @@ android {
|
|||||||
abortOnError = false
|
abortOnError = false
|
||||||
checkReleaseBuilds = false
|
checkReleaseBuilds = false
|
||||||
}
|
}
|
||||||
|
|
||||||
composeOptions {
|
|
||||||
kotlinCompilerExtensionVersion = compose.versions.compiler.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -154,26 +152,25 @@ dependencies {
|
|||||||
implementation(projects.presentationWidget)
|
implementation(projects.presentationWidget)
|
||||||
|
|
||||||
// Compose
|
// Compose
|
||||||
implementation(platform(compose.bom))
|
|
||||||
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)
|
||||||
debugImplementation(compose.ui.tooling)
|
debugImplementation(compose.ui.tooling)
|
||||||
implementation(compose.ui.tooling.preview)
|
implementation(compose.ui.tooling.preview)
|
||||||
implementation(compose.ui.util)
|
implementation(compose.ui.util)
|
||||||
implementation(compose.accompanist.webview)
|
|
||||||
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)
|
||||||
@@ -215,10 +212,6 @@ dependencies {
|
|||||||
// Disk
|
// Disk
|
||||||
implementation(libs.disklrucache)
|
implementation(libs.disklrucache)
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.junrar)
|
|
||||||
// SY -->
|
|
||||||
implementation(libs.zip4j)
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation(libs.preferencektx)
|
implementation(libs.preferencektx)
|
||||||
@@ -247,12 +240,13 @@ dependencies {
|
|||||||
implementation(libs.bundles.voyager)
|
implementation(libs.bundles.voyager)
|
||||||
implementation(libs.compose.materialmotion)
|
implementation(libs.compose.materialmotion)
|
||||||
implementation(libs.swipe)
|
implementation(libs.swipe)
|
||||||
|
implementation(libs.compose.webview)
|
||||||
|
implementation(libs.compose.grid)
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
implementation(libs.logcat)
|
implementation(libs.logcat)
|
||||||
|
|
||||||
// Crash reports/analytics
|
// Crash reports/analytics
|
||||||
// implementation(libs.bundles.acra)
|
|
||||||
// "standardImplementation"(libs.firebase.analytics)
|
// "standardImplementation"(libs.firebase.analytics)
|
||||||
|
|
||||||
// Shizuku
|
// Shizuku
|
||||||
@@ -265,6 +259,8 @@ dependencies {
|
|||||||
// debugImplementation(libs.leakcanary.android)
|
// debugImplementation(libs.leakcanary.android)
|
||||||
implementation(libs.leakcanary.plumber)
|
implementation(libs.leakcanary.plumber)
|
||||||
|
|
||||||
|
testImplementation(kotlinx.coroutines.test)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
// Text distance (EH)
|
// Text distance (EH)
|
||||||
implementation(sylibs.simularity)
|
implementation(sylibs.simularity)
|
||||||
@@ -279,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 {
|
||||||
@@ -300,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",
|
||||||
@@ -311,31 +311,11 @@ tasks {
|
|||||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
|
||||||
"-opt-in=coil3.annotation.ExperimentalCoilApi",
|
"-opt-in=coil3.annotation.ExperimentalCoilApi",
|
||||||
"-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi",
|
|
||||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
"-opt-in=kotlinx.coroutines.FlowPreview",
|
"-opt-in=kotlinx.coroutines.FlowPreview",
|
||||||
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
||||||
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
|
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
|
||||||
)
|
)
|
||||||
|
|
||||||
if (project.findProperty("tachiyomi.enableComposeCompilerMetrics") == "true") {
|
|
||||||
kotlinOptions.freeCompilerArgs += listOf(
|
|
||||||
"-P",
|
|
||||||
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=" +
|
|
||||||
project.layout.buildDirectory.dir("compose_metrics").get().asFile.absolutePath,
|
|
||||||
)
|
|
||||||
kotlinOptions.freeCompilerArgs += listOf(
|
|
||||||
"-P",
|
|
||||||
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=" +
|
|
||||||
project.layout.buildDirectory.dir("compose_metrics").get().asFile.absolutePath,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://developer.android.com/jetpack/androidx/releases/compose-compiler#1.5.9
|
|
||||||
kotlinOptions.freeCompilerArgs += listOf(
|
|
||||||
"-P",
|
|
||||||
"plugin:androidx.compose.compiler.plugins.kotlin:nonSkippingGroupOptimization=true",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+27
-1
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
-keep,allowoptimization class eu.kanade.**
|
-keep,allowoptimization class eu.kanade.**
|
||||||
-keep,allowoptimization class tachiyomi.**
|
-keep,allowoptimization class tachiyomi.**
|
||||||
|
-keep,allowoptimization class mihon.**
|
||||||
|
|
||||||
# Keep common dependencies used in extensions
|
# Keep common dependencies used in extensions
|
||||||
-keep,allowoptimization class androidx.preference.** { public protected *; }
|
-keep,allowoptimization class androidx.preference.** { public protected *; }
|
||||||
@@ -46,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
|
||||||
@@ -126,6 +131,12 @@
|
|||||||
-keep class com.google.firebase.installations.** { *; }
|
-keep class com.google.firebase.installations.** { *; }
|
||||||
-keep interface com.google.firebase.installations.** { *; }
|
-keep interface com.google.firebase.installations.** { *; }
|
||||||
|
|
||||||
|
# Google Drive
|
||||||
|
-keep class com.google.api.services.** { *; }
|
||||||
|
|
||||||
|
# Google OAuth
|
||||||
|
-keep class com.google.api.client.** { *; }
|
||||||
|
|
||||||
# SY -->
|
# SY -->
|
||||||
# SqlCipher
|
# SqlCipher
|
||||||
-keepclassmembers class net.zetetic.database.sqlcipher.SQLiteCustomFunction { *; }
|
-keepclassmembers class net.zetetic.database.sqlcipher.SQLiteCustomFunction { *; }
|
||||||
@@ -260,6 +271,9 @@
|
|||||||
-keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference
|
-keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference
|
||||||
-keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; }
|
-keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; }
|
||||||
|
|
||||||
|
# Keep apache http client
|
||||||
|
-keep class org.apache.http.** { *; }
|
||||||
|
|
||||||
# Suggested rules
|
# Suggested rules
|
||||||
-dontwarn com.oracle.svm.core.annotate.AutomaticFeature
|
-dontwarn com.oracle.svm.core.annotate.AutomaticFeature
|
||||||
-dontwarn com.oracle.svm.core.annotate.Delete
|
-dontwarn com.oracle.svm.core.annotate.Delete
|
||||||
@@ -272,4 +286,16 @@
|
|||||||
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
||||||
-dontwarn java.lang.Module
|
-dontwarn java.lang.Module
|
||||||
-dontwarn org.graalvm.nativeimage.hosted.RuntimeResourceAccess
|
-dontwarn org.graalvm.nativeimage.hosted.RuntimeResourceAccess
|
||||||
-dontwarn org.jspecify.annotations.NullMarked
|
-dontwarn org.jspecify.annotations.NullMarked
|
||||||
|
-dontwarn javax.naming.InvalidNameException
|
||||||
|
-dontwarn javax.naming.NamingException
|
||||||
|
-dontwarn javax.naming.directory.Attribute
|
||||||
|
-dontwarn javax.naming.directory.Attributes
|
||||||
|
-dontwarn javax.naming.ldap.LdapName
|
||||||
|
-dontwarn javax.naming.ldap.Rdn
|
||||||
|
-dontwarn org.ietf.jgss.GSSContext
|
||||||
|
-dontwarn org.ietf.jgss.GSSCredential
|
||||||
|
-dontwarn org.ietf.jgss.GSSException
|
||||||
|
-dontwarn org.ietf.jgss.GSSManager
|
||||||
|
-dontwarn org.ietf.jgss.GSSName
|
||||||
|
-dontwarn org.ietf.jgss.Oid
|
||||||
@@ -3,4 +3,4 @@
|
|||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_tachi_monochrome_launcher" />
|
<monochrome android:drawable="@drawable/ic_tachi_monochrome_launcher" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_tachi_monochrome_launcher" />
|
<monochrome android:drawable="@drawable/ic_tachi_monochrome_launcher" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
@@ -188,6 +188,20 @@
|
|||||||
<data android:host="shikimori-auth" />
|
<data android:host="shikimori-auth" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.setting.track.GoogleDriveLoginActivity"
|
||||||
|
android:label="GoogleDrive"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:scheme="eu.kanade.google.oauth" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="exh.ui.login.EhLoginActivity"
|
android:name="exh.ui.login.EhLoginActivity"
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ import eu.kanade.domain.chapter.interactor.GetAvailableScanlators
|
|||||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.download.interactor.DeleteDownload
|
import eu.kanade.domain.download.interactor.DeleteDownload
|
||||||
import eu.kanade.domain.extension.interactor.CreateExtensionRepo
|
|
||||||
import eu.kanade.domain.extension.interactor.DeleteExtensionRepo
|
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
import eu.kanade.domain.extension.interactor.GetExtensionLanguages
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionRepos
|
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionsByType
|
import eu.kanade.domain.extension.interactor.GetExtensionsByType
|
||||||
import eu.kanade.domain.extension.interactor.TrustExtension
|
import eu.kanade.domain.extension.interactor.TrustExtension
|
||||||
@@ -26,6 +23,17 @@ import eu.kanade.domain.track.interactor.AddTracks
|
|||||||
import eu.kanade.domain.track.interactor.RefreshTracks
|
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.domain.chapter.interactor.FilterChaptersForDownload
|
||||||
|
import mihon.domain.extensionrepo.interactor.CreateExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.DeleteExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepoCount
|
||||||
|
import mihon.domain.extensionrepo.interactor.ReplaceExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.UpdateExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.repository.ExtensionRepoRepository
|
||||||
|
import mihon.domain.extensionrepo.service.ExtensionRepoService
|
||||||
|
import mihon.domain.upcoming.interactor.GetUpcomingManga
|
||||||
import tachiyomi.data.category.CategoryRepositoryImpl
|
import tachiyomi.data.category.CategoryRepositoryImpl
|
||||||
import tachiyomi.data.chapter.ChapterRepositoryImpl
|
import tachiyomi.data.chapter.ChapterRepositoryImpl
|
||||||
import tachiyomi.data.history.HistoryRepositoryImpl
|
import tachiyomi.data.history.HistoryRepositoryImpl
|
||||||
@@ -111,6 +119,7 @@ class DomainModule : InjektModule {
|
|||||||
addFactory { GetMangaByUrlAndSourceId(get()) }
|
addFactory { GetMangaByUrlAndSourceId(get()) }
|
||||||
addFactory { GetManga(get()) }
|
addFactory { GetManga(get()) }
|
||||||
addFactory { GetNextChapters(get(), get(), get(), get()) }
|
addFactory { GetNextChapters(get(), get(), get(), get()) }
|
||||||
|
addFactory { GetUpcomingManga(get()) }
|
||||||
addFactory { ResetViewerFlags(get()) }
|
addFactory { ResetViewerFlags(get()) }
|
||||||
addFactory { SetMangaChapterFlags(get()) }
|
addFactory { SetMangaChapterFlags(get()) }
|
||||||
addFactory { FetchInterval(get()) }
|
addFactory { FetchInterval(get()) }
|
||||||
@@ -144,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()) }
|
||||||
@@ -171,10 +181,15 @@ class DomainModule : InjektModule {
|
|||||||
addFactory { ToggleLanguage(get()) }
|
addFactory { ToggleLanguage(get()) }
|
||||||
addFactory { ToggleSource(get()) }
|
addFactory { ToggleSource(get()) }
|
||||||
addFactory { ToggleSourcePin(get()) }
|
addFactory { ToggleSourcePin(get()) }
|
||||||
addFactory { TrustExtension(get()) }
|
addFactory { TrustExtension(get(), get()) }
|
||||||
|
|
||||||
addFactory { CreateExtensionRepo(get()) }
|
addSingletonFactory<ExtensionRepoRepository> { ExtensionRepoRepositoryImpl(get()) }
|
||||||
|
addFactory { ExtensionRepoService(get(), get()) }
|
||||||
|
addFactory { GetExtensionRepo(get()) }
|
||||||
|
addFactory { GetExtensionRepoCount(get()) }
|
||||||
|
addFactory { CreateExtensionRepo(get(), get()) }
|
||||||
addFactory { DeleteExtensionRepo(get()) }
|
addFactory { DeleteExtensionRepo(get()) }
|
||||||
addFactory { GetExtensionRepos(get()) }
|
addFactory { ReplaceExtensionRepo(get()) }
|
||||||
|
addFactory { UpdateExtensionRepo(get(), get()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package eu.kanade.domain.base
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
|
||||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
|
||||||
import tachiyomi.core.common.preference.Preference
|
import tachiyomi.core.common.preference.Preference
|
||||||
import tachiyomi.core.common.preference.PreferenceStore
|
import tachiyomi.core.common.preference.PreferenceStore
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
@@ -22,8 +20,6 @@ class BasePreferences(
|
|||||||
|
|
||||||
fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore)
|
fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore)
|
||||||
|
|
||||||
fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType)
|
|
||||||
|
|
||||||
fun shownOnboardingFlow() = preferenceStore.getBoolean(Preference.appStateKey("onboarding_complete"), false)
|
fun shownOnboardingFlow() = preferenceStore.getBoolean(Preference.appStateKey("onboarding_complete"), false)
|
||||||
|
|
||||||
enum class ExtensionInstaller(val titleRes: StringResource, val requiresSystemPermission: Boolean) {
|
enum class ExtensionInstaller(val titleRes: StringResource, val requiresSystemPermission: Boolean) {
|
||||||
@@ -32,4 +28,6 @@ class BasePreferences(
|
|||||||
SHIZUKU(MR.strings.ext_installer_shizuku, false),
|
SHIZUKU(MR.strings.ext_installer_shizuku, false),
|
||||||
PRIVATE(MR.strings.ext_installer_private, false),
|
PRIVATE(MR.strings.ext_installer_private, false),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun displayProfile() = preferenceStore.getString("pref_display_profile_key", "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,4 +39,5 @@ fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
|
|||||||
it.date_upload = dateUpload
|
it.date_upload = dateUpload
|
||||||
it.chapter_number = chapterNumber.toFloat()
|
it.chapter_number = chapterNumber.toFloat()
|
||||||
it.source_order = sourceOrder.toInt()
|
it.source_order = sourceOrder.toInt()
|
||||||
|
it.last_modified = lastModifiedAt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package eu.kanade.domain.extension.interactor
|
|
||||||
|
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
|
||||||
import tachiyomi.core.common.preference.plusAssign
|
|
||||||
|
|
||||||
class CreateExtensionRepo(private val preferences: SourcePreferences) {
|
|
||||||
|
|
||||||
fun await(name: String): Result {
|
|
||||||
// Do not allow invalid formats
|
|
||||||
if (!name.matches(repoRegex)) {
|
|
||||||
return Result.InvalidUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
preferences.extensionRepos() += name.removeSuffix("/index.min.json")
|
|
||||||
|
|
||||||
return Result.Success
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed interface Result {
|
|
||||||
data object InvalidUrl : Result
|
|
||||||
data object Success : Result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val repoRegex = """^https://.*/index\.min\.json$""".toRegex()
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package eu.kanade.domain.extension.interactor
|
|
||||||
|
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
|
||||||
import tachiyomi.core.common.preference.minusAssign
|
|
||||||
|
|
||||||
class DeleteExtensionRepo(private val preferences: SourcePreferences) {
|
|
||||||
|
|
||||||
fun await(repo: String) {
|
|
||||||
preferences.extensionRepos() -= repo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package eu.kanade.domain.extension.interactor
|
|
||||||
|
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
class GetExtensionRepos(private val preferences: SourcePreferences) {
|
|
||||||
|
|
||||||
fun subscribe(): Flow<Set<String>> {
|
|
||||||
return preferences.extensionRepos().changes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,7 @@ class GetExtensionsByType(
|
|||||||
extensionManager.installedExtensionsFlow,
|
extensionManager.installedExtensionsFlow,
|
||||||
extensionManager.untrustedExtensionsFlow,
|
extensionManager.untrustedExtensionsFlow,
|
||||||
extensionManager.availableExtensionsFlow,
|
extensionManager.availableExtensionsFlow,
|
||||||
) { _activeLanguages, _installed, _untrusted, _available ->
|
) { enabledLanguages, _installed, _untrusted, _available ->
|
||||||
val (updates, installed) = _installed
|
val (updates, installed) = _installed
|
||||||
.filter { (showNsfwSources || !it.isNsfw) }
|
.filter { (showNsfwSources || !it.isNsfw) }
|
||||||
.sortedWith(
|
.sortedWith(
|
||||||
@@ -41,9 +41,9 @@ class GetExtensionsByType(
|
|||||||
}
|
}
|
||||||
.flatMap { ext ->
|
.flatMap { ext ->
|
||||||
if (ext.sources.isEmpty()) {
|
if (ext.sources.isEmpty()) {
|
||||||
return@flatMap if (ext.lang in _activeLanguages) listOf(ext) else emptyList()
|
return@flatMap if (ext.lang in enabledLanguages) listOf(ext) else emptyList()
|
||||||
}
|
}
|
||||||
ext.sources.filter { it.lang in _activeLanguages }
|
ext.sources.filter { it.lang in enabledLanguages }
|
||||||
.map {
|
.map {
|
||||||
ext.copy(
|
ext.copy(
|
||||||
name = it.name,
|
name = it.name,
|
||||||
|
|||||||
@@ -3,15 +3,18 @@ package eu.kanade.domain.extension.interactor
|
|||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
|
import mihon.domain.extensionrepo.repository.ExtensionRepoRepository
|
||||||
import tachiyomi.core.common.preference.getAndSet
|
import tachiyomi.core.common.preference.getAndSet
|
||||||
|
|
||||||
class TrustExtension(
|
class TrustExtension(
|
||||||
|
private val extensionRepoRepository: ExtensionRepoRepository,
|
||||||
private val preferences: SourcePreferences,
|
private val preferences: SourcePreferences,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun isTrusted(pkgInfo: PackageInfo, signatureHash: String): Boolean {
|
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
|
||||||
val key = "${pkgInfo.packageName}:${PackageInfoCompat.getLongVersionCode(pkgInfo)}:$signatureHash"
|
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
|
||||||
return key in preferences.trustedExtensions().get()
|
val key = "${pkgInfo.packageName}:${PackageInfoCompat.getLongVersionCode(pkgInfo)}:${fingerprints.last()}"
|
||||||
|
return trustedFingerprints.any { fingerprints.contains(it) } || key in preferences.trustedExtensions().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trust(pkgName: String, versionCode: Long, signatureHash: String) {
|
fun trust(pkgName: String, versionCode: Long, signatureHash: String) {
|
||||||
@@ -19,9 +22,7 @@ class TrustExtension(
|
|||||||
// Remove previously trusted versions
|
// Remove previously trusted versions
|
||||||
val removed = exts.filterNot { it.startsWith("$pkgName:") }.toMutableSet()
|
val removed = exts.filterNot { it.startsWith("$pkgName:") }.toMutableSet()
|
||||||
|
|
||||||
removed.also {
|
removed.also { it += "$pkgName:$versionCode:$signatureHash" }
|
||||||
it += "$pkgName:$versionCode:$signatureHash"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package eu.kanade.domain.sync
|
||||||
|
|
||||||
|
import eu.kanade.domain.sync.models.SyncSettings
|
||||||
|
import eu.kanade.tachiyomi.data.sync.models.SyncTriggerOptions
|
||||||
|
import tachiyomi.core.common.preference.Preference
|
||||||
|
import tachiyomi.core.common.preference.PreferenceStore
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class SyncPreferences(
|
||||||
|
private val preferenceStore: PreferenceStore,
|
||||||
|
) {
|
||||||
|
fun clientHost() = preferenceStore.getString("sync_client_host", "https://sync.tachiyomi.org")
|
||||||
|
fun clientAPIKey() = preferenceStore.getString("sync_client_api_key", "")
|
||||||
|
fun lastSyncTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_sync_timestamp"), 0L)
|
||||||
|
|
||||||
|
fun lastSyncEtag() = preferenceStore.getString("sync_etag", "")
|
||||||
|
|
||||||
|
fun syncInterval() = preferenceStore.getInt("sync_interval", 0)
|
||||||
|
fun syncService() = preferenceStore.getInt("sync_service", 0)
|
||||||
|
|
||||||
|
fun googleDriveAccessToken() = preferenceStore.getString(
|
||||||
|
Preference.appStateKey("google_drive_access_token"),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun googleDriveRefreshToken() = preferenceStore.getString(
|
||||||
|
Preference.appStateKey("google_drive_refresh_token"),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun uniqueDeviceID(): String {
|
||||||
|
val uniqueIDPreference = preferenceStore.getString(Preference.appStateKey("unique_device_id"), "")
|
||||||
|
|
||||||
|
// Retrieve the current value of the preference
|
||||||
|
var uniqueID = uniqueIDPreference.get()
|
||||||
|
if (uniqueID.isBlank()) {
|
||||||
|
uniqueID = UUID.randomUUID().toString()
|
||||||
|
uniqueIDPreference.set(uniqueID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isSyncEnabled(): Boolean {
|
||||||
|
return syncService().get() != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSyncSettings(): SyncSettings {
|
||||||
|
return SyncSettings(
|
||||||
|
libraryEntries = preferenceStore.getBoolean("library_entries", true).get(),
|
||||||
|
categories = preferenceStore.getBoolean("categories", true).get(),
|
||||||
|
chapters = preferenceStore.getBoolean("chapters", true).get(),
|
||||||
|
tracking = preferenceStore.getBoolean("tracking", true).get(),
|
||||||
|
history = preferenceStore.getBoolean("history", true).get(),
|
||||||
|
appSettings = preferenceStore.getBoolean("appSettings", true).get(),
|
||||||
|
extensionRepoSettings = preferenceStore.getBoolean("extensionRepoSettings", true).get(),
|
||||||
|
sourceSettings = preferenceStore.getBoolean("sourceSettings", true).get(),
|
||||||
|
privateSettings = preferenceStore.getBoolean("privateSettings", true).get(),
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
customInfo = preferenceStore.getBoolean("customInfo", true).get(),
|
||||||
|
readEntries = preferenceStore.getBoolean("readEntries", true).get(),
|
||||||
|
savedSearches = preferenceStore.getBoolean("savedSearches", true).get(),
|
||||||
|
// SY <--
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSyncSettings(syncSettings: SyncSettings) {
|
||||||
|
preferenceStore.getBoolean("library_entries", true).set(syncSettings.libraryEntries)
|
||||||
|
preferenceStore.getBoolean("categories", true).set(syncSettings.categories)
|
||||||
|
preferenceStore.getBoolean("chapters", true).set(syncSettings.chapters)
|
||||||
|
preferenceStore.getBoolean("tracking", true).set(syncSettings.tracking)
|
||||||
|
preferenceStore.getBoolean("history", true).set(syncSettings.history)
|
||||||
|
preferenceStore.getBoolean("appSettings", true).set(syncSettings.appSettings)
|
||||||
|
preferenceStore.getBoolean("extensionRepoSettings", true).set(syncSettings.extensionRepoSettings)
|
||||||
|
preferenceStore.getBoolean("sourceSettings", true).set(syncSettings.sourceSettings)
|
||||||
|
preferenceStore.getBoolean("privateSettings", true).set(syncSettings.privateSettings)
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
preferenceStore.getBoolean("customInfo", true).set(syncSettings.customInfo)
|
||||||
|
preferenceStore.getBoolean("readEntries", true).set(syncSettings.readEntries)
|
||||||
|
preferenceStore.getBoolean("savedSearches", true).set(syncSettings.savedSearches)
|
||||||
|
// SY <--
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSyncTriggerOptions(): SyncTriggerOptions {
|
||||||
|
return SyncTriggerOptions(
|
||||||
|
syncOnChapterRead = preferenceStore.getBoolean("sync_on_chapter_read", false).get(),
|
||||||
|
syncOnChapterOpen = preferenceStore.getBoolean("sync_on_chapter_open", false).get(),
|
||||||
|
syncOnAppStart = preferenceStore.getBoolean("sync_on_app_start", false).get(),
|
||||||
|
syncOnAppResume = preferenceStore.getBoolean("sync_on_app_resume", false).get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSyncTriggerOptions(syncTriggerOptions: SyncTriggerOptions) {
|
||||||
|
preferenceStore.getBoolean("sync_on_chapter_read", false)
|
||||||
|
.set(syncTriggerOptions.syncOnChapterRead)
|
||||||
|
preferenceStore.getBoolean("sync_on_chapter_open", false)
|
||||||
|
.set(syncTriggerOptions.syncOnChapterOpen)
|
||||||
|
preferenceStore.getBoolean("sync_on_app_start", false)
|
||||||
|
.set(syncTriggerOptions.syncOnAppStart)
|
||||||
|
preferenceStore.getBoolean("sync_on_app_resume", false)
|
||||||
|
.set(syncTriggerOptions.syncOnAppResume)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package eu.kanade.domain.sync.models
|
||||||
|
|
||||||
|
data class SyncSettings(
|
||||||
|
val libraryEntries: Boolean = true,
|
||||||
|
val categories: Boolean = true,
|
||||||
|
val chapters: Boolean = true,
|
||||||
|
val tracking: Boolean = true,
|
||||||
|
val history: Boolean = true,
|
||||||
|
val appSettings: Boolean = true,
|
||||||
|
val extensionRepoSettings: Boolean = true,
|
||||||
|
val sourceSettings: Boolean = true,
|
||||||
|
val privateSettings: Boolean = false,
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
val customInfo: Boolean = true,
|
||||||
|
val readEntries: Boolean = true,
|
||||||
|
val savedSearches: Boolean = true,
|
||||||
|
// 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)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.net.Uri
|
|||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
@@ -241,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,8 +250,8 @@ private fun DetailsHeader(
|
|||||||
Update available: ${extension.hasUpdate}
|
Update available: ${extension.hasUpdate}
|
||||||
Obsolete: ${extension.isObsolete}
|
Obsolete: ${extension.isObsolete}
|
||||||
Shared: ${extension.isShared}
|
Shared: ${extension.isShared}
|
||||||
Repository: ${extension.repoUrl}
|
Repository: ${extension.repoUrl}
|
||||||
""".trimIndent()
|
""".trimIndent(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -362,10 +361,8 @@ private fun InfoText(
|
|||||||
primaryTextStyle: TextStyle = MaterialTheme.typography.bodyLarge,
|
primaryTextStyle: TextStyle = MaterialTheme.typography.bodyLarge,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
|
||||||
|
|
||||||
val clickableModifier = if (onClick != null) {
|
val clickableModifier = if (onClick != null) {
|
||||||
Modifier.clickable(interactionSource, indication = null) { onClick() }
|
Modifier.clickable(interactionSource = null, indication = null, onClick = onClick)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ fun FeedScreen(
|
|||||||
onClickDelete: (FeedSavedSearch) -> Unit,
|
onClickDelete: (FeedSavedSearch) -> Unit,
|
||||||
onClickManga: (Manga) -> Unit,
|
onClickManga: (Manga) -> Unit,
|
||||||
onRefresh: () -> Unit,
|
onRefresh: () -> Unit,
|
||||||
getMangaState: @Composable (Manga, CatalogueSource?) -> State<Manga>,
|
getMangaState: @Composable (Manga) -> State<Manga>,
|
||||||
) {
|
) {
|
||||||
when {
|
when {
|
||||||
state.isLoading -> LoadingScreen()
|
state.isLoading -> LoadingScreen()
|
||||||
@@ -119,7 +119,7 @@ fun FeedScreen(
|
|||||||
) {
|
) {
|
||||||
FeedItem(
|
FeedItem(
|
||||||
item = item,
|
item = item,
|
||||||
getMangaState = { getMangaState(it, item.source) },
|
getMangaState = { getMangaState(it) },
|
||||||
onClickManga = onClickManga,
|
onClickManga = onClickManga,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fun CrashScreen(
|
|||||||
acceptText = stringResource(MR.strings.pref_dump_crash_logs),
|
acceptText = stringResource(MR.strings.pref_dump_crash_logs),
|
||||||
onAcceptClick = {
|
onAcceptClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
CrashLogUtil(context).dumpLogs()
|
CrashLogUtil(context).dumpLogs(exception)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rejectText = stringResource(MR.strings.crash_screen_restart_application),
|
rejectText = stringResource(MR.strings.crash_screen_restart_application),
|
||||||
|
|||||||
@@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ fun LibraryToolbar(
|
|||||||
onClickRefresh: () -> Unit,
|
onClickRefresh: () -> Unit,
|
||||||
onClickGlobalUpdate: () -> Unit,
|
onClickGlobalUpdate: () -> Unit,
|
||||||
onClickOpenRandomManga: () -> Unit,
|
onClickOpenRandomManga: () -> Unit,
|
||||||
|
onClickSyncNow: () -> Unit,
|
||||||
// SY -->
|
// SY -->
|
||||||
onClickSyncExh: (() -> Unit)?,
|
onClickSyncExh: (() -> Unit)?,
|
||||||
// SY <--
|
// SY <--
|
||||||
@@ -60,6 +61,7 @@ fun LibraryToolbar(
|
|||||||
onClickRefresh = onClickRefresh,
|
onClickRefresh = onClickRefresh,
|
||||||
onClickGlobalUpdate = onClickGlobalUpdate,
|
onClickGlobalUpdate = onClickGlobalUpdate,
|
||||||
onClickOpenRandomManga = onClickOpenRandomManga,
|
onClickOpenRandomManga = onClickOpenRandomManga,
|
||||||
|
onClickSyncNow = onClickSyncNow,
|
||||||
// SY -->
|
// SY -->
|
||||||
onClickSyncExh = onClickSyncExh,
|
onClickSyncExh = onClickSyncExh,
|
||||||
// SY <--
|
// SY <--
|
||||||
@@ -77,6 +79,7 @@ private fun LibraryRegularToolbar(
|
|||||||
onClickRefresh: () -> Unit,
|
onClickRefresh: () -> Unit,
|
||||||
onClickGlobalUpdate: () -> Unit,
|
onClickGlobalUpdate: () -> Unit,
|
||||||
onClickOpenRandomManga: () -> Unit,
|
onClickOpenRandomManga: () -> Unit,
|
||||||
|
onClickSyncNow: () -> Unit,
|
||||||
// SY -->
|
// SY -->
|
||||||
onClickSyncExh: (() -> Unit)?,
|
onClickSyncExh: (() -> Unit)?,
|
||||||
// SY <--
|
// SY <--
|
||||||
@@ -125,7 +128,10 @@ private fun LibraryRegularToolbar(
|
|||||||
title = stringResource(MR.strings.action_open_random_manga),
|
title = stringResource(MR.strings.action_open_random_manga),
|
||||||
onClick = onClickOpenRandomManga,
|
onClick = onClickOpenRandomManga,
|
||||||
),
|
),
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(SYMR.strings.sync_library),
|
||||||
|
onClick = onClickSyncNow,
|
||||||
|
),
|
||||||
).builder().apply {
|
).builder().apply {
|
||||||
// SY -->
|
// SY -->
|
||||||
if (onClickSyncExh != null) {
|
if (onClickSyncExh != null) {
|
||||||
|
|||||||
@@ -1,16 +1,33 @@
|
|||||||
package eu.kanade.presentation.manga
|
package eu.kanade.presentation.manga
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Add
|
||||||
|
import androidx.compose.material.icons.outlined.Book
|
||||||
|
import androidx.compose.material.icons.outlined.SwapVert
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import eu.kanade.presentation.components.AdaptiveSheet
|
||||||
|
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||||
|
import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
|
||||||
|
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -18,42 +35,92 @@ fun DuplicateMangaDialog(
|
|||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
onOpenManga: () -> Unit,
|
onOpenManga: () -> Unit,
|
||||||
|
onMigrate: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
AlertDialog(
|
val minHeight = LocalPreferenceMinHeight.current
|
||||||
|
|
||||||
|
AdaptiveSheet(
|
||||||
|
modifier = modifier,
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
title = {
|
) {
|
||||||
Text(text = stringResource(MR.strings.are_you_sure))
|
Column(
|
||||||
},
|
modifier = Modifier
|
||||||
text = {
|
.padding(
|
||||||
Text(text = stringResource(MR.strings.confirm_add_duplicate_manga))
|
vertical = TabbedDialogPaddings.Vertical,
|
||||||
},
|
horizontal = TabbedDialogPaddings.Horizontal,
|
||||||
confirmButton = {
|
)
|
||||||
FlowRow(
|
.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(TitlePadding),
|
||||||
|
text = stringResource(MR.strings.are_you_sure),
|
||||||
|
style = MaterialTheme.typography.headlineMedium,
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(MR.strings.confirm_add_duplicate_manga),
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.height(PaddingSize))
|
||||||
|
|
||||||
|
TextPreferenceWidget(
|
||||||
|
title = stringResource(MR.strings.action_show_manga),
|
||||||
|
icon = Icons.Outlined.Book,
|
||||||
|
onPreferenceClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
onOpenManga()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
HorizontalDivider()
|
||||||
|
|
||||||
|
TextPreferenceWidget(
|
||||||
|
title = stringResource(MR.strings.action_migrate_duplicate),
|
||||||
|
icon = Icons.Outlined.SwapVert,
|
||||||
|
onPreferenceClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
onMigrate()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
HorizontalDivider()
|
||||||
|
|
||||||
|
TextPreferenceWidget(
|
||||||
|
title = stringResource(MR.strings.action_add_anyway),
|
||||||
|
icon = Icons.Outlined.Add,
|
||||||
|
onPreferenceClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
onConfirm()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.sizeIn(minHeight = minHeight)
|
||||||
|
.clickable { onDismissRequest.invoke() }
|
||||||
|
.padding(ButtonPadding)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
) {
|
) {
|
||||||
TextButton(
|
OutlinedButton(onClick = onDismissRequest, modifier = Modifier.fillMaxWidth()) {
|
||||||
onClick = {
|
Text(
|
||||||
onDismissRequest()
|
modifier = Modifier
|
||||||
onOpenManga()
|
.padding(vertical = 8.dp),
|
||||||
},
|
text = stringResource(MR.strings.action_cancel),
|
||||||
) {
|
color = MaterialTheme.colorScheme.primary,
|
||||||
Text(text = stringResource(MR.strings.action_show_manga))
|
style = MaterialTheme.typography.titleLarge,
|
||||||
}
|
fontSize = 16.sp,
|
||||||
|
)
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
|
||||||
Text(text = stringResource(MR.strings.action_cancel))
|
|
||||||
}
|
|
||||||
TextButton(
|
|
||||||
onClick = {
|
|
||||||
onDismissRequest()
|
|
||||||
onConfirm()
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text(text = stringResource(MR.strings.action_add))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val PaddingSize = 16.dp
|
||||||
|
|
||||||
|
private val ButtonPadding = PaddingValues(top = 16.dp, bottom = 16.dp)
|
||||||
|
private val TitlePadding = PaddingValues(bottom = 16.dp, top = 8.dp)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
+11
-9
@@ -9,13 +9,13 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.CheckCircle
|
import androidx.compose.material.icons.filled.CheckCircle
|
||||||
import androidx.compose.material.icons.outlined.ArrowDownward
|
import androidx.compose.material.icons.outlined.ArrowDownward
|
||||||
import androidx.compose.material.icons.outlined.ErrorOutline
|
import androidx.compose.material.icons.outlined.ErrorOutline
|
||||||
import androidx.compose.material.ripple
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ProgressIndicatorDefaults
|
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.ripple
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -24,6 +24,7 @@ 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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
import androidx.compose.ui.hapticfeedback.HapticFeedback
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
@@ -85,13 +86,12 @@ private fun NotDownloadedIndicator(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (ChapterDownloadAction) -> Unit,
|
onClick: (ChapterDownloadAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(IconButtonTokens.StateLayerSize)
|
.size(IconButtonTokens.StateLayerSize)
|
||||||
.commonClickable(
|
.commonClickable(
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
hapticFeedback = hapticFeedback,
|
hapticFeedback = LocalHapticFeedback.current,
|
||||||
onLongClick = { onClick(ChapterDownloadAction.START_NOW) },
|
onLongClick = { onClick(ChapterDownloadAction.START_NOW) },
|
||||||
onClick = { onClick(ChapterDownloadAction.START) },
|
onClick = { onClick(ChapterDownloadAction.START) },
|
||||||
)
|
)
|
||||||
@@ -115,14 +115,13 @@ private fun DownloadingIndicator(
|
|||||||
onClick: (ChapterDownloadAction) -> Unit,
|
onClick: (ChapterDownloadAction) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
|
||||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(IconButtonTokens.StateLayerSize)
|
.size(IconButtonTokens.StateLayerSize)
|
||||||
.commonClickable(
|
.commonClickable(
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
hapticFeedback = hapticFeedback,
|
hapticFeedback = LocalHapticFeedback.current,
|
||||||
onLongClick = { onClick(ChapterDownloadAction.CANCEL) },
|
onLongClick = { onClick(ChapterDownloadAction.CANCEL) },
|
||||||
onClick = { isMenuExpanded = true },
|
onClick = { isMenuExpanded = true },
|
||||||
),
|
),
|
||||||
@@ -139,6 +138,8 @@ private fun DownloadingIndicator(
|
|||||||
modifier = IndicatorModifier,
|
modifier = IndicatorModifier,
|
||||||
color = strokeColor,
|
color = strokeColor,
|
||||||
strokeWidth = IndicatorStrokeWidth,
|
strokeWidth = IndicatorStrokeWidth,
|
||||||
|
trackColor = Color.Transparent,
|
||||||
|
strokeCap = StrokeCap.Butt,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val animatedProgress by animateFloatAsState(
|
val animatedProgress by animateFloatAsState(
|
||||||
@@ -155,6 +156,9 @@ private fun DownloadingIndicator(
|
|||||||
modifier = IndicatorModifier,
|
modifier = IndicatorModifier,
|
||||||
color = strokeColor,
|
color = strokeColor,
|
||||||
strokeWidth = IndicatorSize / 2,
|
strokeWidth = IndicatorSize / 2,
|
||||||
|
trackColor = Color.Transparent,
|
||||||
|
strokeCap = StrokeCap.Butt,
|
||||||
|
gapSize = 0.dp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
|
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
|
||||||
@@ -188,14 +192,13 @@ private fun DownloadedIndicator(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (ChapterDownloadAction) -> Unit,
|
onClick: (ChapterDownloadAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
|
||||||
var isMenuExpanded by remember { mutableStateOf(false) }
|
var isMenuExpanded by remember { mutableStateOf(false) }
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(IconButtonTokens.StateLayerSize)
|
.size(IconButtonTokens.StateLayerSize)
|
||||||
.commonClickable(
|
.commonClickable(
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
hapticFeedback = hapticFeedback,
|
hapticFeedback = LocalHapticFeedback.current,
|
||||||
onLongClick = { isMenuExpanded = true },
|
onLongClick = { isMenuExpanded = true },
|
||||||
onClick = { isMenuExpanded = true },
|
onClick = { isMenuExpanded = true },
|
||||||
),
|
),
|
||||||
@@ -225,13 +228,12 @@ private fun ErrorIndicator(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (ChapterDownloadAction) -> Unit,
|
onClick: (ChapterDownloadAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(IconButtonTokens.StateLayerSize)
|
.size(IconButtonTokens.StateLayerSize)
|
||||||
.commonClickable(
|
.commonClickable(
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
hapticFeedback = hapticFeedback,
|
hapticFeedback = LocalHapticFeedback.current,
|
||||||
onLongClick = { onClick(ChapterDownloadAction.START) },
|
onLongClick = { onClick(ChapterDownloadAction.START) },
|
||||||
onClick = { onClick(ChapterDownloadAction.START) },
|
onClick = { onClick(ChapterDownloadAction.START) },
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import androidx.compose.animation.fadeIn
|
|||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -33,12 +32,12 @@ import androidx.compose.material.icons.outlined.Label
|
|||||||
import androidx.compose.material.icons.outlined.MoreVert
|
import androidx.compose.material.icons.outlined.MoreVert
|
||||||
import androidx.compose.material.icons.outlined.RemoveDone
|
import androidx.compose.material.icons.outlined.RemoveDone
|
||||||
import androidx.compose.material.icons.outlined.SwapCalls
|
import androidx.compose.material.icons.outlined.SwapCalls
|
||||||
import androidx.compose.material.ripple
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.ripple
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
@@ -90,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) }
|
||||||
@@ -199,7 +198,7 @@ private fun RowScope.Button(
|
|||||||
.size(48.dp)
|
.size(48.dp)
|
||||||
.weight(animatedWeight)
|
.weight(animatedWeight)
|
||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = null,
|
||||||
indication = ripple(bounded = false),
|
indication = ripple(bounded = false),
|
||||||
onLongClick = onLongClick,
|
onLongClick = onLongClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
@@ -239,6 +238,7 @@ fun LibraryBottomActionMenu(
|
|||||||
onClickCleanTitles: (() -> Unit)?,
|
onClickCleanTitles: (() -> Unit)?,
|
||||||
onClickMigrate: (() -> Unit)?,
|
onClickMigrate: (() -> Unit)?,
|
||||||
onClickAddToMangaDex: (() -> Unit)?,
|
onClickAddToMangaDex: (() -> Unit)?,
|
||||||
|
onClickResetInfo: (() -> Unit)?,
|
||||||
// SY <--
|
// SY <--
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -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 =
|
||||||
@@ -267,7 +267,7 @@ fun LibraryBottomActionMenu(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null
|
val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null || onClickResetInfo != null
|
||||||
val configuration = LocalConfiguration.current
|
val configuration = LocalConfiguration.current
|
||||||
val moveMarkPrev = remember { !configuration.isTabletUi() }
|
val moveMarkPrev = remember { !configuration.isTabletUi() }
|
||||||
var overFlowOpen by remember { mutableStateOf(false) }
|
var overFlowOpen by remember { mutableStateOf(false) }
|
||||||
@@ -364,6 +364,12 @@ fun LibraryBottomActionMenu(
|
|||||||
onClick = onClickAddToMangaDex,
|
onClick = onClickAddToMangaDex,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (onClickResetInfo != null) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(text = stringResource(SYMR.strings.reset_info)) },
|
||||||
|
onClick = onClickResetInfo,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Button(
|
Button(
|
||||||
|
|||||||
@@ -36,13 +36,12 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
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.sp
|
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
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,34 +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 {
|
Row {
|
||||||
ProvideTextStyle(
|
val subtitleStyle = MaterialTheme.typography.bodySmall
|
||||||
value = MaterialTheme.typography.bodyMedium.copy(
|
.merge(
|
||||||
fontSize = 12.sp,
|
color = LocalContentColor.current
|
||||||
color = LocalContentColor.current.copy(alpha = textSubtitleAlpha),
|
.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) {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ private fun NewUpdateScreenPreview() {
|
|||||||
changelogInfo = """
|
changelogInfo = """
|
||||||
## Yay
|
## Yay
|
||||||
Foobar
|
Foobar
|
||||||
|
|
||||||
### More info
|
### More info
|
||||||
- Hello
|
- Hello
|
||||||
- World
|
- World
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
+78
-67
@@ -3,11 +3,12 @@ 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
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -60,7 +61,6 @@ import eu.kanade.tachiyomi.util.CrashLogUtil
|
|||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import eu.kanade.tachiyomi.util.system.isDevFlavor
|
import eu.kanade.tachiyomi.util.system.isDevFlavor
|
||||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
|
||||||
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
|
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
|
||||||
import eu.kanade.tachiyomi.util.system.powerManager
|
import eu.kanade.tachiyomi.util.system.powerManager
|
||||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
||||||
@@ -113,71 +113,54 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||||||
val basePreferences = remember { Injekt.get<BasePreferences>() }
|
val basePreferences = remember { Injekt.get<BasePreferences>() }
|
||||||
val networkPreferences = remember { Injekt.get<NetworkPreferences>() }
|
val networkPreferences = remember { Injekt.get<NetworkPreferences>() }
|
||||||
|
|
||||||
return buildList {
|
return listOf(
|
||||||
addAll(
|
Preference.PreferenceItem.TextPreference(
|
||||||
listOf(
|
title = stringResource(MR.strings.pref_dump_crash_logs),
|
||||||
/* SY --> Preference.PreferenceItem.SwitchPreference(
|
subtitle = stringResource(MR.strings.pref_dump_crash_logs_summary),
|
||||||
pref = basePreferences.acraEnabled(),
|
onClick = {
|
||||||
title = stringResource(MR.strings.pref_enable_acra),
|
scope.launch {
|
||||||
subtitle = stringResource(MR.strings.pref_acra_summary),
|
CrashLogUtil(context).dumpLogs()
|
||||||
enabled = isPreviewBuildType || isReleaseBuildType,
|
}
|
||||||
), SY <-- */
|
},
|
||||||
Preference.PreferenceItem.TextPreference(
|
),
|
||||||
title = stringResource(MR.strings.pref_dump_crash_logs),
|
/* SY --> Preference.PreferenceItem.SwitchPreference(
|
||||||
subtitle = stringResource(MR.strings.pref_dump_crash_logs_summary),
|
pref = networkPreferences.verboseLogging(),
|
||||||
onClick = {
|
title = stringResource(MR.strings.pref_verbose_logging),
|
||||||
scope.launch {
|
subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
|
||||||
CrashLogUtil(context).dumpLogs()
|
onValueChanged = {
|
||||||
}
|
context.toast(MR.strings.requires_app_restart)
|
||||||
},
|
true
|
||||||
),
|
},
|
||||||
/* SY --> Preference.PreferenceItem.SwitchPreference(
|
), SY <-- */
|
||||||
pref = networkPreferences.verboseLogging(),
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(MR.strings.pref_verbose_logging),
|
title = stringResource(MR.strings.pref_debug_info),
|
||||||
subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
|
onClick = { navigator.push(DebugInfoScreen()) },
|
||||||
onValueChanged = {
|
),
|
||||||
context.toast(MR.strings.requires_app_restart)
|
Preference.PreferenceItem.TextPreference(
|
||||||
true
|
title = stringResource(MR.strings.pref_onboarding_guide),
|
||||||
},
|
onClick = { navigator.push(OnboardingScreen()) },
|
||||||
), SY <-- */
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(MR.strings.pref_debug_info),
|
title = stringResource(MR.strings.pref_manage_notifications),
|
||||||
onClick = { navigator.push(DebugInfoScreen()) },
|
onClick = {
|
||||||
),
|
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
||||||
Preference.PreferenceItem.TextPreference(
|
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||||
title = stringResource(MR.strings.pref_onboarding_guide),
|
}
|
||||||
onClick = { navigator.push(OnboardingScreen()) },
|
context.startActivity(intent)
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
)
|
getBackgroundActivityGroup(),
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
getDataGroup(),
|
||||||
add(
|
getNetworkGroup(networkPreferences = networkPreferences),
|
||||||
Preference.PreferenceItem.TextPreference(
|
getLibraryGroup(),
|
||||||
title = stringResource(MR.strings.pref_manage_notifications),
|
getReaderGroup(basePreferences = basePreferences),
|
||||||
onClick = {
|
getExtensionsGroup(basePreferences = basePreferences),
|
||||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
// SY -->
|
||||||
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
// getDownloaderGroup(),
|
||||||
}
|
getDataSaverGroup(),
|
||||||
context.startActivity(intent)
|
getDeveloperToolsGroup(),
|
||||||
},
|
// SY <--
|
||||||
),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
addAll(
|
|
||||||
listOf(
|
|
||||||
getBackgroundActivityGroup(),
|
|
||||||
getDataGroup(),
|
|
||||||
getNetworkGroup(networkPreferences = networkPreferences),
|
|
||||||
getLibraryGroup(),
|
|
||||||
getExtensionsGroup(basePreferences = basePreferences),
|
|
||||||
// SY -->
|
|
||||||
// getDownloaderGroup(),
|
|
||||||
getDataSaverGroup(),
|
|
||||||
getDeveloperToolsGroup(),
|
|
||||||
// SY <--
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -368,6 +351,34 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getReaderGroup(
|
||||||
|
basePreferences: BasePreferences,
|
||||||
|
): Preference.PreferenceGroup {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val chooseColorProfile = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.OpenDocument(),
|
||||||
|
) { uri ->
|
||||||
|
uri?.let {
|
||||||
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
context.contentResolver.takePersistableUriPermission(uri, flags)
|
||||||
|
basePreferences.displayProfile().set(uri.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(MR.strings.pref_category_reader),
|
||||||
|
preferenceItems = persistentListOf(
|
||||||
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(MR.strings.pref_display_profile),
|
||||||
|
subtitle = basePreferences.displayProfile().get(),
|
||||||
|
onClick = {
|
||||||
|
chooseColorProfile.launch(arrayOf("*/*"))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getExtensionsGroup(
|
private fun getExtensionsGroup(
|
||||||
basePreferences: BasePreferences,
|
basePreferences: BasePreferences,
|
||||||
|
|||||||
+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 = {
|
||||||
|
|||||||
+7
-3
@@ -2,6 +2,7 @@ package eu.kanade.presentation.more.settings.screen
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
@@ -17,6 +18,7 @@ import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
|
|||||||
import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryScreen
|
import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryScreen
|
||||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
|
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepoCount
|
||||||
import tachiyomi.core.common.i18n.stringResource
|
import tachiyomi.core.common.i18n.stringResource
|
||||||
import tachiyomi.domain.UnsortedPreferences
|
import tachiyomi.domain.UnsortedPreferences
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
@@ -39,7 +41,9 @@ object SettingsBrowseScreen : SearchableSettings {
|
|||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
|
val sourcePreferences = remember { Injekt.get<SourcePreferences>() }
|
||||||
val reposCount by sourcePreferences.extensionRepos().collectAsState()
|
val getExtensionRepoCount = remember { Injekt.get<GetExtensionRepoCount>() }
|
||||||
|
|
||||||
|
val reposCount by getExtensionRepoCount.subscribe().collectAsState(0)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -90,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(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -104,7 +108,7 @@ object SettingsBrowseScreen : SearchableSettings {
|
|||||||
),
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.TextPreference(
|
||||||
title = stringResource(MR.strings.label_extension_repos),
|
title = stringResource(MR.strings.label_extension_repos),
|
||||||
subtitle = pluralStringResource(MR.plurals.num_repos, reposCount.size, reposCount.size),
|
subtitle = pluralStringResource(MR.plurals.num_repos, reposCount, reposCount),
|
||||||
onClick = {
|
onClick = {
|
||||||
navigator.push(ExtensionReposScreen())
|
navigator.push(ExtensionReposScreen())
|
||||||
},
|
},
|
||||||
|
|||||||
+263
-2
@@ -15,16 +15,19 @@ import androidx.compose.foundation.layout.height
|
|||||||
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.automirrored.outlined.HelpOutline
|
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
|
import androidx.compose.material3.MultiChoiceSegmentedButtonRow
|
||||||
import androidx.compose.material3.SegmentedButton
|
import androidx.compose.material3.SegmentedButton
|
||||||
import androidx.compose.material3.SegmentedButtonDefaults
|
import androidx.compose.material3.SegmentedButtonDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -35,10 +38,13 @@ import androidx.core.net.toUri
|
|||||||
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 com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
|
import eu.kanade.domain.sync.SyncPreferences
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
||||||
import eu.kanade.presentation.more.settings.screen.data.RestoreBackupScreen
|
import eu.kanade.presentation.more.settings.screen.data.RestoreBackupScreen
|
||||||
import eu.kanade.presentation.more.settings.screen.data.StorageInfo
|
import eu.kanade.presentation.more.settings.screen.data.StorageInfo
|
||||||
|
import eu.kanade.presentation.more.settings.screen.data.SyncSettingsSelector
|
||||||
|
import eu.kanade.presentation.more.settings.screen.data.SyncTriggerOptionsScreen
|
||||||
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
||||||
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
||||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||||
@@ -46,10 +52,15 @@ import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
|||||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
|
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
|
||||||
|
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
||||||
|
import eu.kanade.tachiyomi.data.sync.SyncManager
|
||||||
|
import eu.kanade.tachiyomi.data.sync.service.GoogleDriveService
|
||||||
|
import eu.kanade.tachiyomi.data.sync.service.GoogleDriveSyncService
|
||||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.common.i18n.stringResource
|
import tachiyomi.core.common.i18n.stringResource
|
||||||
import tachiyomi.core.common.storage.displayablePath
|
import tachiyomi.core.common.storage.displayablePath
|
||||||
@@ -91,13 +102,16 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||||
val storagePreferences = Injekt.get<StoragePreferences>()
|
val storagePreferences = Injekt.get<StoragePreferences>()
|
||||||
|
|
||||||
|
val syncPreferences = remember { Injekt.get<SyncPreferences>() }
|
||||||
|
val syncService by syncPreferences.syncService().collectAsState()
|
||||||
|
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
getStorageLocationPref(storagePreferences = storagePreferences),
|
getStorageLocationPref(storagePreferences = storagePreferences),
|
||||||
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
|
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),
|
||||||
|
|
||||||
getBackupAndRestoreGroup(backupPreferences = backupPreferences),
|
getBackupAndRestoreGroup(backupPreferences = backupPreferences),
|
||||||
getDataGroup(),
|
getDataGroup(),
|
||||||
)
|
) + getSyncPreferences(syncPreferences = syncPreferences, syncService = syncService)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -113,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())
|
||||||
@@ -330,4 +354,241 @@ object SettingsDataScreen : SearchableSettings {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSyncPreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> {
|
||||||
|
return listOf(
|
||||||
|
Preference.PreferenceGroup(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_service_category),
|
||||||
|
preferenceItems = persistentListOf(
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = syncPreferences.syncService(),
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_service),
|
||||||
|
entries = persistentMapOf(
|
||||||
|
SyncManager.SyncService.NONE.value to stringResource(MR.strings.off),
|
||||||
|
SyncManager.SyncService.SYNCYOMI.value to stringResource(SYMR.strings.syncyomi),
|
||||||
|
SyncManager.SyncService.GOOGLE_DRIVE.value to stringResource(SYMR.strings.google_drive),
|
||||||
|
),
|
||||||
|
onValueChanged = { true },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) + getSyncServicePreferences(syncPreferences, syncService)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSyncServicePreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> {
|
||||||
|
val syncServiceType = SyncManager.SyncService.fromInt(syncService)
|
||||||
|
|
||||||
|
val basePreferences = getBasePreferences(syncServiceType, syncPreferences)
|
||||||
|
|
||||||
|
return if (syncServiceType != SyncManager.SyncService.NONE) {
|
||||||
|
basePreferences + getAdditionalPreferences(syncPreferences)
|
||||||
|
} else {
|
||||||
|
basePreferences
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getBasePreferences(
|
||||||
|
syncServiceType: SyncManager.SyncService,
|
||||||
|
syncPreferences: SyncPreferences,
|
||||||
|
): List<Preference> {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val preferences = when (syncServiceType) {
|
||||||
|
SyncManager.SyncService.NONE -> emptyList()
|
||||||
|
SyncManager.SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences)
|
||||||
|
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
|
||||||
|
private fun getAdditionalPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
||||||
|
return listOf(getSyncNowPref(), getAutomaticSyncGroup(syncPreferences))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getGoogleDrivePreferences(): List<Preference> {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val googleDriveSync = Injekt.get<GoogleDriveService>()
|
||||||
|
return listOf(
|
||||||
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_google_drive_sign_in),
|
||||||
|
onClick = {
|
||||||
|
val intent = googleDriveSync.getSignInIntent()
|
||||||
|
context.startActivity(intent)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
getGoogleDrivePurge(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getGoogleDrivePurge(): Preference.PreferenceItem.TextPreference {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val context = LocalContext.current
|
||||||
|
val googleDriveSync = remember { GoogleDriveSyncService(context) }
|
||||||
|
var showPurgeDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showPurgeDialog) {
|
||||||
|
PurgeConfirmationDialog(
|
||||||
|
onConfirm = {
|
||||||
|
showPurgeDialog = false
|
||||||
|
scope.launch {
|
||||||
|
val result = googleDriveSync.deleteSyncDataFromGoogleDrive()
|
||||||
|
when (result) {
|
||||||
|
GoogleDriveSyncService.DeleteSyncDataStatus.NOT_INITIALIZED -> context.toast(
|
||||||
|
SYMR.strings.google_drive_not_signed_in,
|
||||||
|
duration = 5000,
|
||||||
|
)
|
||||||
|
GoogleDriveSyncService.DeleteSyncDataStatus.NO_FILES -> context.toast(
|
||||||
|
SYMR.strings.google_drive_sync_data_not_found,
|
||||||
|
duration = 5000,
|
||||||
|
)
|
||||||
|
GoogleDriveSyncService.DeleteSyncDataStatus.SUCCESS -> context.toast(
|
||||||
|
SYMR.strings.google_drive_sync_data_purged,
|
||||||
|
duration = 5000,
|
||||||
|
)
|
||||||
|
GoogleDriveSyncService.DeleteSyncDataStatus.ERROR -> context.toast(
|
||||||
|
SYMR.strings.google_drive_sync_data_purge_error,
|
||||||
|
duration = 10000,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDismissRequest = { showPurgeDialog = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_google_drive_purge_sync_data),
|
||||||
|
onClick = { showPurgeDialog = true },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun PurgeConfirmationDialog(
|
||||||
|
onConfirm: () -> Unit,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
title = { Text(text = stringResource(SYMR.strings.pref_purge_confirmation_title)) },
|
||||||
|
text = { Text(text = stringResource(SYMR.strings.pref_purge_confirmation_message)) },
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onConfirm) {
|
||||||
|
Text(text = stringResource(MR.strings.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSelfHostPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
return listOf(
|
||||||
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_host),
|
||||||
|
subtitle = stringResource(SYMR.strings.pref_sync_host_summ),
|
||||||
|
pref = syncPreferences.clientHost(),
|
||||||
|
onValueChanged = { newValue ->
|
||||||
|
scope.launch {
|
||||||
|
// Trim spaces at the beginning and end, then remove trailing slash if present
|
||||||
|
val trimmedValue = newValue.trim()
|
||||||
|
val modifiedValue = trimmedValue.trimEnd { it == '/' }
|
||||||
|
syncPreferences.clientHost().set(modifiedValue)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_api_key),
|
||||||
|
subtitle = stringResource(SYMR.strings.pref_sync_api_key_summ),
|
||||||
|
pref = syncPreferences.clientAPIKey(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSyncNowPref(): Preference.PreferenceGroup {
|
||||||
|
val context = LocalContext.current
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_now_group_title),
|
||||||
|
preferenceItems = persistentListOf(
|
||||||
|
getSyncOptionsPref(),
|
||||||
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_now),
|
||||||
|
subtitle = stringResource(SYMR.strings.pref_sync_now_subtitle),
|
||||||
|
onClick = {
|
||||||
|
if (!SyncDataJob.isRunning(context)) {
|
||||||
|
SyncDataJob.startNow(context)
|
||||||
|
} else {
|
||||||
|
context.toast(SYMR.strings.sync_in_progress)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSyncOptionsPref(): Preference.PreferenceItem.TextPreference {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
return Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_options),
|
||||||
|
subtitle = stringResource(SYMR.strings.pref_sync_options_summ),
|
||||||
|
onClick = { navigator.push(SyncTriggerOptionsScreen()) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getAutomaticSyncGroup(syncPreferences: SyncPreferences): Preference.PreferenceGroup {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val syncIntervalPref = syncPreferences.syncInterval()
|
||||||
|
val lastSync by syncPreferences.lastSyncTimestamp().collectAsState()
|
||||||
|
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_automatic_category),
|
||||||
|
preferenceItems = persistentListOf(
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = syncIntervalPref,
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_interval),
|
||||||
|
entries = persistentMapOf(
|
||||||
|
0 to stringResource(MR.strings.off),
|
||||||
|
30 to stringResource(SYMR.strings.update_30min),
|
||||||
|
60 to stringResource(SYMR.strings.update_1hour),
|
||||||
|
180 to stringResource(SYMR.strings.update_3hour),
|
||||||
|
360 to stringResource(MR.strings.update_6hour),
|
||||||
|
720 to stringResource(MR.strings.update_12hour),
|
||||||
|
1440 to stringResource(MR.strings.update_24hour),
|
||||||
|
2880 to stringResource(MR.strings.update_48hour),
|
||||||
|
10080 to stringResource(MR.strings.update_weekly),
|
||||||
|
),
|
||||||
|
onValueChanged = {
|
||||||
|
SyncDataJob.setupTask(context, it)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.InfoPreference(
|
||||||
|
stringResource(SYMR.strings.last_synchronization, relativeTimeSpanString(lastSync)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+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(
|
||||||
|
|||||||
+4
-6
@@ -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(
|
||||||
@@ -235,11 +231,13 @@ object SettingsLibraryScreen : SearchableSettings {
|
|||||||
pref = libraryPreferences.newShowUpdatesCount(),
|
pref = libraryPreferences.newShowUpdatesCount(),
|
||||||
title = stringResource(MR.strings.pref_library_update_show_tab_badge),
|
title = stringResource(MR.strings.pref_library_update_show_tab_badge),
|
||||||
),
|
),
|
||||||
|
// SY -->
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = libraryPreferences.libraryReadDuplicateChapters(),
|
pref = libraryPreferences.libraryReadDuplicateChapters(),
|
||||||
title = stringResource(MR.strings.pref_library_mark_duplicate_chapters),
|
title = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters),
|
||||||
subtitle = stringResource(MR.strings.pref_library_mark_duplicate_chapters_summary),
|
subtitle = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters_summary),
|
||||||
),
|
),
|
||||||
|
// SY <--
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+74
-17
@@ -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
|
||||||
@@ -35,6 +36,7 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
// SY -->
|
// SY -->
|
||||||
val forceHorizontalSeekbar by readerPref.forceHorizontalSeekbar().collectAsState()
|
val forceHorizontalSeekbar by readerPref.forceHorizontalSeekbar().collectAsState()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
Preference.PreferenceItem.ListPreference(
|
Preference.PreferenceItem.ListPreference(
|
||||||
pref = readerPref.defaultReadingMode(),
|
pref = readerPref.defaultReadingMode(),
|
||||||
@@ -81,24 +83,14 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
enabled = !forceHorizontalSeekbar,
|
enabled = !forceHorizontalSeekbar,
|
||||||
),
|
),
|
||||||
// SY <--
|
// SY <--
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
|
||||||
pref = readerPref.trueColor(),
|
|
||||||
title = stringResource(MR.strings.pref_true_color),
|
|
||||||
subtitle = stringResource(MR.strings.pref_true_color_summary),
|
|
||||||
enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O,
|
|
||||||
),
|
|
||||||
/* SY -->
|
/* SY -->
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = readerPref.pageTransitions(),
|
pref = readerPref.pageTransitions(),
|
||||||
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),
|
||||||
@@ -161,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(
|
||||||
@@ -178,11 +229,13 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
pref = readerPreferences.skipDupe(),
|
pref = readerPreferences.skipDupe(),
|
||||||
title = stringResource(MR.strings.pref_skip_dupe_chapters),
|
title = stringResource(MR.strings.pref_skip_dupe_chapters),
|
||||||
),
|
),
|
||||||
|
// SY -->
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = readerPreferences.markReadDupe(),
|
pref = readerPreferences.markReadDupe(),
|
||||||
title = stringResource(MR.strings.pref_mark_read_dupe_chapters),
|
title = stringResource(SYMR.strings.pref_mark_read_dupe_chapters),
|
||||||
subtitle = stringResource(MR.strings.pref_mark_read_dupe_chapters_summary),
|
subtitle = stringResource(SYMR.strings.pref_mark_read_dupe_chapters_summary),
|
||||||
),
|
),
|
||||||
|
// SY <--
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = readerPreferences.alwaysShowChapterTransition(),
|
pref = readerPreferences.alwaysShowChapterTransition(),
|
||||||
title = stringResource(MR.strings.pref_always_show_chapter_transition),
|
title = stringResource(MR.strings.pref_always_show_chapter_transition),
|
||||||
@@ -570,10 +623,14 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
.toMap()
|
.toMap()
|
||||||
.toImmutableMap(),
|
.toImmutableMap(),
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.ListPreference(
|
||||||
pref = readerPreferences.cacheArchiveMangaOnDisk(),
|
pref = readerPreferences.archiveReaderMode(),
|
||||||
title = stringResource(SYMR.strings.cache_archived_manga_to_disk),
|
title = stringResource(SYMR.strings.pref_archive_reader_mode),
|
||||||
subtitle = stringResource(SYMR.strings.cache_archived_manga_to_disk_subtitle),
|
subtitle = stringResource(SYMR.strings.pref_archive_reader_mode_summary),
|
||||||
|
entries = ReaderPreferences.archiveModeTypes
|
||||||
|
.mapIndexed { index, it -> index to stringResource(it) }
|
||||||
|
.toMap()
|
||||||
|
.toImmutableMap(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -56,10 +56,9 @@ import tachiyomi.presentation.core.icons.Reddit
|
|||||||
import tachiyomi.presentation.core.icons.X
|
import tachiyomi.presentation.core.icons.X
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
object AboutScreen : Screen() {
|
object AboutScreen : Screen() {
|
||||||
|
|
||||||
@@ -293,11 +292,15 @@ object AboutScreen : Screen() {
|
|||||||
|
|
||||||
internal fun getFormattedBuildTime(): String {
|
internal fun getFormattedBuildTime(): String {
|
||||||
return try {
|
return try {
|
||||||
val df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'", Locale.US)
|
LocalDateTime.ofInstant(
|
||||||
.withZone(ZoneId.of("UTC"))
|
Instant.parse(BuildConfig.BUILD_TIME),
|
||||||
val buildTime = LocalDateTime.from(df.parse(BuildConfig.BUILD_TIME))
|
ZoneId.systemDefault(),
|
||||||
|
)
|
||||||
buildTime!!.toDateTimestampString(UiPreferences.dateFormat(Injekt.get<UiPreferences>().dateFormat().get()))
|
.toDateTimestampString(
|
||||||
|
UiPreferences.dateFormat(
|
||||||
|
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||||
|
),
|
||||||
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
BuildConfig.BUILD_TIME
|
BuildConfig.BUILD_TIME
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -32,12 +32,13 @@ class OpenSourceLicensesScreen : Screen() {
|
|||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
onLibraryClick = {
|
onLibraryClick = {
|
||||||
val libraryLicenseScreen = OpenSourceLibraryLicenseScreen(
|
navigator.push(
|
||||||
name = it.library.name,
|
OpenSourceLibraryLicenseScreen(
|
||||||
website = it.library.website,
|
name = it.name,
|
||||||
license = it.library.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
website = it.website,
|
||||||
|
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
navigator.push(libraryLicenseScreen)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-3
@@ -8,11 +8,15 @@ 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.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
|
||||||
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionReposScreen
|
import eu.kanade.presentation.more.settings.screen.browse.components.ExtensionReposScreen
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
|
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||||
|
|
||||||
@@ -29,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) {
|
||||||
@@ -42,17 +46,19 @@ class ExtensionReposScreen(
|
|||||||
ExtensionReposScreen(
|
ExtensionReposScreen(
|
||||||
state = successState,
|
state = successState,
|
||||||
onClickCreate = { screenModel.showDialog(RepoDialog.Create) },
|
onClickCreate = { screenModel.showDialog(RepoDialog.Create) },
|
||||||
|
onOpenWebsite = { context.openInBrowser(it.website) },
|
||||||
onClickDelete = { screenModel.showDialog(RepoDialog.Delete(it)) },
|
onClickDelete = { screenModel.showDialog(RepoDialog.Delete(it)) },
|
||||||
|
onClickRefresh = { screenModel.refreshRepos() },
|
||||||
navigateUp = navigator::pop,
|
navigateUp = navigator::pop,
|
||||||
)
|
)
|
||||||
|
|
||||||
when (val dialog = successState.dialog) {
|
when (val dialog = successState.dialog) {
|
||||||
null -> {}
|
null -> {}
|
||||||
RepoDialog.Create -> {
|
is RepoDialog.Create -> {
|
||||||
ExtensionRepoCreateDialog(
|
ExtensionRepoCreateDialog(
|
||||||
onDismissRequest = screenModel::dismissDialog,
|
onDismissRequest = screenModel::dismissDialog,
|
||||||
onCreate = { screenModel.createRepo(it) },
|
onCreate = { screenModel.createRepo(it) },
|
||||||
repos = successState.repos,
|
repoUrls = successState.repos.map { it.baseUrl }.toImmutableSet(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is RepoDialog.Delete -> {
|
is RepoDialog.Delete -> {
|
||||||
@@ -62,6 +68,21 @@ class ExtensionReposScreen(
|
|||||||
repo = dialog.repo,
|
repo = dialog.repo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is RepoDialog.Conflict -> {
|
||||||
|
ExtensionRepoConflictDialog(
|
||||||
|
onDismissRequest = screenModel::dismissDialog,
|
||||||
|
onMigrate = { screenModel.replaceRepo(dialog.newRepo) },
|
||||||
|
oldRepo = dialog.oldRepo,
|
||||||
|
newRepo = dialog.newRepo,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is RepoDialog.Confirm -> {
|
||||||
|
ExtensionRepoConfirmDialog(
|
||||||
|
onDismissRequest = screenModel::dismissDialog,
|
||||||
|
onCreate = { screenModel.createRepo(dialog.url) },
|
||||||
|
repo = dialog.url,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
|||||||
+49
-14
@@ -4,24 +4,29 @@ import androidx.compose.runtime.Immutable
|
|||||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.screenModelScope
|
import cafe.adriel.voyager.core.model.screenModelScope
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.domain.extension.interactor.CreateExtensionRepo
|
|
||||||
import eu.kanade.domain.extension.interactor.DeleteExtensionRepo
|
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionRepos
|
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
import mihon.domain.extensionrepo.interactor.CreateExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.DeleteExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.ReplaceExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.interactor.UpdateExtensionRepo
|
||||||
|
import mihon.domain.extensionrepo.model.ExtensionRepo
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
import tachiyomi.i18n.MR
|
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
|
||||||
|
|
||||||
class ExtensionReposScreenModel(
|
class ExtensionReposScreenModel(
|
||||||
private val getExtensionRepos: GetExtensionRepos = Injekt.get(),
|
private val getExtensionRepo: GetExtensionRepo = Injekt.get(),
|
||||||
private val createExtensionRepo: CreateExtensionRepo = Injekt.get(),
|
private val createExtensionRepo: CreateExtensionRepo = Injekt.get(),
|
||||||
private val deleteExtensionRepo: DeleteExtensionRepo = Injekt.get(),
|
private val deleteExtensionRepo: DeleteExtensionRepo = Injekt.get(),
|
||||||
|
private val replaceExtensionRepo: ReplaceExtensionRepo = Injekt.get(),
|
||||||
|
private val updateExtensionRepo: UpdateExtensionRepo = Injekt.get(),
|
||||||
) : StateScreenModel<RepoScreenState>(RepoScreenState.Loading) {
|
) : StateScreenModel<RepoScreenState>(RepoScreenState.Loading) {
|
||||||
|
|
||||||
private val _events: Channel<RepoEvent> = Channel(Int.MAX_VALUE)
|
private val _events: Channel<RepoEvent> = Channel(Int.MAX_VALUE)
|
||||||
@@ -29,7 +34,7 @@ class ExtensionReposScreenModel(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
getExtensionRepos.subscribe()
|
getExtensionRepo.subscribeAll()
|
||||||
.collectLatest { repos ->
|
.collectLatest { repos ->
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
RepoScreenState.Success(
|
RepoScreenState.Success(
|
||||||
@@ -43,25 +48,51 @@ class ExtensionReposScreenModel(
|
|||||||
/**
|
/**
|
||||||
* Creates and adds a new repo to the database.
|
* Creates and adds a new repo to the database.
|
||||||
*
|
*
|
||||||
* @param name The name of the repo to create.
|
* @param baseUrl The baseUrl of the repo to create.
|
||||||
*/
|
*/
|
||||||
fun createRepo(name: String) {
|
fun createRepo(baseUrl: String) {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
when (createExtensionRepo.await(name)) {
|
when (val result = createExtensionRepo.await(baseUrl)) {
|
||||||
is CreateExtensionRepo.Result.InvalidUrl -> _events.send(RepoEvent.InvalidUrl)
|
CreateExtensionRepo.Result.InvalidUrl -> _events.send(RepoEvent.InvalidUrl)
|
||||||
|
CreateExtensionRepo.Result.RepoAlreadyExists -> _events.send(RepoEvent.RepoAlreadyExists)
|
||||||
|
is CreateExtensionRepo.Result.DuplicateFingerprint -> {
|
||||||
|
showDialog(RepoDialog.Conflict(result.oldRepo, result.newRepo))
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the given repo from the database.
|
* Inserts a repo to the database, replace a matching repo with the same signing key fingerprint if found.
|
||||||
*
|
*
|
||||||
* @param repo The repo to delete.
|
* @param newRepo The repo to insert
|
||||||
*/
|
*/
|
||||||
fun deleteRepo(repo: String) {
|
fun replaceRepo(newRepo: ExtensionRepo) {
|
||||||
screenModelScope.launchIO {
|
screenModelScope.launchIO {
|
||||||
deleteExtensionRepo.await(repo)
|
replaceExtensionRepo.await(newRepo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes information for each repository.
|
||||||
|
*/
|
||||||
|
fun refreshRepos() {
|
||||||
|
val status = state.value
|
||||||
|
|
||||||
|
if (status is RepoScreenState.Success) {
|
||||||
|
screenModelScope.launchIO {
|
||||||
|
updateExtensionRepo.awaitAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the given repo from the database
|
||||||
|
*/
|
||||||
|
fun deleteRepo(baseUrl: String) {
|
||||||
|
screenModelScope.launchIO {
|
||||||
|
deleteExtensionRepo.await(baseUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,11 +118,14 @@ class ExtensionReposScreenModel(
|
|||||||
sealed class RepoEvent {
|
sealed class RepoEvent {
|
||||||
sealed class LocalizedMessage(val stringRes: StringResource) : RepoEvent()
|
sealed class LocalizedMessage(val stringRes: StringResource) : RepoEvent()
|
||||||
data object InvalidUrl : LocalizedMessage(MR.strings.invalid_repo_name)
|
data object InvalidUrl : LocalizedMessage(MR.strings.invalid_repo_name)
|
||||||
|
data object RepoAlreadyExists : LocalizedMessage(MR.strings.error_repo_exists)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class RepoDialog {
|
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 Confirm(val url: String) : RepoDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class RepoScreenState {
|
sealed class RepoScreenState {
|
||||||
@@ -101,7 +135,8 @@ sealed class RepoScreenState {
|
|||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class Success(
|
data class Success(
|
||||||
val repos: ImmutableSet<String>,
|
val repos: ImmutableSet<ExtensionRepo>,
|
||||||
|
val oldRepos: ImmutableSet<String>? = null,
|
||||||
val dialog: RepoDialog? = null,
|
val dialog: RepoDialog? = null,
|
||||||
) : RepoScreenState() {
|
) : RepoScreenState() {
|
||||||
|
|
||||||
|
|||||||
+21
-5
@@ -9,6 +9,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.Label
|
import androidx.compose.material.icons.automirrored.outlined.Label
|
||||||
|
import androidx.compose.material.icons.automirrored.outlined.OpenInNew
|
||||||
import androidx.compose.material.icons.outlined.ContentCopy
|
import androidx.compose.material.icons.outlined.ContentCopy
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material3.ElevatedCard
|
import androidx.compose.material3.ElevatedCard
|
||||||
@@ -22,15 +23,17 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
|
import mihon.domain.extensionrepo.model.ExtensionRepo
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
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
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ExtensionReposContent(
|
fun ExtensionReposContent(
|
||||||
repos: ImmutableSet<String>,
|
repos: ImmutableSet<ExtensionRepo>,
|
||||||
lazyListState: LazyListState,
|
lazyListState: LazyListState,
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
|
onOpenWebsite: (ExtensionRepo) -> Unit,
|
||||||
onClickDelete: (String) -> Unit,
|
onClickDelete: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -45,7 +48,8 @@ fun ExtensionReposContent(
|
|||||||
ExtensionRepoListItem(
|
ExtensionRepoListItem(
|
||||||
modifier = Modifier.animateItemPlacement(),
|
modifier = Modifier.animateItemPlacement(),
|
||||||
repo = it,
|
repo = it,
|
||||||
onDelete = { onClickDelete(it) },
|
onOpenWebsite = { onOpenWebsite(it) },
|
||||||
|
onDelete = { onClickDelete(it.baseUrl) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +58,8 @@ fun ExtensionReposContent(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ExtensionRepoListItem(
|
private fun ExtensionRepoListItem(
|
||||||
repo: String,
|
repo: ExtensionRepo,
|
||||||
|
onOpenWebsite: () -> Unit,
|
||||||
onDelete: () -> Unit,
|
onDelete: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -74,16 +79,27 @@ private fun ExtensionRepoListItem(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = null)
|
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = null)
|
||||||
Text(text = repo, modifier = Modifier.padding(start = MaterialTheme.padding.medium))
|
Text(
|
||||||
|
text = repo.name,
|
||||||
|
modifier = Modifier.padding(start = MaterialTheme.padding.medium),
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.End,
|
horizontalArrangement = Arrangement.End,
|
||||||
) {
|
) {
|
||||||
|
IconButton(onClick = onOpenWebsite) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Outlined.OpenInNew,
|
||||||
|
contentDescription = stringResource(MR.strings.action_open_in_browser),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
val url = "$repo/index.min.json"
|
val url = "${repo.baseUrl}/index.min.json"
|
||||||
context.copyToClipboard(url, url)
|
context.copyToClipboard(url, url)
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
|||||||
+71
-2
@@ -1,6 +1,7 @@
|
|||||||
package eu.kanade.presentation.more.settings.screen.browse.components
|
package eu.kanade.presentation.more.settings.screen.browse.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -14,8 +15,10 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import mihon.domain.extensionrepo.model.ExtensionRepo
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
@@ -24,12 +27,12 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
fun ExtensionRepoCreateDialog(
|
fun ExtensionRepoCreateDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
onCreate: (String) -> Unit,
|
onCreate: (String) -> Unit,
|
||||||
repos: ImmutableSet<String>,
|
repoUrls: ImmutableSet<String>,
|
||||||
) {
|
) {
|
||||||
var name by remember { mutableStateOf("") }
|
var name by remember { mutableStateOf("") }
|
||||||
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val nameAlreadyExists = remember(name) { repos.contains(name) }
|
val nameAlreadyExists = remember(name) { repoUrls.contains(name) }
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
@@ -73,6 +76,7 @@ fun ExtensionRepoCreateDialog(
|
|||||||
Text(text = stringResource(msgRes))
|
Text(text = stringResource(msgRes))
|
||||||
},
|
},
|
||||||
isError = name.isNotEmpty() && nameAlreadyExists,
|
isError = name.isNotEmpty() && nameAlreadyExists,
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -115,3 +119,68 @@ fun ExtensionRepoDeleteDialog(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ExtensionRepoConflictDialog(
|
||||||
|
oldRepo: ExtensionRepo,
|
||||||
|
newRepo: ExtensionRepo,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onMigrate: () -> Unit,
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onMigrate()
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(MR.strings.action_replace_repo))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Text(text = stringResource(MR.strings.action_replace_repo_title))
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(text = stringResource(MR.strings.action_replace_repo_message, newRepo.name, oldRepo.name))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@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))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+16
@@ -5,12 +5,17 @@ package eu.kanade.presentation.more.settings.screen.browse.components
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Refresh
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import eu.kanade.presentation.category.components.CategoryFloatingActionButton
|
import eu.kanade.presentation.category.components.CategoryFloatingActionButton
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.more.settings.screen.browse.RepoScreenState
|
import eu.kanade.presentation.more.settings.screen.browse.RepoScreenState
|
||||||
|
import mihon.domain.extensionrepo.model.ExtensionRepo
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.components.material.Scaffold
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
@@ -23,7 +28,9 @@ import tachiyomi.presentation.core.util.plus
|
|||||||
fun ExtensionReposScreen(
|
fun ExtensionReposScreen(
|
||||||
state: RepoScreenState.Success,
|
state: RepoScreenState.Success,
|
||||||
onClickCreate: () -> Unit,
|
onClickCreate: () -> Unit,
|
||||||
|
onOpenWebsite: (ExtensionRepo) -> Unit,
|
||||||
onClickDelete: (String) -> Unit,
|
onClickDelete: (String) -> Unit,
|
||||||
|
onClickRefresh: () -> Unit,
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
@@ -33,6 +40,14 @@ fun ExtensionReposScreen(
|
|||||||
navigateUp = navigateUp,
|
navigateUp = navigateUp,
|
||||||
title = stringResource(MR.strings.label_extension_repos),
|
title = stringResource(MR.strings.label_extension_repos),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
actions = {
|
||||||
|
IconButton(onClick = onClickRefresh) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Refresh,
|
||||||
|
contentDescription = stringResource(resource = MR.strings.action_webview_refresh),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
@@ -55,6 +70,7 @@ fun ExtensionReposScreen(
|
|||||||
lazyListState = lazyListState,
|
lazyListState = lazyListState,
|
||||||
paddingValues = paddingValues + topSmallPaddingValues +
|
paddingValues = paddingValues + topSmallPaddingValues +
|
||||||
PaddingValues(horizontal = MaterialTheme.padding.medium),
|
PaddingValues(horizontal = MaterialTheme.padding.medium),
|
||||||
|
onOpenWebsite = onOpenWebsite,
|
||||||
onClickDelete = onClickDelete,
|
onClickDelete = onClickDelete,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+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()
|
||||||
|
|||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
package eu.kanade.presentation.more.settings.screen.data
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import eu.kanade.domain.sync.SyncPreferences
|
||||||
|
import eu.kanade.domain.sync.models.SyncSettings
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.util.Screen
|
||||||
|
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
|
||||||
|
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
|
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||||
|
import tachiyomi.presentation.core.components.SectionCard
|
||||||
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class SyncSettingsSelector : Screen() {
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val model = rememberScreenModel { SyncSettingsSelectorModel() }
|
||||||
|
val state by model.state.collectAsState()
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
AppBar(
|
||||||
|
title = stringResource(SYMR.strings.pref_choose_what_to_sync),
|
||||||
|
navigateUp = navigator::pop,
|
||||||
|
scrollBehavior = it,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { contentPadding ->
|
||||||
|
LazyColumnWithAction(
|
||||||
|
contentPadding = contentPadding,
|
||||||
|
actionLabel = stringResource(MR.strings.action_save),
|
||||||
|
actionEnabled = true,
|
||||||
|
onClickAction = {
|
||||||
|
navigator.pop()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
SectionCard(MR.strings.label_library) {
|
||||||
|
Options(BackupOptions.libraryOptions, state, model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
SectionCard(MR.strings.label_settings) {
|
||||||
|
Options(BackupOptions.settingsOptions, state, model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Options(
|
||||||
|
options: ImmutableList<BackupOptions.Entry>,
|
||||||
|
state: SyncSettingsSelectorModel.State,
|
||||||
|
model: SyncSettingsSelectorModel,
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
LabeledCheckbox(
|
||||||
|
label = stringResource(option.label),
|
||||||
|
checked = option.getter(state.options),
|
||||||
|
onCheckedChange = {
|
||||||
|
model.toggle(option.setter, it)
|
||||||
|
},
|
||||||
|
enabled = option.enabled(state.options),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SyncSettingsSelectorModel(
|
||||||
|
val syncPreferences: SyncPreferences = Injekt.get(),
|
||||||
|
) : StateScreenModel<SyncSettingsSelectorModel.State>(
|
||||||
|
State(syncOptionsToBackupOptions(syncPreferences.getSyncSettings())),
|
||||||
|
) {
|
||||||
|
fun toggle(setter: (BackupOptions, Boolean) -> BackupOptions, enabled: Boolean) {
|
||||||
|
mutableState.update {
|
||||||
|
val updatedOptions = setter(it.options, enabled)
|
||||||
|
syncPreferences.setSyncSettings(backupOptionsToSyncOptions(updatedOptions))
|
||||||
|
it.copy(options = updatedOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun syncNow(context: Context) {
|
||||||
|
SyncDataJob.startNow(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class State(
|
||||||
|
val options: BackupOptions = BackupOptions(),
|
||||||
|
) companion object {
|
||||||
|
private fun syncOptionsToBackupOptions(syncSettings: SyncSettings): BackupOptions {
|
||||||
|
return BackupOptions(
|
||||||
|
libraryEntries = syncSettings.libraryEntries,
|
||||||
|
categories = syncSettings.categories,
|
||||||
|
chapters = syncSettings.chapters,
|
||||||
|
tracking = syncSettings.tracking,
|
||||||
|
history = syncSettings.history,
|
||||||
|
appSettings = syncSettings.appSettings,
|
||||||
|
extensionRepoSettings = syncSettings.extensionRepoSettings,
|
||||||
|
sourceSettings = syncSettings.sourceSettings,
|
||||||
|
privateSettings = syncSettings.privateSettings,
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
customInfo = syncSettings.customInfo,
|
||||||
|
readEntries = syncSettings.readEntries,
|
||||||
|
savedSearches = syncSettings.savedSearches,
|
||||||
|
// SY <--
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun backupOptionsToSyncOptions(backupOptions: BackupOptions): SyncSettings {
|
||||||
|
return SyncSettings(
|
||||||
|
libraryEntries = backupOptions.libraryEntries,
|
||||||
|
categories = backupOptions.categories,
|
||||||
|
chapters = backupOptions.chapters,
|
||||||
|
tracking = backupOptions.tracking,
|
||||||
|
history = backupOptions.history,
|
||||||
|
appSettings = backupOptions.appSettings,
|
||||||
|
extensionRepoSettings = backupOptions.extensionRepoSettings,
|
||||||
|
sourceSettings = backupOptions.sourceSettings,
|
||||||
|
privateSettings = backupOptions.privateSettings,
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
customInfo = backupOptions.customInfo,
|
||||||
|
readEntries = backupOptions.readEntries,
|
||||||
|
savedSearches = backupOptions.savedSearches,
|
||||||
|
// SY <--
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
package eu.kanade.presentation.more.settings.screen.data
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import eu.kanade.domain.sync.SyncPreferences
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.util.Screen
|
||||||
|
import eu.kanade.tachiyomi.data.sync.models.SyncTriggerOptions
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||||
|
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||||
|
import tachiyomi.presentation.core.components.SectionCard
|
||||||
|
import tachiyomi.presentation.core.components.material.Scaffold
|
||||||
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class SyncTriggerOptionsScreen : Screen() {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content() {
|
||||||
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
val model = rememberScreenModel { SyncOptionsScreenModel() }
|
||||||
|
val state by model.state.collectAsState()
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
AppBar(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_options),
|
||||||
|
navigateUp = navigator::pop,
|
||||||
|
scrollBehavior = it,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { contentPadding ->
|
||||||
|
LazyColumnWithAction(
|
||||||
|
contentPadding = contentPadding,
|
||||||
|
actionLabel = stringResource(MR.strings.action_save),
|
||||||
|
actionEnabled = true,
|
||||||
|
onClickAction = {
|
||||||
|
navigator.pop()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
SectionCard(SYMR.strings.label_triggers) {
|
||||||
|
Options(SyncTriggerOptions.mainOptions, state, model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Options(
|
||||||
|
options: ImmutableList<SyncTriggerOptions.Entry>,
|
||||||
|
state: SyncOptionsScreenModel.State,
|
||||||
|
model: SyncOptionsScreenModel,
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
LabeledCheckbox(
|
||||||
|
label = stringResource(option.label),
|
||||||
|
checked = option.getter(state.options),
|
||||||
|
onCheckedChange = {
|
||||||
|
model.toggle(option.setter, it)
|
||||||
|
},
|
||||||
|
enabled = option.enabled(state.options),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SyncOptionsScreenModel(
|
||||||
|
val syncPreferences: SyncPreferences = Injekt.get(),
|
||||||
|
) : StateScreenModel<SyncOptionsScreenModel.State>(
|
||||||
|
State(
|
||||||
|
syncPreferences.getSyncTriggerOptions(),
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun toggle(setter: (SyncTriggerOptions, Boolean) -> SyncTriggerOptions, enabled: Boolean) {
|
||||||
|
mutableState.update {
|
||||||
|
val updatedTriggerOptions = setter(it.options, enabled)
|
||||||
|
syncPreferences.setSyncTriggerOptions(updatedTriggerOptions)
|
||||||
|
it.copy(
|
||||||
|
options = updatedTriggerOptions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class State(
|
||||||
|
val options: SyncTriggerOptions = SyncTriggerOptions(),
|
||||||
|
)
|
||||||
|
}
|
||||||
+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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import androidx.activity.compose.BackHandler
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
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.CalendarMonth
|
||||||
import androidx.compose.material.icons.outlined.FlipToBack
|
import androidx.compose.material.icons.outlined.FlipToBack
|
||||||
import androidx.compose.material.icons.outlined.Refresh
|
import androidx.compose.material.icons.outlined.Refresh
|
||||||
import androidx.compose.material.icons.outlined.SelectAll
|
import androidx.compose.material.icons.outlined.SelectAll
|
||||||
@@ -50,6 +51,7 @@ fun UpdateScreen(
|
|||||||
onClickCover: (UpdatesItem) -> Unit,
|
onClickCover: (UpdatesItem) -> Unit,
|
||||||
onSelectAll: (Boolean) -> Unit,
|
onSelectAll: (Boolean) -> Unit,
|
||||||
onInvertSelection: () -> Unit,
|
onInvertSelection: () -> Unit,
|
||||||
|
onCalendarClicked: () -> Unit,
|
||||||
onUpdateLibrary: () -> Boolean,
|
onUpdateLibrary: () -> Boolean,
|
||||||
onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit,
|
onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit,
|
||||||
onMultiBookmarkClicked: (List<UpdatesItem>, bookmark: Boolean) -> Unit,
|
onMultiBookmarkClicked: (List<UpdatesItem>, bookmark: Boolean) -> Unit,
|
||||||
@@ -63,6 +65,7 @@ fun UpdateScreen(
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { scrollBehavior ->
|
topBar = { scrollBehavior ->
|
||||||
UpdatesAppBar(
|
UpdatesAppBar(
|
||||||
|
onCalendarClicked = { onCalendarClicked() },
|
||||||
onUpdateLibrary = { onUpdateLibrary() },
|
onUpdateLibrary = { onUpdateLibrary() },
|
||||||
actionModeCounter = state.selected.size,
|
actionModeCounter = state.selected.size,
|
||||||
onSelectAll = { onSelectAll(true) },
|
onSelectAll = { onSelectAll(true) },
|
||||||
@@ -132,6 +135,7 @@ fun UpdateScreen(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun UpdatesAppBar(
|
private fun UpdatesAppBar(
|
||||||
|
onCalendarClicked: () -> Unit,
|
||||||
onUpdateLibrary: () -> Unit,
|
onUpdateLibrary: () -> Unit,
|
||||||
// For action mode
|
// For action mode
|
||||||
actionModeCounter: Int,
|
actionModeCounter: Int,
|
||||||
@@ -147,6 +151,11 @@ private fun UpdatesAppBar(
|
|||||||
actions = {
|
actions = {
|
||||||
AppBarActions(
|
AppBarActions(
|
||||||
persistentListOf(
|
persistentListOf(
|
||||||
|
AppBar.Action(
|
||||||
|
title = stringResource(MR.strings.action_view_upcoming),
|
||||||
|
icon = Icons.Outlined.CalendarMonth,
|
||||||
|
onClick = onCalendarClicked,
|
||||||
|
),
|
||||||
AppBar.Action(
|
AppBar.Action(
|
||||||
title = stringResource(MR.strings.action_update_library),
|
title = stringResource(MR.strings.action_update_library),
|
||||||
icon = Icons.Outlined.Refresh,
|
icon = Icons.Outlined.Refresh,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
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 com.google.accompanist.web.AccompanistWebViewClient
|
import com.kevinnzou.web.AccompanistWebViewClient
|
||||||
import com.google.accompanist.web.LoadingState
|
import com.kevinnzou.web.LoadingState
|
||||||
import com.google.accompanist.web.WebContent
|
import com.kevinnzou.web.WebContent
|
||||||
import com.google.accompanist.web.WebView
|
import com.kevinnzou.web.WebView
|
||||||
import com.google.accompanist.web.rememberWebViewNavigator
|
import com.kevinnzou.web.rememberWebViewNavigator
|
||||||
import com.google.accompanist.web.rememberWebViewState
|
import com.kevinnzou.web.rememberWebViewState
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user