Compare commits

...

318 Commits

Author SHA1 Message Date
Kyle Nguyen
1c8ec59df1
Merge 0e0a9aac5b into be671b42ce 2024-09-19 07:12:26 +00:00
imkunet
0e0a9aac5b
Make spotless 2024-09-19 03:12:00 -04:00
imkunet
7a50521ad7
Add migration to add notes to manga 2024-09-19 03:05:45 -04:00
imkunet
5c690cc6c2
Fixes to pass relevant testing 2024-09-19 03:05:02 -04:00
imkunet
05fc1d7b4f
Impose note editor length limit 2024-09-19 03:05:02 -04:00
imkunet
f262f68ea7
Fixed padding 2024-09-19 03:05:02 -04:00
imkunet
44cffcfcf7
Make cursor jump to end by default 2024-09-19 03:05:02 -04:00
imkunet
5a42eb0d5f
Added fade transition between states 2024-09-19 03:05:02 -04:00
imkunet
e861b97bac
Make the edit notes button edit directly 2024-09-19 03:05:01 -04:00
imkunet
23be98b6d4
Added tablet notes 2024-09-19 03:05:01 -04:00
imkunet
610e37510c
Polishing off note editor
- moved note to manga screen
- added backup support
- make notes save
- change the way the initial model is loaded
2024-09-19 03:05:01 -04:00
imkunet
309086920c
Add the text editor
pending work is to save the notes and make it work with the backup
2024-09-19 02:50:43 -04:00
imkunet
28c23d184a
Initial markdown render test 2024-09-19 02:50:42 -04:00
AntsyLich
be671b42ce
Move firebase permission removal to standard flavor
And disable some more stuff
2024-09-18 17:37:33 +06:00
renovate[bot]
0042cb6582
fix(deps): update dependency com.android.tools.build:gradle to v8.6.1 (#1235)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-18 15:35:47 +06:00
renovate[bot]
1e570bc965
fix(deps): update dependency me.zhanghai.android.libarchive:library to v1.1.1 (#1229)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-17 14:48:00 +06:00
Roshan Varughese
9cc7d42dd9
Re-enable fetching chapters list for entries with licenced status (#1230)
Enable Licensed
2024-09-17 14:47:04 +06:00
MajorTanya
f5c6d2e1a6
Fix Kitsu synopsis nullability (#1233)
This time, the Kitsu API docs are silent on whether this field (or
any other field) can be null/undefined/etc, but it can happen and
caused an error during search and update. This change just ensures the
attribute is nullable and is set to an empty String when it is null.
2024-09-17 14:46:37 +06:00
Roshan Varughese
339dc33f58
Fix WheelPicker Manual Input (#1209)
* Fix WheelPicker Manual Input

* Lambda

* inline

* Update WheelPicker.kt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-09-14 14:43:03 +00:00
Cuong-Tran
223af5508f
Fix: wrong calculation of nextUpdate when setting custom fetchInterval (#1206) 2024-09-14 19:58:24 +06:00
renovate[bot]
d42f776c5c
fix(deps): update dependency androidx.compose:compose-bom to v2024.09.01 (#1214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:57:58 +06:00
renovate[bot]
5c0dc3e05a
fix(deps): update dependency com.google.firebase:firebase-bom to v33.3.0 (#1216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:57:44 +06:00
renovate[bot]
bebf80dfae
fix(deps): update dependency com.squareup.okio:okio to v3.9.1 (#1217)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:57:31 +06:00
renovate[bot]
86dd809f4d
chore(deps): update gradle/actions action to v4.1.0 (#1219)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:57:14 +06:00
renovate[bot]
1ff88dd927
fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-coroutines-bom to v1.9.0 (#1222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:56:58 +06:00
renovate[bot]
be5d467955
chore(deps): update actions/setup-java action to v4.3.0 (#1212)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-14 19:56:47 +06:00
renovate[bot]
fcb01b5bcf
chore(deps): update dependency gradle to v8.10.1 (#1211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-09 17:29:31 +06:00
renovate[bot]
844dae1a4d
fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-collections-immutable to v0.3.8 (#1198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-09 17:29:12 +06:00
AntsyLich
83fd4746ed
Use new library for injekt with inorichi patch 2024-09-08 20:09:45 +06:00
NGB-Was-Taken
c8ad6cdf31
Show toast for app restart when User-Agent is changed (#1204) 2024-09-07 14:15:22 +06:00
AntsyLich
fbcc48fefc
Bump NDK version (#1203) 2024-09-07 14:14:59 +06:00
AntsyLich
6f422745ba
Reduce ChapterNavigator horizontal padding on small ui (#1202)
Co-authored-by: p
2024-09-07 14:14:42 +06:00
AntsyLich
bec549cc44
Use TextFieldState in BasicTextField where applicable (#1201)
Co-authored-by: p
2024-09-07 08:11:14 +00:00
AntsyLich
c4f235ae07
Use uy.kohesive.injekt instead of com.github.inorichi.injekt (#1205) 2024-09-07 08:01:49 +00:00
AntsyLich
8fd1239bea
spotlessApply my beloved (#1196) 2024-09-05 13:03:24 +00:00
bapeey
b56a97bb8e
Ignore "intent://" urls on webview (#1193)
ignore intent urls
2024-09-05 16:11:09 +06:00
renovate[bot]
52036e5664
fix(deps): update dependency androidx.activity:activity-compose to v1.9.2 (#1189)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-05 16:08:40 +06:00
renovate[bot]
29a74509a4
fix(deps): update dependency com.google.accompanist:accompanist-systemuicontroller to v0.36.0 (#1192)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-05 16:08:27 +06:00
renovate[bot]
0e956cbb51
fix(deps): update lifecycle.version to v2.8.5 (#1190)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-05 16:08:06 +06:00
AntsyLich
2baffa62ca
Switch to stable compose 2024-09-05 16:07:08 +06:00
AntsyLich
bd7b354198
Move archive related code to :core:archive 2024-09-05 16:00:46 +06:00
AntsyLich
70c1a842b2
Rename LocalesConfigPlugin file to LocalesConfigTask 2024-09-05 14:17:18 +06:00
MajorTanya
001249a89d
Fix Kitsu ratingTwenty being typed as String (#1191)
The API docs and the responses type `ratingTwenty` as a "number" (Int
in Kotlin, it's divided by 2 for a .5 step scale 0-10). It's nullable
because an entry without a user rating returns `null` in that field.
2024-09-05 10:56:58 +06:00
renovate[bot]
c4d2fffb12
fix(deps): update dependency com.android.tools:desugar_jdk_libs to v2.1.2 (#1188)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-04 16:20:22 +06:00
AntsyLich
f22767d863
Fix mishap in 02af9b1acf 2024-09-03 17:32:19 +06:00
AntsyLich
02af9b1acf
Remove more unnecessary permissions from Firebase dependency 2024-09-03 17:22:39 +06:00
AntsyLich
3c611b95fb
Add crashlytics to standard builds 2024-09-03 15:45:19 +06:00
AntsyLich
fc1c804bfd
Migrate some classpaths to gradle plugins 2024-09-03 14:09:12 +06:00
Roshan Varughese
abfb72c89c
Option to update trackers when chapter marked as read (#1177)
* Track when marked as read

* Add dismiss to snack bar

* i18n & ignore decimal chapters

* Detekt would have caught that 🤣

* `Ok` > `Yes`

* Dont prompt if untracked or current > new

* Move to MangaScreenModel

* Suggestions

Co-Authored-By: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

* Review 2

* toggleAllSelections first

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-09-03 03:41:44 +06:00
Smol Ame
9c1905ede7
Enable 'Split Tall Images' by default (#1185) 2024-09-03 01:46:28 +06:00
MajorTanya
9f99f038f3
Use DTOs to parse tracking API responses (#1103)
* Migrate tracking APIs to DTOs

Changes the handling of tracker API responses to be parsed to DTOs
instead of doing so "manually" by use of `jsonPrimitive`s and/or
`Json.decodeFromString` invocations.

This greatly simplifies the API response handling.

Renamed constants to SCREAMING_SNAKE_CASE.

Largely tried to name the DTOs in a uniform pattern, with the
tracker's (short) name at the beginning of file and data class names
(ALOAuth instead of OAuth, etc).

With these changes, no area of the code base should be using
`jsonPrimitive` and/or `Json.decodeFromString` anymore.

* Fix wrong types in KitsuAlgoliaSearchItem

This API returns start and end dates as Long and the score as Double.

Kitsu's docs claim they're strings (and they are, when requesting
manga details from Kitsu directly) but the Algolia search results
return Longs and Double, respectively.

* Apply review changes

- Renamed `BangumiX` classes to `BGMX` classes.
- Renamed `toXStatus` and `toXScore` to `toApiStatus` and `toApiScore`

* Handle migration from detekt to spotless

Removed Suppressions added for detekt.

Specifically removed:
- `SwallowedException` where an exception ends as a default value
- `MagicNumber`
- `CyclomaticComplexMethod`
- `TooGenericExceptionThrown`

Also ran spotlessApply which changed SMAddMangaResponse

* Fix Kitsu failing to add series

The `included` attribute seems to only appear when the user already
has the entry in their Kitsu list.

Since both `data` and `included` are required for `firstToTrack`, a
guard clause has been added before all its calls.

* Fix empty Bangumi error when entry doesn't exist

Previously, the non-null assertion (!!) would cause a
NullPointerException and a Toast with
"Bangumi error: " (no message) when the user had removed their list
entry from Bangumi through other means like the website.

Now it will show "Bangumi error: Could not find manga".

This is analogous to the error shown by Kitsu under these
circumstances.

* Fix Shikimori ignoring missing remote entry

The user would see no indication that Shikimori could not properly
refresh the track from the remote. This change causes the error Toast
notification to pop up with the following message
"Shikimori error: Could not find manga".

This is analogous to Kitsu and Bangumi.

* Remove usage of let where not needed

These particular occurrences weren't needed because properties are
directly accessible to further act upon. This neatly simplifies these
clauses.

* Remove missed let
2024-09-03 01:46:08 +06:00
AntsyLich
6c6ea84509
spotlessApply my beloved 2024-09-02 22:35:00 +06:00
AntsyLich
4ee31bfea5
Add stable marker to Manga data class
Co-authored-by: ivan <12537387+ivaniskandar@users.noreply.github.com>
2024-09-02 21:54:53 +06:00
AntsyLich
03eb756ecb
Collect MangaScreen state with lifecycle
Co-authored-by: ivan <12537387+ivaniskandar@users.noreply.github.com>
2024-09-02 21:22:21 +06:00
AntsyLich
a45eb5e528
PagerPageHolder: lazy init loading indicator
Co-authored-by: ivan <12537387+ivaniskandar@users.noreply.github.com>
2024-09-02 21:13:52 +06:00
AntsyLich
8f9a325895
Use feature flags in compose compiler plugin
And slight cleanup
2024-08-30 13:55:11 +06:00
renovate[bot]
f74071ab0a
fix(deps): update dependency com.android.tools.build:gradle to v8.6.0 (#1178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 11:37:56 +06:00
renovate[bot]
7fb3ef48e4
fix(deps): update dependency com.android.tools:desugar_jdk_libs to v2.1.1 (#1172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 11:37:38 +06:00
renovate[bot]
1837faa573
fix(deps): update serialization.version to v1.7.2 (#1173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-30 11:37:22 +06:00
AntsyLich
518abf032c
Remove legacy broken source and history backup 2024-08-30 11:36:34 +06:00
Roshan Varughese
7ca64a67c5
Hide keyboard when a Tracker SearchResultItem is clicked (#1168)
* Hide keyboard on select

* Code Review Suggestion
2024-08-27 18:26:55 +06:00
renovate[bot]
d26c010e57
chore(deps): update gradle/actions action to v4.0.1 (#1165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-27 18:02:08 +06:00
renovate[bot]
607e56a4ec
fix(deps): update dependency com.android.tools:desugar_jdk_libs to v2.1.0 (#1162)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-26 23:08:39 +06:00
Catting
952a98c180
Add "show entry" action to download notifications (#1159)
* Add 'show entry' to download notifications

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

* fixup! Add 'show entry' to download notifications

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

* fixup! Add 'show entry' to download notifications

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

* spotless! Add 'show entry' to download notifications

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

* fixup! spotless- Apply suggestions from code review

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

---------

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-26 19:31:02 +06:00
Roshan Varughese
45628b14db
Add confirmation when adding repo via URI (#1158)
* Add confirmation when adding repo via URI

* Blank lines

* Suggestions

* Reverting Changes

* Removing Unused Imports
2024-08-25 22:07:14 +06:00
Roshan Varughese
5dc6569a68
Respect privacy settings in extension update notification (#1156)
* Hide Extension Names in Update Notifications when Content is Hidden

* Moving `val` inside if

* [skip ci] Update CHANGELOG.md
2024-08-25 19:47:25 +06:00
renovate[bot]
fba9bacdc1
fix(deps): update aboutlib.version to v11.2.3 (#1151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 22:41:29 +06:00
Dani
ca968f162e
Add option to skip downloading duplicate read chapters (#1125)
* Add query to get chapter count by manga and chapter number

* Add functions to get chapter count by manga and chapter number

* Only count read chapters

* Add interactor

* Savepoint

* Extract new chapter logic to separate function

* Update javadocs

* Add preference to toggle new functionality

* Add todo

* Add debug logcat

* Use string resource instead of hardcoding title

* Add temporary logcat for debugging

* Fix detekt issues

* Update javadocs

* Update download unread chapters preference

* Remove debug logcat calls

* Update javadocs

* Resolve issue where read chapters were still being downloaded during manual manga fetch

* Apply code review changes

* Apply code review changes

* Revert "Apply code review changes"

This reverts commit 1a2dce78acc66a7c529ce5b572bdaf94804b1a30.

* Revert "Apply code review changes"

This reverts commit ac2a77829313967ad39ce3cb0c0231083b9d640d.

* Group download chapter logic inside the interactor GetChaptersToDownload

* Update javadocs

* Apply code review

* Apply code review

* Apply code review

* Update CHANGELOG.md to include the new feature

* Run spotless

* Update domain/src/main/java/mihon/domain/chapter/interactor/FilterChaptersForDownload.kt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-23 15:43:46 +06:00
renovate[bot]
379d587826
fix(deps): update moko to v0.24.2 (#1148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 13:08:49 +06:00
renovate[bot]
034ec4cb12
chore(deps): update kotlin monorepo to v2.0.20 (#1144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 07:23:52 +06:00
renovate[bot]
2481767532
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.08.00-alpha02 (#1143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 07:23:42 +06:00
renovate[bot]
ab2b734d49
fix(deps): update dependency com.google.firebase:firebase-analytics to v22.1.0 (#1146)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-23 07:22:55 +06:00
MajorTanya
aac4d6e548
Add PR or commit refs to CHANGELOG.md (#1117)
* [skip ci] Add PR or commit refs to CHANGELOG.md

* [skip ci] Update CHANGELOG.md

* [skip ci] Make usernames, PRs, hashes clickable

GFM autolinking for those is not applied to all Markdown documents.

* Change commit style

* [skip ci] Add ref to #1057

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-22 04:36:43 +06:00
renovate[bot]
08ae51ea8c
fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.3.0 (#1142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-22 00:27:56 +06:00
Hosted Weblate
4387ae5ff3
Translations update from Hosted Weblate
Co-authored-by: Ahmed seif al-nasr <ahmdsyfalnsr2@gmail.com>
Co-authored-by: Anas KANJO <anas.kanjo2022@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: Frosted <cinardogan110@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: gekka <1778962971@qq.com>
Co-authored-by: ɴᴇᴋᴏ <s99095lkjjim@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/tr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ar/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/id/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/tr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals
2024-08-20 02:32:52 +06:00
AntsyLich
d6252ab770
Address spotless lint errors (#1138)
* Add spotless (with ktlint)

* Run spotlessApply

* screaming case screaming case screaming case

* Update PagerViewerAdapter.kt

* Update ReaderTransitionView.kt
2024-08-19 18:11:39 +06:00
AntsyLich
5ae8095ef1
Add spotless (with ktlint) (#1136) 2024-08-19 18:11:14 +06:00
AntsyLich
ac41bffdc9
Generate locales_config.xml in build dir 2024-08-19 16:52:23 +06:00
AntsyLich
777ae2461e
Remove detekt (#1130)
Annoying. More annoying in this project.
2024-08-19 12:51:37 +06:00
renovate[bot]
b2f1719c50
fix(deps): update dependency org.conscrypt:conscrypt-android to v2.5.3 (#1135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-19 10:59:11 +06:00
renovate[bot]
3f050a83dd
chore(deps): update dependency gradle to v8.10 (#1122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-14 20:18:25 +06:00
renovate[bot]
6f4e3f776f
fix(deps): update dependency org.junit.jupiter:junit-jupiter to v5.11.0 (#1121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-14 20:16:39 +06:00
FooIbar
1c47a6b9b3
Add comment about RecyclerView cache size (#1119)
Note for forks: Increasing cache size may cause OOM on API < 26, better
to make it API 26+ only.
2024-08-13 22:03:10 +06:00
AntsyLich
f4348df870
Remove WebViewClientCompat 2024-08-13 13:42:14 +06:00
AntsyLich
9a34ace09c
Sync compose theme with MDC theme 2024-08-13 12:42:32 +06:00
AntsyLich
124a787cda
Update CHANGELOG.md 2024-08-12 23:51:56 +06:00
AntsyLich
b404a71e26
Create CHANGELOG.md 2024-08-12 23:34:46 +06:00
MajorTanya
be124ebe86
Fix some migrations never running (#1114)
Both `SetupBackupCreateMigration` and `SetupLibraryUpdateMigration` were
trying to get the `App` class from Injekt which is never provided via
the `AppModule`. Using `Application` instead works since the
`workManager` property used by the respective `setupTask` functions is
an extension property on `Context`.

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-12 05:36:34 +06:00
AntsyLich
fdb96179c6
Handle Android SDK 35 API collision 2024-08-12 05:22:56 +06:00
Catting
c5994e057b
Add an "open in browser" button to reader menu (#1110)
* Add an "open in browser" button to reader menu

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

* fixup! Add an "open in browser" button to reader menu

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>

---------

Signed-off-by: Catting <5874051+mm12@users.noreply.github.com>
2024-08-12 03:52:47 +06:00
AntsyLich
3f1d28c383
Fix UI freeze after migration
Fixes #938
2024-08-12 03:21:17 +06:00
AntsyLich
84b2164787
Add a button to select all scanlators
Resolves #943
Closes #1109
2024-08-12 02:51:13 +06:00
Catting
200d39e023
Add Copy Tracker URL on icon long press (#1101)
* Add Copy Tracker URL on icon long press

Signed-off-by: Catt0s <5874051+mm12@users.noreply.github.com>

* Add 'Copy To Clipboard' to tracker item menu

Signed-off-by: Catt0s <5874051+mm12@users.noreply.github.com>

* Add 'Copy link' to locales.

Signed-off-by: Catt0s <5874051+mm12@users.noreply.github.com>

* Implement code review suggestions
>
> Co-authored-by: AntsyLich  <59261191+AntsyLich@users.noreply.github.com>

Signed-off-by: Catt0s <5874051+mm12@users.noreply.github.com>

* Update app/src/main/java/eu/kanade/presentation/track/components/TrackLogoIcon.kt

---------

Signed-off-by: Catt0s <5874051+mm12@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-11 23:10:36 +06:00
Weblate (bot)
b1b15a93ee
Translations update from Hosted Weblate (#939)
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ar/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ca/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/cs/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/de/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/es/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/fil/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/id/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ja/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ml/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ru/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/sv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/am/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ar/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/be/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/bg/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/bn/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ca/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ceb/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cs/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/da/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/eo/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/eu/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fa/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fi/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/he/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hi/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/id/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/jv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ka/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/kk/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/km/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/kn/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ko/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/lt/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/lv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ml/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/mr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ms/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nl/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nn/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pl/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ro/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sa/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sah/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sc/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sdh/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sk/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sq/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sv/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/te/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/th/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/tr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/uk/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/uz/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/vi/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals

Co-authored-by: Ahmed seif al-nasr <ahmdsyfalnsr2@gmail.com>
Co-authored-by: Ajeje Brazorf <lmelonimamo@yahoo.it>
Co-authored-by: Akhil Raj <akhilakae07@gmail.com>
Co-authored-by: Animeboynz <40583749+Animeboynz@users.noreply.github.com>
Co-authored-by: David Katrinka <davidkatrinka1995@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: Eduard Ereza Martínez <eduard@ereza.cat>
Co-authored-by: Eji-san <ejierubani@gmail.com>
Co-authored-by: FateXBlood <fatexblood@gmail.com>
Co-authored-by: Giorgio Sanna <sannagiorgio1997@gmail.com>
Co-authored-by: Iker Lerones <ikerlero@hotmail.com>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
Co-authored-by: Matyáš Caras <matyas@caras.wtf>
Co-authored-by: Norsze <norbert.szabo7+github@gmail.com>
Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: abc0922001 <abc0922001@hotmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: gekka <1778962971@qq.com>
Co-authored-by: sebastians17 <sebastians117.ss@gmail.com>
Co-authored-by: vodkapmp <vodkapmp@gmail.com>
Co-authored-by: ɴᴇᴋᴏ <s99095lkjjim@gmail.com>
Co-authored-by: Артём Голуб <artemtirax2001@gmail.com>
2024-08-11 22:55:47 +06:00
MajorTanya
97c81fadb4
Fix MAL search results not showing start dates (#1098)
The previous approach would always throw an Exception because
`SimpleDateFormat.format()` expects the input to be of type `Date` or
`Number`, not `String`.
2024-08-11 22:55:13 +06:00
MajorTanya
9240eceedc
Change Kitsu to kitsu.app domain (#1106)
cf. 244fdccca9
2024-08-11 22:40:28 +06:00
Catting
14ae57d78b
Contributing: ktLintFormat -> detekt (#1102)
* Contributing: ktLintFormat -> detekt 

update Contributing info to use detekt instead of ktLintFormat

* Update CONTRIBUTING.md

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-11 03:58:02 +06:00
renovate[bot]
4828c54245
fix(deps): update dependency com.android.tools.build:gradle to v8.5.2 (#1099)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 09:51:28 +06:00
renovate[bot]
dca9bf1057
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.08.00-alpha01 (#1094)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 04:31:56 +06:00
renovate[bot]
e8b7c3e24b
fix(deps): update dependency io.coil-kt.coil3:coil-bom to v3.0.0-alpha10 (#1092)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 04:29:35 +06:00
renovate[bot]
af77083660
fix(deps): update dependency androidx.work:work-runtime to v2.9.1 (#1091)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 04:23:36 +06:00
renovate[bot]
36b9caeea8
fix(deps): update dependency androidx.annotation:annotation to v1.8.2 (#1090)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 04:22:33 +06:00
renovate[bot]
fdc1423f3d
chore(deps): update gradle/actions action to v4 (#1095)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 02:33:30 +06:00
renovate[bot]
8e40146f96
fix(deps): update paging.version to v3.3.2 (#1093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-09 01:44:48 +06:00
AntsyLich
1c16fc79c2
ExpandableMangaDescription: Adjust size transform anim spec
Co-authored-by: ivan <12537387+ivaniskandar@users.noreply.github.com>
2024-08-07 14:30:39 +06:00
Roshan Varughese
31263084ec
Add Backup and Restore of Extension Repos (#1057)
* Backup/Restore Extension Repos

* Refactor

* Moving to Under App Settings

* Sort by URL, Check existing by SHA and Error Logging

Untested. Currently in a lecture and can't test if the changes really work.

* Changes to logic

* Don't ask me what's happening here

* Renaming Variables

* Fixing restoreAmount & changes to logic

Co-Authored-By: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-08-07 13:49:17 +06:00
AntsyLich
2858ef835f
Rename backup restore error log file 2024-08-07 12:02:49 +06:00
renovate[bot]
edb8201f74
chore(deps): update kotlin monorepo to v2.0.10 (#1085)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-06 20:41:28 +06:00
FooIbar
854474f85f
Don't crash on ill-formed URLs (#1084) 2024-08-06 20:39:49 +06:00
Tran M. Cuong
04db46fe75
fix: drawScrollbar crash on list with 0 item but only sticky header (#1083) 2024-08-06 20:38:56 +06:00
renovate[bot]
3f6bd5f010
chore(deps): update actions/setup-java action to v4.2.2 (#1080)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-06 20:38:13 +06:00
FooIbar
a3dfd2efe6
Match extra layout space with scroll distance (#1076)
And increase recycler item view cache size.
2024-08-04 21:45:11 +06:00
Vetle Ledaal
de8ef6dad7
Improve error message if restoring from JSON file (#1056)
* Improve error message if restoring from JSON file

* Replace Exception with IOException

* Use more generic error message if protobuf fails

* fix lint
2024-07-31 20:39:41 +06:00
AntsyLich
8160b47ff5
Bump default user agent string 2024-07-30 21:09:56 +06:00
AntsyLich
c201b341a7
Cleanup backup/restore related code 2024-07-30 04:59:16 +06:00
AntsyLich
56fb4f62a1
Fix library is backed up when disabled and make categories backup/restore independent 2024-07-30 04:47:57 +06:00
Roshan Varughese
0af90999c8
Adds Option to Copy Panel to Clipboard (#1003)
* Add Copy to Clipboard

* Removing Unused Import

* Reusing onShare function

* Commit Suggestion

* Early Return on null

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-07-27 02:59:59 +06:00
Tran M. Cuong
913ff22132
Fix disappearance items when fast scrolling (#1035)
* Don't use animateItem's fade-in/fade-out in FastScrollLazyColumn

* Move to extension function

Avoid using animateItemPlacement name since it's shadowed by compose-bom's deprecated one
2024-07-27 01:01:32 +06:00
renovate[bot]
04aa5b36a5
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.07.00-alpha02 (#1051)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-26 19:23:23 +06:00
renovate[bot]
41e2dc7ae8
fix(deps): update paging.version to v3.3.1 (#1046)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 22:00:41 +06:00
Roshan Varughese
88efde8796
Format Category String on Subtitle Display (#1030)
* Fixes #1029

* Max Line Length Fix

* Update SettingsLibraryScreen.kt

No idea how this works.

Co-authored-by: Foolbar <118464521+Foolbar@users.noreply.github.com>

---------

Co-authored-by: Foolbar <118464521+Foolbar@users.noreply.github.com>
2024-07-25 22:00:06 +06:00
renovate[bot]
b7849d7146
fix(deps): update lifecycle.version to v2.8.4 (#1045)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 21:35:38 +06:00
renovate[bot]
602b58f364
fix(deps): update dependency androidx.annotation:annotation to v1.8.1 (#1043)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 01:15:21 +06:00
renovate[bot]
e48dbdbf23
fix(deps): update dependency androidx.activity:activity-compose to v1.9.1 (#1042)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-25 01:14:44 +06:00
renovate[bot]
6ace423e18
chore(deps): update softprops/action-gh-release action to v2.0.8 (#1024)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 19:09:53 +06:00
FooIbar
51b68cd25f
Remove obsolete workaround (#1021) 2024-07-24 19:09:29 +06:00
renovate[bot]
ca784cbe32
fix(deps): update dependency io.coil-kt.coil3:coil-bom to v3.0.0-alpha09 (#1039)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-24 18:53:11 +06:00
renovate[bot]
4f61b2e4e8
fix(deps): update dependency io.mockk:mockk to v1.13.12 (#1016)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-16 16:19:27 +06:00
renovate[bot]
8c9d12a840
chore(deps): update gradle/actions action to v3.5.0 (#1018)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-16 16:19:14 +06:00
renovate[bot]
f63e950910
chore(deps): update dependency gradle to v8.9 (#1007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 06:04:57 +06:00
renovate[bot]
f3f2bd41c3
fix(deps): update dependency org.jsoup:jsoup to v1.18.1 (#999)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 04:52:17 +06:00
renovate[bot]
14d687c5cd
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.07.00-alpha01 (#1002)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 04:52:08 +06:00
renovate[bot]
e94c8dac94
chore(deps): update actions/dependency-review-action action to v4.3.4 (#1009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 04:51:55 +06:00
renovate[bot]
7a2ca4bf4d
fix(deps): update dependency com.android.tools.build:gradle to v8.5.1 (#1010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-12 04:51:42 +06:00
Roshan Varughese
4a7613d515
A Minor Milestone (#1000)
* Fixes README.md Alignment

* Adds parameter to both
2024-07-10 21:30:12 +06:00
renovate[bot]
e65634cb42
Bump coil version and some cleanup
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-10 01:24:32 +06:00
FooIbar
daa47e0493
Fix some issues when reading/saving images (#993)
* Fix unsupported mime type error when saving images

Avoid using platform mime type map to get extensions as it may not have
all mime types we support.

* Fix jxl images downloading/reading
2024-07-08 16:02:50 +06:00
AntsyLich
cbcd8bd668
Fix login prompts despite being logged in to trackers in Manga screen 2024-07-08 09:20:58 +06:00
AntsyLich
2092c81bad
Observe tracker login state instead of fetching once (#987)
* Observe tracker login state instead of fetching once

* Review changes
2024-07-06 07:25:33 +06:00
AntsyLich
5a61ca5535
Make global search "Has result" sticky
Closes #133
2024-07-03 06:00:04 +06:00
Roshan Varughese
ddba71df37
Smart Update Dialog Tweak (#977)
* Smart Update Dialog Fix

* Build Fail Change 1

* Commit Suggested Change

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

* Build Fail Change 2

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-07-02 18:08:33 +06:00
CrepeTF
75b5d96601
Correct tako variable colours (#976) 2024-07-02 16:52:55 +06:00
renovate[bot]
77db8873f6
fix(deps): update lifecycle.version to v2.8.3 (#972)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-02 01:58:48 +06:00
WerctFourth
bff6183cf3
Update image-decoder revision (#971) 2024-07-01 22:15:46 +06:00
Ahmad Ansori Palembani
e620665dda
Add safeguard to prevent ArchiveInputStream from being closed twice (#967)
* fix: Add safeguard to prevent ArchiveInputStream from being closed twice

* detekt

* lint: Make detekt happy

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-30 19:57:29 +06:00
renovate[bot]
c0f9de88e7
fix(deps): update dependency io.coil-kt.coil3:coil-bom to v3.0.0-alpha07 (#960)
* fix(deps): update dependency io.coil-kt.coil3:coil-bom to v3.0.0-alpha07

* Fix build

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-30 01:44:17 +06:00
renovate[bot]
80cdebcdf4
fix(deps): update aboutlib.version to v11.2.2 (#965)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-29 23:26:00 +06:00
renovate[bot]
9e2f97eeb8
fix(deps): update dependency org.junit.jupiter:junit-jupiter to v5.10.3 (#962)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-28 17:59:49 +06:00
CrepeTF
e132cc405f
Theme fixes (#963)
* Fix theme issue with download progress indicator

* Fix theme issue with download progress indicator + better contrast
2024-06-28 17:59:32 +06:00
Caio Oliveira
2674b84974
buildSrc: Fix strange warning in ci build (#952)
* buildSrc: Fix strange warning

´Project accessors enabled, but root project name not explicitly set for 'buildSrc'. Checking out the project in different folders will impact the generated code and implicitly the buildscript classpath, breaking caching.´

* Update settings.gradle.kts

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-27 11:50:30 +06:00
renovate[bot]
f34702d4fc
fix(deps): update dependency androidx.test.espresso:espresso-core to v3.6.1 (#958)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-27 11:50:11 +06:00
renovate[bot]
7823966ddf
fix(deps): update dependency androidx.test.ext:junit-ktx to v1.2.1 (#959)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-27 11:48:58 +06:00
renovate[bot]
2d41bf5589
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.06.00-alpha01 (#957)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-27 03:42:32 +06:00
renovate[bot]
d8fe7d32ca
fix(deps): update serialization.version to v1.7.1 (#951)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-27 03:30:34 +06:00
Maddie Witman
2f86f25d5b
Added configuration options to e-ink page flashes (#625)
* Recommit for e-ink pref changes

* Fixed state holder for flash interval

* Detekt

* Refactor suggested by Antsy

* inverted currentDisplayRefresh check for early exit
2024-06-27 02:04:28 +06:00
FooIbar
239c38982c
Refactor archive support with libarchive (#949)
* Refactor archive support with libarchive

* Revert string resource changs

* Only mark archive formats as supported

Comic book archives should not be compressed.

* Fixup

* Remove epub from archive format list

* Move to mihon package

* Format

* Cleanup
2024-06-26 20:54:25 +06:00
renovate[bot]
36e40c0997
fix(deps): update dependency androidx.test.ext:junit-ktx to v1.2.0 (#948)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-25 07:49:12 +06:00
renovate[bot]
40754659a9
fix(deps): update dependency androidx.test.espresso:espresso-core to v3.6.0 (#947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-25 07:05:44 +06:00
AntsyLich
a41ea8a61d
[skip ci] remove unused github workflow 2024-06-24 19:28:25 +06:00
FooIbar
5c249dd790
Upload build artifacts (#941)
To decode obfuscated stack traces and help debugging R8 issues.
2024-06-23 08:04:30 +06:00
AntsyLich
e17f70f722
Cleanup in CommonMangaItem.kt
Closes #19

Co-authored-by: Roshan Varughese <40583749+Animeboynz@users.noreply.github.com>
2024-06-23 05:00:26 +06:00
Tran M. Cuong
e57638a49c
Fix Migrator test and also add the test to build script (#896)
* Fix MigratorTest after update to Kotlin 2.0.0

* add main module's test to build script
2024-06-23 04:05:44 +06:00
FooIbar
0ce1cf22cd
Fix unexpected skips in strong skipping mode (#940) 2024-06-23 03:53:49 +06:00
AntsyLich
4ed2062cab
Update build_pull_request.yml paths-ignore 2024-06-23 03:40:17 +06:00
renovate[bot]
f6ec53cdde
fix(deps): update dependency io.github.fornewid:material-motion-compose-core to v2.0.1 (#945)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-23 03:35:12 +06:00
renovate[bot]
b37357f909
fix(deps): update dependency com.google.firebase:firebase-analytics to v22.0.2 (#936)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-21 03:21:27 +06:00
renovate[bot]
f58a05e918
fix(deps): update moko to v0.24.1 (#933)
* fix(deps): update moko to v0.24.1

* Fix build

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-21 02:43:48 +06:00
Weblate (bot)
cf02119da5
Translations update from Hosted Weblate (#904)
* Translated using Weblate (Malayalam)

Currently translated at 16.9% (136 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ml/

* Translated using Weblate (Swedish)

Currently translated at 99.1% (797 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sv/

* Translated using Weblate (Arabic)

Currently translated at 99.5% (800 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ar/

* Translated using Weblate (Swedish)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sv/

* Translated using Weblate (Swedish)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/sv/

---------

Co-authored-by: Akhil Raj <akhilakae07@gmail.com>
Co-authored-by: Norsze <norbert.szabo7+github@gmail.com>
Co-authored-by: Duh051 <duhduh272@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
2024-06-21 02:24:22 +06:00
renovate[bot]
5e2a3ee927
chore(deps): update softprops/action-gh-release action to v2.0.6 (#929)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-21 01:41:26 +06:00
renovate[bot]
3b8ed3059a
chore(deps): update gradle/actions action to v3.4.2 (#924)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-18 05:08:07 +06:00
FooIbar
4182ae89a0
Fix R8 version configuration not working (#916)
This reverts commit f3226fb278.
2024-06-17 04:53:02 +06:00
FooIbar
f3226fb278
Update R8 to fix NoSuchMethodError crash (#914) 2024-06-16 14:48:02 +06:00
renovate[bot]
30a6e3a6a1
chore(deps): update gradle/actions action to v3.4.1 (#905)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-16 04:47:39 +06:00
renovate[bot]
2e78bceb30
fix(deps): update dependency com.android.tools.build:gradle to v8.5.0 (#901)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-14 05:06:11 +06:00
renovate[bot]
a5838387b1
chore(deps): update gradle/actions action to v3.4.0 (#902)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-14 05:05:57 +06:00
Weblate (bot)
aa1714b2ac
Translations update from Hosted Weblate (#878)
* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Croatian)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/

* Translated using Weblate (Malayalam)

Currently translated at 15.5% (125 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ml/

* Translated using Weblate (Malayalam)

Currently translated at 15.5% (125 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ml/

* Translated using Weblate (Malayalam)

Currently translated at 94.4% (17 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ml/

---------

Co-authored-by: ɴᴇᴋᴏ <s99095lkjjim@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Akhil Raj <akhilakae07@gmail.com>
Co-authored-by: Animeboynz <roshanvarughese@hotmail.com>
2024-06-13 03:34:04 +06:00
AntsyLich
f696f209c6
Fix issue with creating and restoring backup
Fixes #881
2024-06-13 03:27:52 +06:00
AntsyLich
9fa22f0b37
Migrate to gradle/actions/wrapper-validation (#892) 2024-06-13 02:45:55 +06:00
renovate[bot]
6d8cfd5f30
chore(deps): update actions/checkout action to v4.1.7 (#891)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 02:31:28 +06:00
renovate[bot]
af57e124f2
fix(deps): update dependency androidx.glance:glance-appwidget to v1.1.0 (#890)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 02:21:15 +06:00
renovate[bot]
8e8ee69bba
fix(deps): update lifecycle.version to v2.8.2 (#889)
fix(deps): update dependency androidx.lifecycle:lifecycle-runtime-ktx to v2.8.2

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-13 02:21:02 +06:00
renovate[bot]
e9d69a83fe
fix(deps): update dependency com.android.tools.build:gradle to v8.4.2 (#883)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-11 14:51:28 +06:00
AntsyLich
6a80305d6c
Fix chapter number parsing when number is after unwanted tag
Fixes #554

Co-authored-by: Naputt1 <94742489+Naputt1@users.noreply.github.com>
2024-06-08 07:07:47 +06:00
AntsyLich
119bcbf8ed
Check category order before restoring from backup
Closes #632

Co-authored-by: Cologler <10906962+Cologler@users.noreply.github.com>
2024-06-08 06:38:35 +06:00
Weblate (bot)
87fe64468c
Translations update from Hosted Weblate (#611)
* Translated using Weblate (Malayalam)

Currently translated at 12.9% (104 of 803 strings)

Translated using Weblate (Malayalam)

Currently translated at 94.4% (17 of 18 strings)

Translated using Weblate (Malayalam)

Currently translated at 11.8% (95 of 803 strings)

Added translation using Weblate (Malayalam)

Added translation using Weblate (Malayalam)

Co-authored-by: Akhil Raj <akhilakae07@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ml/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ml/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals

* Translated using Weblate (Italian)

Currently translated at 99.6% (800 of 803 strings)

Co-authored-by: Federico Pierantoni <federico.pieranton@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/
Translation: Mihon/Mihon

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/
Translation: Mihon/Mihon

* Translated using Weblate (Javanese)

Currently translated at 38.7% (311 of 803 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (803 of 803 strings)

Translated using Weblate (Indonesian)

Currently translated at 98.7% (793 of 803 strings)

Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/id/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/jv/
Translation: Mihon/Mihon

* Translated using Weblate (Greek)

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/
Translation: Mihon/Mihon

* Translated using Weblate (Serbian)

Currently translated at 99.2% (797 of 803 strings)

Co-authored-by: Rikishaaa <jebote90@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sr/
Translation: Mihon/Mihon

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: Blackiezin <mcperenan134@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt_BR/
Translation: Mihon/Mihon

* Translated using Weblate (French)

Currently translated at 100.0% (18 of 18 strings)

Translated using Weblate (French)

Currently translated at 99.0% (795 of 803 strings)

Co-authored-by: LaQuiche426 <loic.dossantos42630@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/fr/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fr/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals

* Translated using Weblate (Portuguese)

Currently translated at 99.8% (802 of 803 strings)

Co-authored-by: ssantos <ssantos@web.de>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt/
Translation: Mihon/Mihon

* Translated using Weblate (Vietnamese)

Currently translated at 100.0% (18 of 18 strings)

Translated using Weblate (Vietnamese)

Currently translated at 96.8% (778 of 803 strings)

Co-authored-by: Karuto <nguyenthaison609@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/vi/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/vi/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals

* Translated using Weblate (Croatian)

Currently translated at 99.5% (799 of 803 strings)

Co-authored-by: Milo Ivir <mail@milotype.de>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/
Translation: Mihon/Mihon

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: Eji-san <ejierubani@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/id/
Translation: Mihon/Mihon

* Translated using Weblate (Galician)

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: kevans <albapazpi@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/
Translation: Mihon/Mihon

* Translated using Weblate (Ukrainian)

Currently translated at 99.8% (802 of 803 strings)

Co-authored-by: Kodekiro Kodekihara <lolbitoklol@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/uk/
Translation: Mihon/Mihon

* Translated using Weblate (Malay)

Currently translated at 98.6% (792 of 803 strings)

Co-authored-by: Farith <mail2@farithadnan.net>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ms/
Translation: Mihon/Mihon

* Translated using Weblate (Nepali)

Currently translated at 100.0% (18 of 18 strings)

Translated using Weblate (Nepali)

Currently translated at 100.0% (803 of 803 strings)

Co-authored-by: FateXBlood <fatexblood@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ne/
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/
Translation: Mihon/Mihon
Translation: Mihon/Mihon Plurals

* Translated using Weblate (Vietnamese)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/vi/

* Translated using Weblate (Croatian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/es/

* Translated using Weblate (Romanian)

Currently translated at 99.6% (800 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ro/

* Translated using Weblate (Romanian)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ro/

* Translated using Weblate (Italian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/

* Translated using Weblate (Polish)

Currently translated at 99.5% (799 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pl/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (German)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Russian)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (French)

Currently translated at 99.5% (800 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fr/

* Translated using Weblate (Filipino)

Currently translated at 99.8% (803 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (Nepali)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ca/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (804 of 804 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ca/

---------

Co-authored-by: Akhil Raj <akhilakae07@gmail.com>
Co-authored-by: Federico Pierantoni <federico.pieranton@gmail.com>
Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Co-authored-by: Rikishaaa <jebote90@gmail.com>
Co-authored-by: Blackiezin <mcperenan134@gmail.com>
Co-authored-by: LaQuiche426 <loic.dossantos42630@gmail.com>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: Karuto <nguyenthaison609@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Eji-san <ejierubani@gmail.com>
Co-authored-by: kevans <albapazpi@gmail.com>
Co-authored-by: Kodekiro Kodekihara <lolbitoklol@gmail.com>
Co-authored-by: Farith <mail2@farithadnan.net>
Co-authored-by: FateXBlood <fatexblood@gmail.com>
Co-authored-by: Nguyễn Trung Đức <vaicato16@gmail.com>
Co-authored-by: Chrono Lux <amber_c001@protonmail.com>
Co-authored-by: Saft Octavian <saftoctavian@gmail.com>
Co-authored-by: Giorgio Sanna <sannagiorgio1997@gmail.com>
Co-authored-by: sebastians17 <sebastians117.ss@gmail.com>
Co-authored-by: Tim Schneeberger <thebone.main@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: Naga <yz2000.pro@gmail.com>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: Eduard Ereza Martínez <eduard@ereza.cat>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
2024-06-07 19:30:00 +06:00
renovate[bot]
bdce3c39f1
fix(deps): update dependency io.github.fornewid:material-motion-compose-core to v2 (#873)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-07 14:58:19 +06:00
AntsyLich
15d999229f
MangaChapterListItem: Don't use alpha modifier
Possibly fixes #822

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-06-07 04:31:42 +06:00
renovate[bot]
1edd55c981
fix(deps): update okhttp monorepo to v5.0.0-alpha.14 (#688)
* fix(deps): update okhttp monorepo to v5.0.0-alpha.14

* Fix build

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-07 04:26:25 +06:00
renovate[bot]
777a071f4a
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.05.00-alpha03 (#843)
* fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.05.00-alpha03

* Fix build

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-07 04:23:27 +06:00
renovate[bot]
71b558cb34
fix(deps): update serialization.version to v1.7.0 (#870)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-07 03:58:55 +06:00
renovate[bot]
46003ec251
chore(deps): update kotlin and compose compiler to v2 (major) (#819)
* chore(deps): update kotlin and compose compiler to v2

* Update .gitignore

* Fix build

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-07 03:48:35 +06:00
renovate[bot]
e8fdfaad64
chore(deps): update actions/dependency-review-action action to v4.3.3 (#867)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-07 03:35:50 +06:00
renovate[bot]
1f7574bd4f
fix(deps): update dependency io.kotest:kotest-assertions-core to v5.9.1 (#869)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-07 03:35:38 +06:00
Cuong M. Tran
da62c7a21a
Fix MigratorTest after update to io.mockk v1.13.11 (#814)
* Fix MigratorTest after update to io.mockk v1.13.11

Causing error: io.mockk.MockKException: was not can only be called on a mocked object

* remove import
2024-06-07 03:35:26 +06:00
renovate[bot]
0870cffba1
fix(deps): update dependency io.github.fornewid:material-motion-compose-core to v1.2.1 (#858)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-02 15:20:56 +06:00
Sven
8632ba85ee
fix: storage permission request for non-conforming devices (#726)
* fix: storage permission request for non-conforming devices

* fix: catch more specific exception

* chore: add toast message to indicate missing persistent permissions

* chore: correct newly introduced translaction string

* Change error toast message

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-06-02 01:25:58 +06:00
renovate[bot]
116579d38c
chore(deps): update dependency gradle to v8.8 (#856)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-02 01:23:39 +06:00
renovate[bot]
098f925519
fix(deps): update dependency androidx.test.ext:junit-ktx to v1.2.0-rc01 (#855)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-02 01:23:31 +06:00
renovate[bot]
9f5db70572
fix(deps): update aboutlib.version to v11.2.1 (#846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 22:03:20 +06:00
renovate[bot]
1f286f1a35
fix(deps): update dependency com.google.firebase:firebase-analytics to v22.0.1 (#848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 22:03:10 +06:00
renovate[bot]
7ab7f5ac37
fix(deps): update dependency com.google.gms:google-services to v4.4.2 (#849)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 22:03:03 +06:00
renovate[bot]
e567250b17
fix(deps): update dependency androidx.test.espresso:espresso-core to v3.6.0-rc01 (#851)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-01 22:02:54 +06:00
renovate[bot]
095da924b9
fix(deps): update dependency androidx.appcompat:appcompat to v1.7.0 (#845)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-30 05:07:22 +06:00
renovate[bot]
b9da98b527
fix(deps): update lifecycle.version to v2.8.1 (#844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-30 05:07:08 +06:00
renovate[bot]
af8696cb90
fix(deps): update paging.version to v3.3.0 (#810)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-27 02:05:53 +06:00
renovate[bot]
de5a64aa73
fix(deps): update dependency org.apache.commons:commons-compress to v1.26.2 (#826)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-27 02:05:40 +06:00
renovate[bot]
9b944092c7
fix(deps): update aboutlib.version to v11.2.0 (#823)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-27 02:05:26 +06:00
renovate[bot]
0cb1794a44
fix(deps): update dependency com.android.tools.build:gradle to v8.4.1 (#818)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-22 13:45:53 +06:00
renovate[bot]
2f243fae11
chore(deps): update kotlin and compose compiler (#800)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:14:12 +06:00
renovate[bot]
d2e5c78074
fix(deps): update lifecycle.version to v2.8.0 (#809)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:12:27 +06:00
renovate[bot]
5912d6b08f
fix(deps): update dependency androidx.annotation:annotation to v1.8.0 (#808)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:12:16 +06:00
renovate[bot]
99b550ae0d
fix(deps): update dependency io.mockk:mockk to v1.13.11 (#803)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:03:52 +06:00
renovate[bot]
8d187f7865
fix(deps): update dependency androidx.test.ext:junit-ktx to v1.2.0-beta01 (#801)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:03:38 +06:00
renovate[bot]
653d5d3e25
fix(deps): update dependency com.google.android.material:material to v1.12.0 (#754)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:03:05 +06:00
renovate[bot]
1dca9363a4
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.05.00-alpha02 (#802)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-18 23:02:46 +06:00
AntsyLich
fffa6a462d
Fix renovate config 2024-05-18 23:00:29 +06:00
renovate[bot]
ce497003e3
fix(deps): update dependency androidx.test.espresso:espresso-core to v3.6.0-beta01 (#797)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-17 16:09:36 +06:00
renovate[bot]
84ea5166de
chore(deps): update actions/checkout action to v4.1.6 (#796)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-17 16:09:21 +06:00
AntsyLich
0392ef0d18
Update renovate config 2024-05-17 16:06:23 +06:00
CrepeTF
16392adcbb
Update themes to follow new compose update changes (#766)
* Update Green Apple theme

* Add some Green Apple theme comments

* Update Lavender theme

* Update Midnight Dusk theme

* Update Nord theme

* Update Strawberry Daiquiri theme

* Update Tako theme

* Update Teal & Turquoise theme

* Update Lavender secondaryContainer and onSecondaryContainer colour

* Update M.Dusk secondaryContainer and onSecondaryContainer colour

* Update Tako secondaryContainer and onSecondaryContainer colour

* Comments

* Update Tidal Wave theme

* Update Yin Yang theme

* Update Yotsuba theme

* Fix navbar tinted background on pure black

* Add surfaceContainer levels to Lavender theme

* Resolve detekt issues

* Add surfaceContainer levels to Midnight Dusk theme

* Add surfaceContainer levels to Nord theme

* Add surfaceContainer levels to Tako theme

* Add surfaceContainer levels to Teal & Turquoise theme

* Add surfaceContainer levels to Tidal Wave theme

* Add surfaceContainer levels to Yin Yang theme

* Add surfaceContainer levels to Yotsuba theme

* Add dark theme surfaceContainer levels to Yotsuba theme

* surfaceContainer tweaks to Yotsuba theme

* surfaceContainer tweaks to Strawberry Daiquiri theme

* surfaceContainer tweaks to Nord theme

* surfaceContainer tweaks to Lavender theme

* Update Tachiyomi theme

* Update Pure Black theme

* Resolve detekt issues

* Oopsie
2024-05-14 02:44:40 +06:00
AwkwardPeak7
f603db3f3f
update r8 rules for MultipartBody.Builder in extensions (#783) 2024-05-11 15:15:02 +06:00
renovate[bot]
ab546e0884
fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-coroutines-bom to v1.8.1 (#778)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-10 20:25:59 +06:00
renovate[bot]
d3306e8cfe
fix(deps): update dependency io.kotest:kotest-assertions-core to v5.9.0 (#774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-10 12:52:40 +06:00
renovate[bot]
aebb86794a
chore(deps): update softprops/action-gh-release action to v2.0.5 (#773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-10 12:52:18 +06:00
renovate[bot]
9a62e4fba3
chore(deps): update actions/checkout action to v4.1.5 (#771)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-10 12:52:05 +06:00
AntsyLich
5955c9c311
Update project icon 2024-05-08 23:06:35 +06:00
AntsyLich
fb9423028e
Remove dependency on compose material 2 components 2024-05-07 15:53:58 +06:00
FooIbar
8e9396a9cf
Fix tap control area shifting after zooming out (#767) 2024-05-07 15:13:43 +06:00
AntsyLich
1df87eabf2
Use new SurfaceContainer color roles
Non-dynamic themes need to be updated

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-05-07 15:03:48 +06:00
AntsyLich
ca7391bbf3
Fix search bar style 2024-05-07 15:03:32 +06:00
Reagan
550f1197e8
Change keyboard type in extension repo dialog (#764) 2024-05-05 16:23:09 +06:00
AntsyLich
dbcc4a7d71
Revert "Fix badge count getting cut off on tab title"
This reverts commit 263e467cde.
2024-05-05 03:31:50 +06:00
AntsyLich
e473c7f09f
Bump compose version
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-05-05 01:55:23 +06:00
AntsyLich
263e467cde
Fix badge count getting cut off on tab title
Fixes #335
2024-05-05 01:55:23 +06:00
Radon Rosborough
7ec2108812
Massively improve findFile performance (#728)
* Massively improve findFile performance

* Update libs.versions.toml

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-05-04 22:40:41 +06:00
AntsyLich
e55e5f6f64
Remove some legacy folder/file name lookup for download
Related to #705
2024-05-04 22:27:51 +06:00
AntsyLich
28dca3b7b8
Address firebase ktx module deprecation 2024-05-04 16:31:08 +06:00
AntsyLich
70cd688ac2
Trust extension by repo (#570) 2024-05-04 16:26:45 +06:00
AntsyLich
21145144cd
Fix some extension related issue and cleanups
- Extension being marked as not installed instead of untrusted after updating with private installer
- Extension update counter not updating due to extension being marked as untrusted
- Minimize `Key "extension-XXX-YYY" was already used` crash
2024-05-04 16:08:38 +06:00
AntsyLich
134e4648a9
Revert "fix(deps): update dependency androidx.compose.compiler:compiler to v1.5.13 (#745)"
This reverts commit 4e5cbbc96b.
2024-05-04 13:33:12 +06:00
renovate[bot]
fa6dba6cc7
fix(deps): update leakcanary to v2.14 (#715)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 19:34:33 +06:00
renovate[bot]
8a51d56c59
fix(deps): update dependency com.android.tools.build:gradle to v8.4.0 (#753)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 19:08:36 +06:00
renovate[bot]
47ee2b45a8
chore(deps): update actions/dependency-review-action action to v4.3.2 (#752)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:22:13 +06:00
renovate[bot]
a2f7d47a0a
fix(deps): update dependency androidx.test.espresso:espresso-core to v3.6.0-alpha04 (#749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:21:52 +06:00
renovate[bot]
4e5cbbc96b
fix(deps): update dependency androidx.compose.compiler:compiler to v1.5.13 (#745)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:21:08 +06:00
renovate[bot]
b720f34267
fix(deps): update dependency androidx.core:core-ktx to v1.13.1 (#748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:20:46 +06:00
renovate[bot]
c6a1412f18
fix(deps): update dependency androidx.test.ext:junit-ktx to v1.2.0-alpha04 (#751)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:20:16 +06:00
renovate[bot]
6290cf222d
fix(deps): update aboutlib.version to v11.1.4 (#744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-03 14:19:59 +06:00
FooIbar
a3d438e2f5
Log app crash exceptions in dumped crash logs (#742) 2024-05-03 00:59:29 +06:00
w
80461d883f
Update subsampling-scale-image-view (#687)
Update libs.versions.toml
2024-05-01 13:09:19 +06:00
FooIbar
c3e7bb12f4
Use Coil pipeline instead of SSIV for image decode (#692) 2024-05-01 13:07:30 +06:00
AntsyLich
2ad98520aa
Revert "fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.04.00-alpha02 (#714)"
This reverts commit f1ce205d00.
2024-04-26 19:04:49 +06:00
renovate[bot]
f1ce205d00
fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.04.00-alpha02 (#714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 14:50:52 +06:00
renovate[bot]
5289830a84
chore(deps): update gradle/wrapper-validation-action action to v3.3.2 (#713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 14:50:41 +06:00
renovate[bot]
dd932e1362
chore(deps): update gradle/actions action to v3.3.2 (#711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 14:50:29 +06:00
renovate[bot]
e85ce6456a
chore(deps): update actions/checkout action to v4.1.4 (#710)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-26 14:50:15 +06:00
MajorTanya
9a3ffe2ea6
Add MyAnimeList issue autoclose (#703)
[skip ci] Add MyAnimeList issue autoclose

This rule is intended to automatically close issues that report
problems with linking MAL that would be solved with the standard
solution of updating & changing the default UA.

The RegEx might be too general, but there isn't any neat pattern in
the previously filed issues.
2024-04-23 11:38:16 +06:00
renovate[bot]
213effa169
fix(deps): update dependency androidx.compose.compiler:compiler to v1.5.12 (#685)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:54:26 +06:00
renovate[bot]
25570147a1
fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.4 (#684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:54:09 +06:00
renovate[bot]
e82a2f5f9f
chore(deps): update gradle/wrapper-validation-action action to v3.3.1 (#683)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:53:55 +06:00
renovate[bot]
935c0c7e2e
chore(deps): update gradle/actions action to v3.3.1 (#682)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:53:35 +06:00
renovate[bot]
2ad462b4d8
fix(deps): update dependency androidx.activity:activity-compose to v1.9.0 (#689)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:53:19 +06:00
renovate[bot]
7fd8f65352
fix(deps): update dependency androidx.core:core-ktx to v1.13.0 (#690)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-20 10:52:56 +06:00
FooIbar
b152e3881b
Use Okio instead of java.io for image processing (#691) 2024-04-20 10:52:40 +06:00
FooIbar
f27ca3b1b2
Use m3 ripple and clean up interactionSource usage (#675)
Also remove a leftover of scoped storage adaptation.
2024-04-17 13:21:24 +06:00
FooIbar
843daa5304
Update compose bom and fix renovate config for it (#674) 2024-04-17 13:21:09 +06:00
renovate[bot]
f080a4937e
fix(deps): update dependency com.google.firebase:firebase-analytics-ktx to v21.6.2 (#656)
Update dependency com.google.firebase:firebase-analytics-ktx to v21.6.2

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-13 21:57:21 +06:00
renovate[bot]
8bba926891
chore(deps): update gradle/actions action to v3.3.0 (#659)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-13 21:56:30 +06:00
renovate[bot]
5378c4c5d6
chore(deps): update gradle/wrapper-validation-action action to v3 (#661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-13 21:55:56 +06:00
renovate[bot]
c94d212ef4
chore(deps): update gradle/wrapper-validation-action action to v2.1.3 (#658)
Update gradle/wrapper-validation-action action to v2.1.3

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-12 13:21:30 +06:00
renovate[bot]
4c43a0ef66
Update aboutlib.version to v11.1.3 (#654)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-12 12:57:35 +06:00
renovate[bot]
ea0fe2414e
Update dependency com.android.tools.build:gradle to v8.3.2 (#655)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-12 12:57:10 +06:00
renovate[bot]
015620711d
Update gradle/actions action to v3.2.1 (#657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-12 12:56:45 +06:00
AntsyLich
6d4267b3bb
Merge branch 'release/v0.16.5' 2024-04-09 16:02:21 +06:00
AntsyLich
2a01a2ac6b
Release v0.16.5 2024-04-09 14:17:04 +06:00
AntsyLich
9a6559b013
Remove unused imports 2024-04-09 14:17:04 +06:00
AntsyLich
a7509b3a3c
Fix build time zone in about screen
And slight cleanup
2024-04-09 14:17:04 +06:00
renovate[bot]
2755d1f35e
chore(deps): update dependency gradle to v8.7 (#567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-09 14:17:04 +06:00
AntsyLich
6a8a9c6bbf
Address detekt issues 2024-04-09 14:17:04 +06:00
w
7862088b94
Update image-decoder, color management (#523)
* Update image-decoder, color management

* move display profile pref

* remove true color pref

* Move Display Profile settings to a new section

* Partially revert "remove true color pref"

This partially reverts commit e1a7581695.

* Tweak label

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-04-09 14:12:49 +06:00
MajorTanya
35f8eda8c5
Switch to seconds for DATE_MODIFIED of saved pages (#552)
While most Android skins are seemingly able to handle the millisecond
format, the documentation technically specifies seconds. This seems to
be causing issues on Samsung devices using the Samsung Gallery app,
which renders the millisecond timestamps as if they were second ones,
causing the dates to be set at some point in the year 56189.

This change should fix that issue on Samsung devices and have no real
impact on the rest.
2024-04-09 14:04:22 +06:00
AntsyLich
fa6fa1f53a
Disable SerialVersionUIDInSerializableClass detekt rule 2024-04-09 14:04:21 +06:00
AntsyLich
c348fac78f
Fix crash in track date selection dialog
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-04-09 14:04:21 +06:00
AntsyLich
ab06720966
Upgrade Compose 2024-04-09 13:23:43 +06:00
Maddie Witman
42ebf017e4
Fix some issues from 7ff95e2 (#415)
* Fixed extra header introduced in 7ff95e2

* Removed parentheses to make detekt happy

* Updated relative date display for dates in the future

* Small cleanup for header creation logic

* replaced "and" with "&&" for better formatting
2024-04-09 13:23:43 +06:00
MajorTanya
3910ffdd9e
Fix DelayedTrackingUpdateJob spam on update errors (#411)
* Fix DelayedTrackingUpdateJob spam on update errors

DelayedTrackingUpdateJob would start spamming when it encountered an
error (e.g. a tracker has an issue) and never stop.
This seems to stem from a circular dependency between the Job's
`doWork` and TrackChapter's `await`.

TrackChapter sets up a completely new instance of the
DelayedTrackingUpdateJob if any Exception was thrown during the track
update.

This causes the Job to get replaced (as per the WorkManager's set
ExistingWorkPolicy).

Because of this, the guard clause at the start of doWork would never
trigger, as all instances of the Job would report being the 0th try
(because they were completely new instances).

This simple fix introduces a boolean `isRetry` parameter to
TrackChapter's await method, which is set to `false` by default.
DelayedTrackingUpdateJob however sets this parameter to `true`, which
means TrackChapter won't try to set up the Job again.

* Rename isRetry parameter to setupJobOnFailure

This also inverts the logic, so true & false were swapped.
2024-04-09 13:23:43 +06:00
AntsyLich
0bfacf5570
Tweak detekt config 2024-04-09 13:23:42 +06:00
AntsyLich
1e28999e13
Revert a mishap in 7ff95e21ba 2024-04-09 13:23:42 +06:00
AntsyLich
1ee54d74a4
Ignore detekt [LongParameterList] for composables 2024-04-09 13:23:42 +06:00
Maddie Witman
a1a52ae81a
Refactor use of Java.util.date to Java.time.*, to fix localized date issues. (#402)
* Add support for localdate based relative times

* Update History Screen to use new localdate based relative times

* Update Updates Screen to use new localdate based relative times

* Cleaned up date util classes

* Updated build time display

* Code cleanup

* Fixed crash in settings

* Updated Preferences item

* Worker Info works

* Fixed Tracker date display

* Code changes to pass detekt
2024-04-09 13:23:42 +06:00
AntsyLich
56e66e041d
Revert "Update Scaffold fork (#10143)" + Cleanup
Causes delay of one frame before actual contentPadding is measured

This reverts commit ea15bc782a.

Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-04-08 17:12:56 +06:00
AntsyLich
13656959ae
MangaCoverFetcher: Small cleanups
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
2024-04-08 17:12:56 +06:00
AntsyLich
20e4cb26d6
Remove unused imports 2024-04-06 12:21:25 +06:00
AntsyLich
e448e40406
Rework buildSrc and remove usage of subprojects 2024-04-06 12:18:10 +06:00
AntsyLich
aed53d3bdc
Fix build time zone in about screen
And slight cleanup
2024-04-06 11:41:39 +06:00
renovate[bot]
d77f2f429d
fix(deps): update sqldelight to v2.0.2 (#544)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-06 09:47:44 +06:00
AntsyLich
c3fd2df6f5
Disable mpp and agp compability warning 2024-04-06 08:39:32 +06:00
renovate[bot]
f5a41e9693
chore(deps): update gradle/actions action to v3.2.0 (#621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-05 06:20:12 +06:00
Weblate (bot)
34bf5c6f87
Translations update from Hosted Weblate (#609)
* Translated using Weblate (Greek)

Currently translated at 99.8% (793 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/tr/

* Translated using Weblate (German)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/de/

* Translated using Weblate (Persian)

Currently translated at 84.7% (673 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fa/

* Translated using Weblate (German)

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Greek)

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/pt_BR/

* Translated using Weblate (Galician)

Currently translated at 95.9% (762 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/

* Translated using Weblate (Japanese)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ja/

* Translated using Weblate (Javanese)

Currently translated at 38.8% (7 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/jv/

* Translated using Weblate (Galician)

Currently translated at 96.5% (767 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/

* Translated using Weblate (Galician)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/gl/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Croatian)

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Russian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Russian)

Currently translated at 99.7% (796 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Filipino)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (German)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Japanese)

Currently translated at 99.4% (794 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Czech)

Currently translated at 99.8% (797 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cs/

* Translated using Weblate (Italian)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/

* Translated using Weblate (Nepali)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/

* Translated using Weblate (Czech)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/cs/

* Translated using Weblate (Italian)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/it/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Russian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Filipino)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (German)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Amharic)

Currently translated at 34.3% (276 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/am/

* Translated using Weblate (Arabic)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ar/

* Translated using Weblate (Belarusian)

Currently translated at 42.0% (338 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/be/

* Translated using Weblate (Bulgarian)

Currently translated at 79.8% (641 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/bg/

* Translated using Weblate (Bengali)

Currently translated at 79.2% (636 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/bn/

* Translated using Weblate (Catalan)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ca/

* Translated using Weblate (Cebuano)

Currently translated at 55.0% (442 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ceb/

* Translated using Weblate (Czech)

Currently translated at 99.2% (797 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cs/

* Translated using Weblate (Chuvash)

Currently translated at 74.5% (599 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cv/

* Translated using Weblate (Danish)

Currently translated at 39.9% (321 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/da/

* Translated using Weblate (German)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Greek)

Currently translated at 98.6% (792 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/

* Translated using Weblate (Esperanto)

Currently translated at 64.2% (516 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/eo/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Basque)

Currently translated at 74.4% (598 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/eu/

* Translated using Weblate (Persian)

Currently translated at 83.5% (671 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fa/

* Translated using Weblate (Finnish)

Currently translated at 84.0% (675 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fi/

* Translated using Weblate (Filipino)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (French)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fr/

* Translated using Weblate (Galician)

Currently translated at 95.2% (765 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/

* Translated using Weblate (Hebrew)

Currently translated at 89.7% (721 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/he/

* Translated using Weblate (Hindi)

Currently translated at 82.6% (664 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hi/

* Translated using Weblate (Croatian)

Currently translated at 98.7% (793 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Indonesian)

Currently translated at 98.6% (792 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/id/

* Translated using Weblate (Italian)

Currently translated at 99.3% (798 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Javanese)

Currently translated at 38.3% (308 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/jv/

* Translated using Weblate (Georgian)

Currently translated at 52.5% (422 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ka/

* Translated using Weblate (Kazakh)

Currently translated at 86.1% (692 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/kk/

* Translated using Weblate (Khmer (Central))

Currently translated at 26.7% (215 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/km/

* Translated using Weblate (Kannada)

Currently translated at 62.2% (500 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/kn/

* Translated using Weblate (Korean)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ko/

* Translated using Weblate (Lithuanian)

Currently translated at 84.9% (682 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/lt/

* Translated using Weblate (Latvian)

Currently translated at 93.3% (750 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/lv/

* Translated using Weblate (Marathi)

Currently translated at 26.6% (214 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/mr/

* Translated using Weblate (Malay)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ms/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nb_NO/

* Translated using Weblate (Nepali)

Currently translated at 99.3% (798 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/

* Translated using Weblate (Dutch)

Currently translated at 92.9% (746 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nl/

* Translated using Weblate (Norwegian Nynorsk)

Currently translated at 33.6% (270 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/nn/

* Translated using Weblate (Polish)

Currently translated at 98.6% (792 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pl/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 98.6% (792 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt_BR/

* Translated using Weblate (Portuguese)

Currently translated at 88.6% (712 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt/

* Translated using Weblate (Romanian)

Currently translated at 97.8% (786 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ro/

* Translated using Weblate (Russian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Sanskrit)

Currently translated at 71.3% (573 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sa/

* Translated using Weblate (Yakut)

Currently translated at 51.3% (412 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sah/

* Translated using Weblate (Sardinian)

Currently translated at 93.3% (750 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sc/

* Translated using Weblate (Kurdish (Southern))

Currently translated at 29.8% (240 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sdh/

* Translated using Weblate (Slovak)

Currently translated at 78.7% (632 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sk/

* Translated using Weblate (Albanian)

Currently translated at 86.6% (696 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sq/

* Translated using Weblate (Serbian)

Currently translated at 98.6% (792 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sr/

* Translated using Weblate (Swedish)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/sv/

* Translated using Weblate (Telugu)

Currently translated at 24.5% (197 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/te/

* Translated using Weblate (Thai)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/th/

* Translated using Weblate (Turkish)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/tr/

* Translated using Weblate (Ukrainian)

Currently translated at 98.5% (791 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/uk/

* Translated using Weblate (Uzbek)

Currently translated at 44.4% (357 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/uz/

* Translated using Weblate (Vietnamese)

Currently translated at 96.3% (774 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/vi/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Update translation files

Updated by "Remove blank strings" hook in Weblate.

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/

---------

Co-authored-by: Syrodil Eventalious <giannis.yalanskyi@gmail.com>
Co-authored-by: NukeSource <dede48076@gmail.com>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
Co-authored-by: Arash <ara.khoram95@gmail.com>
Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Co-authored-by: Mr. Fakezay <fakezaydev@gmail.com>
Co-authored-by: kevans <albapazpi@gmail.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: gekka <1778962971@qq.com>
Co-authored-by: akir45 <akkn0708@gmail.com>
Co-authored-by: Matyáš Caras <matyas@caras.cafe>
Co-authored-by: Federico Pierantoni <federico.pieranton@gmail.com>
Co-authored-by: FateXBlood <zecrofelix@gmail.com>
2024-04-01 08:04:30 +06:00
Weblate (bot)
6abaa47f5b
Translations update from Hosted Weblate (#508)
* Translated using Weblate (Greek)

Currently translated at 99.8% (793 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/tr/

* Translated using Weblate (German)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/de/

* Translated using Weblate (Persian)

Currently translated at 84.7% (673 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fa/

* Translated using Weblate (German)

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Greek)

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/el/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (794 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/pt_BR/

* Translated using Weblate (Galician)

Currently translated at 95.9% (762 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/

* Translated using Weblate (Japanese)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/ja/

* Translated using Weblate (Javanese)

Currently translated at 38.8% (7 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/jv/

* Translated using Weblate (Galician)

Currently translated at 96.5% (767 of 794 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/gl/

* Translated using Weblate (Galician)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/gl/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Croatian)

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hr/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (793 of 793 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Russian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (795 of 795 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Russian)

Currently translated at 99.7% (796 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Filipino)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (German)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

* Translated using Weblate (Japanese)

Currently translated at 99.4% (794 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Czech)

Currently translated at 99.8% (797 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/cs/

* Translated using Weblate (Italian)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/it/

* Translated using Weblate (Nepali)

Currently translated at 100.0% (798 of 798 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ne/

* Translated using Weblate (Czech)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/cs/

* Translated using Weblate (Italian)

Currently translated at 100.0% (18 of 18 strings)

Translation: Mihon/Mihon Plurals
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon-plurals/it/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/es/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Russian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ru/

* Translated using Weblate (Filipino)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/fil/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (German)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/hu/

* Translated using Weblate (Japanese)

Currently translated at 99.7% (801 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ja/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (803 of 803 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hant/

---------

Co-authored-by: Syrodil Eventalious <giannis.yalanskyi@gmail.com>
Co-authored-by: NukeSource <dede48076@gmail.com>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
Co-authored-by: Arash <ara.khoram95@gmail.com>
Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Co-authored-by: Mr. Fakezay <fakezaydev@gmail.com>
Co-authored-by: kevans <albapazpi@gmail.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: gekka <1778962971@qq.com>
Co-authored-by: akir45 <akkn0708@gmail.com>
Co-authored-by: Matyáš Caras <matyas@caras.cafe>
Co-authored-by: Federico Pierantoni <federico.pieranton@gmail.com>
Co-authored-by: FateXBlood <zecrofelix@gmail.com>
2024-04-01 07:51:46 +06:00
Maddie Witman
c9fddf9e38
Moves upcoming requirement from existence to current day or later. (#606)
* Moves upcoming requirement from existence to current day or later.

* Suppress millis conversion warning
2024-03-31 13:49:06 +06:00
MajorTanya
555d2f834f
Add ProGuard rule to keep mihon namespace classes (#605)
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-03-31 05:35:12 +06:00
Andreas
6b3423a12b
Fix Migrator not doing work (#604) 2024-03-31 05:03:28 +06:00
renovate[bot]
7c6fd026a3
chore(deps): update actions/dependency-review-action action to v4.2.5 (#591)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-29 13:52:47 +06:00
renovate[bot]
86fbd20665
fix(deps): update detekt to v1.23.6 (#595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-29 13:25:35 +06:00
renovate[bot]
8c8d65d3c7
fix(deps): update dependency io.github.kevinnzou:compose-webview to v0.33.6 (#594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-29 13:25:28 +06:00
renovate[bot]
f1660beafc
fix(deps): update aboutlib.version to v11.1.1 (#592)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-29 13:25:21 +06:00
Maddie Witman
72222ad86d
New Feature: Introduce Upcoming page to Mihon (#420)
* Work in progress upcoming feature

* Checkpointing WIP upcoming feature

* Functional Upcoming Screen

* Rename UpdateCalendar to UpdateUpcoming

* Converted Strings to resources

* Cleanup

* Fixed detekt issues

* Removed Link icon per @AntsyLich's suggestion.

* Detekt

* Fixed Calendar display on wide form factor devices

* Added Key to upcoming lazycolumn

* Updated tablet mode UI to support two column view

* Updated header creation logic

* Updated header creation logic... again

* Moved stray string to resources

* Fixed PR Comments and query refactor

* Tweaks to query, refactored to flow, comments on calendar

* Switched to Date Formatter

* Cleaned up date formatter

* More Refactor work

* Updated Calendar to support localized week formats

* Fixed year format

* Refactored Header animation

* Moved upcoming FAQ

* Completed YearMonth Migration

* Replaced currentYearMonth with delegate

* Even more cleanup

* cleaned up alignment modifiers

* Click Handler and other refactors

* Removed Wrapped Content Height/Size/extra clips

* Huge Refactor for CalendarDay

* Another cleanup attempt

* Migrated to new mihon.feature.* module pattern

* changed access modifier

* A Bunch of changes from the next round of reviews

* Cleanups

* Cleanup 2

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-03-29 01:02:33 +06:00
Andreas
0265c16eb2
Migrator improvements (#588) 2024-03-29 00:36:33 +06:00
Andreas
666d6aa117
Rewrite Migrations (#577)
* Rewrite Migrations

* Fix Detekt errors

* Do migrations synchronous

* Filter and sort migrations

* Review changes

* Review changes 2

* Fix Detekt errors
2024-03-25 23:26:19 +06:00
AntsyLich
6965e59a64
Fix mishap in e020ae5ed5 2024-03-24 05:54:27 +06:00
AntsyLich
e020ae5ed5
Fix more TypeReference issues and cleanup 2024-03-24 05:16:31 +06:00
MajorTanya
05071b4205
Fix extension repo crash with TypeReference issue (#574)
Fix by @AntsyLich.

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-03-24 04:21:19 +06:00
MajorTanya
da20d00481
Fix repo name used for URL instead of baseUrl (#572)
* Fix repo name used for URL instead of baseUrl

This applies to both the item being shown in the screen as well as the
"copy to clipboard" button. Before, copying a repo url would return
"The Repo Name/index.json.min". This PR fixes that.

* Correct Misunderstanding

Passing the whole ExtensionRepo data class through now, using the name
for display purposes and the baseUrl for copying the URL.
2024-03-23 21:03:55 +06:00
MajorTanya
8c437ceecf
Refactor the ExtensionRepoService to use DTOs (#573)
* Refactor the ExtensionRepoService to use DTOs

Slightly refactored the `ExtensionRepoService` so it uses a DTO with
`parseAs` to avoid parsing the JSON response by hand.

The default Json instance Injekt provides here has
`ignoreUnknownKeys` enabled, so the `ExtensionRepoMetaDto` only
specifies the meta key of the response content.

The extension function `toExtensionRepo` allows for mapping the new
DTO to the `domain` `ExtensionRepo` data class.

* Implement feedback

- Removed SerialName of the ExtensionRepoMetaDto property and renamed
it `meta`, same as the incoming attribute.
- Added a more general catch clause that also logs the occurring
Exception

Detekt likes to complain about TooGenericExceptionCaught, hence the
Suppress annotation on the function.
2024-03-23 21:03:44 +06:00
AntsyLich
9672ea8b1b
Fix extension repo migration not triggering 2024-03-23 17:29:20 +06:00
Maddie Witman
ba9cfd867c
Migrated from Accompanist Webview to KevinZou WebView (#569)
* Migrated from Accompanist Webview to KevinZou WebView to preempt deprecation

* Removed old webview from version library
2024-03-23 07:10:18 +06:00
Maddie Witman
4b4e468510
Grab extension repo detail from repo.json and include in DB (#506)
* WIP Extension Repo DB Support

* Wired in to extension screen, browse settings screen

* Detekt changes

* Ui tweaks and open in browser

* Migrate ExtensionRepos on Update

* Migration Cleanup

* Slight cleanup / error handling

* Update ExtensionRepo from Repo.json during extension search.
Added Manual refresh in extension repos page.

* Split repo fetching into separate API module, major refactor work

* Removed development strings

* Moved migration to #3

* Fixed rebase

* Detekt changes

* Added Replace Repository Dialog

* Cleanup, removed platform specific code, PR comments

* Removed extra function, reverted small change

* Detekt cleanup

* Apply suggestions from code review

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

* Fixed error introduced in cleanup

* Tweak for multiline when

* Moved getCount() to flow

* changed getCount to non-suspend, used property delegation

* Apply suggestions from code review

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

* Fixed formatting with updated comment string

* Big wave of PR comments, renaming/other tweaks

* onOpenWebsite changes

* onOpenWebsite changes

* trying to make single line

* Renamed ExtensionRepoApi.kt to ExtensionRepoService.kt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-03-23 04:58:35 +06:00
576 changed files with 10085 additions and 6607 deletions

View File

@ -53,7 +53,7 @@ body:
label: Mihon version label: Mihon version
description: You can find your Mihon version in **More → About**. description: You can find your Mihon version in **More → About**.
placeholder: | placeholder: |
Example: "0.16.4" Example: "0.16.5"
validations: validations:
required: true required: true
@ -96,7 +96,7 @@ body:
required: true required: true
- label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https://mihon.app/docs/guides/troubleshooting/). - label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https://mihon.app/docs/guides/troubleshooting/).
required: true required: true
- label: I have updated the app to version **[0.16.4](https://github.com/mihonapp/mihon/releases/latest)**. - label: I have updated the app to version **[0.16.5](https://github.com/mihonapp/mihon/releases/latest)**.
required: true required: true
- label: I have updated all installed extensions. - label: I have updated all installed extensions.
required: true required: true

View File

@ -31,7 +31,7 @@ body:
required: true required: true
- label: I have written a short but informative title. - label: I have written a short but informative title.
required: true required: true
- label: I have updated the app to version **[0.16.4](https://github.com/mihonapp/mihon/releases/latest)**. - label: I have updated the app to version **[0.16.5](https://github.com/mihonapp/mihon/releases/latest)**.
required: true required: true
- label: I will fill out all of the requested information in this form. - label: I will fill out all of the requested information in this form.
required: true required: true

10
.github/mergify.yml vendored
View File

@ -1,10 +0,0 @@
#pull_request_rules:
# - name: Automatically merge translations
# conditions:
# - "author = weblate"
# - "-conflict"
# - "current-day-of-week = Sat"
# - "created-at < 1 day ago"
# actions:
# merge:
# method: squash

View File

@ -1,18 +1,14 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": ["config:base"],
"config:base"
],
"schedule": ["every friday"],
"labels": ["Dependencies"], "labels": ["Dependencies"],
"packageRules": [ "packageRules": [
{ {
// Compiler plugins are tightly coupled to Kotlin version "groupName": "Compose BOM (Alpha)",
"groupName": "Kotlin", "matchPackageNames": [
"matchPackagePrefixes": [ "dev.chrisbanes.compose:compose-bom"
"androidx.compose.compiler",
"org.jetbrains.kotlin",
], ],
"ignoreUnstable": false
} }
] ]
} }

View File

@ -3,8 +3,8 @@ on:
pull_request: pull_request:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
- 'i18n/src/commonMain/resources/**/strings.xml' - 'i18n/src/commonMain/moko-resources/**/strings.xml'
- 'i18n/src/commonMain/resources/**/plurals.xml' - 'i18n/src/commonMain/moko-resources/**/plurals.xml'
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@ -20,22 +20,34 @@ jobs:
steps: steps:
- name: Clone repo - name: Clone repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@b231772637bb498f11fdbc86052b6e8a8dc9fc92 # v2.1.2 uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Dependency Review - name: Dependency Review
uses: actions/dependency-review-action@0fa40c3c10055986a88de3baa0d6ec17c5a894b3 # v4.2.3 uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
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@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Build app and run unit tests - name: Build app and run unit tests
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest run: ./gradlew spotlessCheck assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: arm64-v8a-${{ github.sha }}
path: app/build/outputs/apk/standard/release/app-standard-arm64-v8a-release-unsigned.apk
- name: Upload mapping
uses: actions/upload-artifact@v4
with:
name: mapping-${{ github.sha }}
path: app/build/outputs/mapping/standardRelease

View File

@ -17,26 +17,38 @@ jobs:
steps: steps:
- name: Clone repo - name: Clone repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@b231772637bb498f11fdbc86052b6e8a8dc9fc92 # v2.1.2 uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Setup Android SDK - name: Setup Android SDK
run: | run: |
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3" ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3"
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0
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@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Build app and run unit tests - name: Build app and run unit tests
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest run: ./gradlew spotlessCheck assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: arm64-v8a-${{ github.sha }}
path: app/build/outputs/apk/standard/release/app-standard-arm64-v8a-release-unsigned.apk
- name: Upload mapping
uses: actions/upload-artifact@v4
with:
name: mapping-${{ github.sha }}
path: app/build/outputs/mapping/standardRelease
# Sign APK and create release for tags # Sign APK and create release for tags
@ -83,7 +95,7 @@ jobs:
- name: Create Release - name: Create Release
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'mihonapp/mihon' if: startsWith(github.ref, 'refs/tags/') && github.repository == 'mihonapp/mihon'
uses: softprops/action-gh-release@9d7c94cfd0a1f3ed45544c887983e9fa900f0564 # v2.0.4 uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8
with: with:
tag_name: ${{ env.VERSION_TAG }} tag_name: ${{ env.VERSION_TAG }}
name: Mihon ${{ env.VERSION_TAG }} name: Mihon ${{ env.VERSION_TAG }}

View File

@ -1,35 +0,0 @@
name: Issue moderator
on:
issues:
types: [opened, edited, reopened]
issue_comment:
types: [created]
jobs:
moderate:
runs-on: ubuntu-latest
steps:
- name: Moderate issues
uses: keiyoushi/issue-moderator-action@a017be83547db6e107431ce7575f53c1dfa3296a
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
duplicate-label: Duplicate
auto-close-rules: |
[
{
"type": "both",
"regex": "^(?!.*myanimelist.*).*(aniyomi|anime).*$",
"ignoreCase": true,
"message": "Mihon does not support anime, and has no plans to support anime. In addition Mihon is not affiliated with Aniyomi https://github.com/jmir1/aniyomi"
},
{
"type": "both",
"regex": ".*(?:fail(?:ed|ure|s)?|can\\s*(?:no|')?t|(?:not|un).*able|(?<!n[o']?t )blocked by|error) (?:to )?(?:get past|by ?pass|penetrate)?.*cloud ?fl?are.*",
"ignoreCase": true,
"labels": ["Cloudflare protected"],
"message": "Refer to the **Solving Cloudflare issues** section at https://mihon.app/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
}
]
auto-close-ignore-label: do-not-autoclose

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.gradle .gradle
.kotlin
/local.properties /local.properties
/.idea/workspace.xml /.idea/workspace.xml
.DS_Store .DS_Store

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 62 KiB

134
CHANGELOG.md Normal file
View File

@ -0,0 +1,134 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Option to disable reader zoom out ([@Splintorien](https://github.com/Splintorien)) ([#302](https://github.com/mihonapp/mihon/pull/302))
- Source name and tracker urls to app generated `ComicInfo.xml` file ([@Shamicen](https://github.com/Shamicen)) ([#459](https://github.com/mihonapp/mihon/pull/459))
- Option to migrate in Duplicate entry dialog ([@sirlag](https://github.com/sirlag)) ([#492](https://github.com/mihonapp/mihon/pull/492))
- Upcoming screen to visualize expected update dates ([@sirlag](https://github.com/sirlag)) ([#420](https://github.com/mihonapp/mihon/pull/420))
- Crash screen error message to the top of the crash log generated from that screen ([@FooIbar](https://github.com/FooIbar)) ([#742](https://github.com/mihonapp/mihon/pull/742))
- Support for 7Zip and RAR5 archives ([@FooIbar](https://github.com/FooIbar), [@null2264](https://github.com/null2264)) ([#949](https://github.com/mihonapp/mihon/pull/949), [#967](https://github.com/mihonapp/mihon/pull/967))
- Extra configuration options to e-ink page flashes ([@sirlag](https://github.com/sirlag)) ([#625](https://github.com/mihonapp/mihon/pull/625))
- 8-bit+ AVIF image support ([@WerctFourth](https://github.com/WerctFourth)) ([#971](https://github.com/mihonapp/mihon/pull/971))
- Smart update dialog message when no predicted released date exists ([@Animeboynz](https://github.com/Animeboynz)) ([#977](https://github.com/mihonapp/mihon/pull/977))
- Save global search "Has result" choice ([@AntsyLich](https://github.com/AntsyLich)) ([`5a61ca5`](https://github.com/mihonapp/mihon/commit/5a61ca5535fe0d9e8e7bcb9e665ba2f9cb0cf649))
- Option to copy reader panel to clipboard ([@Animeboynz](https://github.com/Animeboynz)) ([#1003](https://github.com/mihonapp/mihon/pull/1003))
- Copy Tracker URL option to tracker sheet ([@mm12](https://github.com/mm12)) ([#1101](https://github.com/mihonapp/mihon/pull/1101))
- A button to exclude all scanlators in exclude scanlators dialog ([@AntsyLich](https://github.com/AntsyLich)) ([`84b2164`](https://github.com/mihonapp/mihon/commit/84b2164787a795f3fd757c325cbfb6ef660ac3a3))
- Open in browser option to reader menu ([@mm12](https://github.com/mm12)) ([#1110](https://github.com/mihonapp/mihon/pull/1110))
- Option to skip downloading duplicate read chapters ([@shabnix](https://github.com/shabnix)) ([#1125](https://github.com/mihonapp/mihon/pull/1125))
### Changed
- Read archive files from memory instead of extracting files to internal storage ([@FooIbar](https://github.com/FooIbar)) ([#326](https://github.com/mihonapp/mihon/pull/326))
- Try to get resource from Extension before checking in the app ([@beer-psi](https://github.com/beer-psi)) ([#433](https://github.com/mihonapp/mihon/pull/433))
- Default user agent ([@AntsyLich](https://github.com/AntsyLich)) ([`8160b47`](https://github.com/mihonapp/mihon/commit/8160b47ff5fbbd9b32caeb462b5be881fabd3449))
- Wait for sources to be initialized before performing source related tasks ([@jobobby04](https://github.com/jobobby04)) ([`a08e03f`](https://github.com/mihonapp/mihon/commit/a08e03f5cbf3f4e6be1de35f97ef8ebb26a1210e))
- Duplicate entry dialog UI ([@sirlag](https://github.com/sirlag)) ([#492](https://github.com/mihonapp/mihon/pull/492))
- Extension trust system ([@AntsyLich](https://github.com/AntsyLich), [@Animeboynz](https://github.com/Animeboynz) ([#570](https://github.com/mihonapp/mihon/pull/570), [#1057](https://github.com/mihonapp/mihon/pull/1057))
- Make category backup/restore not dependant on library backup ([@AntsyLich](https://github.com/AntsyLich)) ([`56fb4f6`](https://github.com/mihonapp/mihon/commit/56fb4f62a152e87a71892aa68c78cac51a2c8596))
- Kitsu domain to `kitsu.app` ([@MajorTanya](https://github.com/MajorTanya)) ([#1106](https://github.com/mihonapp/mihon/pull/1106))
- Respect privacy settings in extension update notification ([@Animeboynz](https://github.com/Animeboynz)) ([#1156](https://github.com/mihonapp/mihon/pull/1156))
### Improvement
- Long strip reader performance ([@FooIbar](https://github.com/FooIbar), [@wwww-wwww](https://github.com/wwww-wwww)) ([#687](https://github.com/mihonapp/mihon/pull/687))
- Performance when looking up specific files ([@raxod502](https://github.com/raxod502)) ([#728](https://github.com/mihonapp/mihon/pull/728))
- Chapter number parsing ([@Naputt1](https://github.com/Naputt1)) ([`6a80305`](https://github.com/mihonapp/mihon/commit/6a80305d6c572da6c08c0c69f5c25ff26ecf7383))
- Error message on restoring if backup decoding fails ([@vetleledaal](https://github.com/vetleledaal)) ([#1056](https://github.com/mihonapp/mihon/pull/1056))
### Fixed
- Creating `ComicInfo.xml` file for local source ([@FooIbar](https://github.com/FooIbar)) ([#325](https://github.com/mihonapp/mihon/pull/325))
- Chapter download indicator ([@ivaniskandar](https://github.com/ivaniskandar)) ([`d8b9a9f`](https://github.com/mihonapp/mihon/commit/d8b9a9f593911569ff2bceb49b4f020978d0d2e1))
- Issues with shizuku in a multi user setup ([@Redjard](https://github.com/Redjard)) ([#494](https://github.com/mihonapp/mihon/pull/494))
- Occasional black bar when scrolling in long strip reader ([@FooIbar](https://github.com/FooIbar)) ([#563](https://github.com/mihonapp/mihon/pull/563))
- Extension being marked as not installed instead of untrusted after updating with private installer ([@AntsyLich](https://github.com/AntsyLich)) ([`2114514`](https://github.com/mihonapp/mihon/commit/21145144cdf550aa775047603e06e261951ebc42))
- Extension update counter not updating due to extension being marked as untrusted ([@AntsyLich](https://github.com/AntsyLich)) ([`2114514`](https://github.com/mihonapp/mihon/commit/21145144cdf550aa775047603e06e261951ebc42))
- `Key "extension-XXX-YYY" was already used` crash ([@AntsyLich](https://github.com/AntsyLich)) ([`2114514`](https://github.com/mihonapp/mihon/commit/21145144cdf550aa775047603e06e261951ebc42))
- Navigation layout tap zones shifting after zooming out in webtoon readers ([@FooIbar](https://github.com/FooIbar)) ([#767](https://github.com/mihonapp/mihon/pull/767))
- Some extension not loading due to missing classes ([@AwkwardPeak7](https://github.com/AwkwardPeak7)) ([#783](https://github.com/mihonapp/mihon/pull/783))
- Theme colors in accordance to upstream changes ([@CrepeTF](https://github.com/CrepeTF), [@AntsyLich](https://github.com/AntsyLich)) ([#766](https://github.com/mihonapp/mihon/pull/766), [#963](https://github.com/mihonapp/mihon/pull/963), [#976](https://github.com/mihonapp/mihon/pull/976))
- Crash when requesting folder access on non-conforming devices ([@mainrs](https://github.com/mainrs)) ([#726](https://github.com/mihonapp/mihon/pull/726))
- Bugged color for Date/Scanlator in chapter list for read chapters ([@ivaniskandar](https://github.com/ivaniskandar)) ([`15d9992`](https://github.com/mihonapp/mihon/commit/15d999229fcce865001d5fa77d0163e6e80e38db))
- Categories having same `order` after restoring backup ([@Cologler](https://github.com/Cologler)) ([`119bcbf`](https://github.com/mihonapp/mihon/commit/119bcbf8ed2415664922ea77fadf0da1165d1732))
- Filter by "Tracking" temporarily stuck after signing out of tracker ([@AntsyLich](https://github.com/AntsyLich)) ([#987](https://github.com/mihonapp/mihon/pull/987))
- JXL image downloading and loading ([@FooIbar](https://github.com/FooIbar)) ([#993](https://github.com/mihonapp/mihon/pull/993))
- Crash when using `%` in category name ([@Animeboynz](https://github.com/Animeboynz), [@FooIbar](https://github.com/FooIbar)) ([#1030](https://github.com/mihonapp/mihon/pull/1030))
- Library is backed up while being disabled ([@AntsyLich](https://github.com/AntsyLich)) ([`56fb4f6`](https://github.com/mihonapp/mihon/commit/56fb4f62a152e87a71892aa68c78cac51a2c8596))
- Crash on list with 0 item but only sticky header ([@cuong-tran](https://github.com/cuong-tran)) ([#1083](https://github.com/mihonapp/mihon/pull/1083))
- Crash when trying to clear cookies of some source ([@FooIbar](https://github.com/FooIbar)) ([#1084](https://github.com/mihonapp/mihon/pull/1084))
- MAL search results not showing start dates ([@MajorTanya](https://github.com/MajorTanya)) ([#1098](https://github.com/mihonapp/mihon/pull/1098))
- Android SDK 35 API collision ([@AntsyLich](https://github.com/AntsyLich)) ([`fdb9617`](https://github.com/mihonapp/mihon/commit/fdb96179c6373eb0a8e7d6daea671a315d5ce5f0))
## [v0.16.5] - 2024-04-09
### Added
- Setting to install custom color profiles to get true colors ([@wwww-wwww](https://github.com/wwww-wwww)) ([#523](https://github.com/mihonapp/mihon/pull/523))
### Changed
- Permanently enable 32-bit color mode ([@wwww-wwww](https://github.com/wwww-wwww)) ([#523](https://github.com/mihonapp/mihon/pull/523))
### Fixed
- Fix wrong dates in Updates and History tab due to time zone issues ([@sirlag](https://github.com/sirlag)) ([#402](https://github.com/mihonapp/mihon/pull/402), [#415](https://github.com/mihonapp/mihon/pull/415))
- Fix app infinitely retries tracker update instead of failing after 3 tries ([@MajorTanya](https://github.com/MajorTanya)) ([#411](https://github.com/mihonapp/mihon/pull/411))
- Fix crash on Pixel devices ([`ab06720`](https://github.com/mihonapp/mihon/commit/ab067209661eceefc04c65f6bdbfcaa8a1264651))
- Fix crash when opening some heif/heic images ([@az4521](https://github.com/az4521)) ([#466](https://github.com/mihonapp/mihon/pull/466))
- Fix crash in track date selection dialog ([@ivaniskandar](https://github.com/ivaniskandar)) ([`c348fac`](https://github.com/mihonapp/mihon/commit/c348fac78fac479fb123bd617c01c78b9ca851d5))
- Fix dates for saved images on Samsung devices ([@MajorTanya](https://github.com/MajorTanya)) ([#552](https://github.com/mihonapp/mihon/pull/552))
- Fix colors getting distorted when opening CMYK jpeg images ([@wwww-wwww](https://github.com/wwww-wwww)) ([#523](https://github.com/mihonapp/mihon/pull/523))
## [v0.16.4] - 2024-02-26
### Fixed
- Circumvent MAL block ([@AntsyLich](https://github.com/AntsyLich)) ([`085ad8d`](https://github.com/mihonapp/mihon/commit/085ad8d44637c375a8ed24aba3a6f75f5b0cc9ee))
## [v0.16.3] - 2024-01-30
### Added
- Copy extension debug info when clicking logo or name in the extension details screen ([@MajorTanya](https://github.com/MajorTanya)) ([#271](https://github.com/mihonapp/mihon/pull/271))
### Changed
- Rename extension update error file to `mihon_update_errors.txt` ([@mjishnu](https://github.com/mjishnu)) ([#253](https://github.com/mihonapp/mihon/pull/253))
- Hide display cutoff setting in reader settings sheet if fullscreen is off ([@Riztard](https://github.com/Riztard)) ([#241](https://github.com/mihonapp/mihon/pull/241))
### Fixed
- Fix bottom sheet display issues on non-Tablet UI ([@theolm](https://github.com/theolm)) ([#182](https://github.com/mihonapp/mihon/pull/182))
- Fix crash when switching screen while a list is scrolling ([@theolm](https://github.com/theolm)) ([#272](https://github.com/mihonapp/mihon/pull/272))
- Fix newly installed extensions not being recognized by Mihon ([@AwkwardPeak7](https://github.com/AwkwardPeak7)) ([#275](https://github.com/mihonapp/mihon/pull/275))
- Fix error handling when refreshing MAL OAuth token ([@AntsyLich](https://github.com/AntsyLich)) ([`0f4de03`](https://github.com/mihonapp/mihon/commit/0f4de03d7a77b52490dc9a95e96a308b93b26e4f))
## [v0.16.2] - 2024-01-28
### Added
- Scanlator filter is now part of Backup ([@jobobby04](https://github.com/jobobby04)) ([#166](https://github.com/mihonapp/mihon/pull/166))
### Changed
- Rename crash log filename to `mihon_crash_logs.txt` ([@MajorTanya](https://github.com/MajorTanya)) ([#234](https://github.com/mihonapp/mihon/pull/234))
### Fixed
- "Flash screen on page change" Making the screen goes blank ([@AntsyLich](https://github.com/AntsyLich)) ([`38d6ab8`](https://github.com/mihonapp/mihon/commit/38d6ab80ce868707829dbc81de4170afe3c2f2a5))
- App icon scaling ([@AntsyLich](https://github.com/AntsyLich)) ([`26815c7`](https://github.com/mihonapp/mihon/commit/26815c7356111394665467c1e81255ac9ee33c1a))
- Updating extension not reflecting correctly ([@AntsyLich](https://github.com/AntsyLich)) ([`cb06898`](https://github.com/mihonapp/mihon/commit/cb068984303f811692531bf6f14902ae118d8ac7))
- Inconsistent button height with some languages in "Data and storage" ([@theolm](https://github.com/theolm)) ([#202](https://github.com/mihonapp/mihon/pull/202))
- Fix chapter not being marked as read in some cases with Enhanced Trackers ([@Secozzi](https://github.com/Secozzi)) ([#219](https://github.com/mihonapp/mihon/pull/219))
- And various tracker related fixes ([@AntsyLich](https://github.com/AntsyLich), [@kitsumed](https://github.com/kitsumed), [@Secozzi](https://github.com/Secozzi)) ([`a024218`](https://github.com/mihonapp/mihon/commit/a024218410953a389b8af4880fa7ae6cc30124a2), [`e3f33e2`](https://github.com/mihonapp/mihon/commit/e3f33e24f5e928ac8a85d1f500fd42d4715fc6b5), [`32188f9`](https://github.com/mihonapp/mihon/commit/32188f9f65009a18250674ef1bd6e57d351c1fba))
## [v0.16.1] - 2024-01-18
### Fixed
- App Icon not filled ([@AntsyLich](https://github.com/AntsyLich)) ([`1849715`](https://github.com/mihonapp/mihon/commit/18497154183356bb0d469b27827f9f7d6b7a3130))
- MangaUpdates default score being set to -1.0 ([@AntsyLich](https://github.com/AntsyLich)) ([`99fd273`](https://github.com/mihonapp/mihon/commit/99fd2731f5d9d374700e89fa67d4d5bf611bbafa))
## [v0.16.0] - 2024-01-16
"The end of 立ち読み (Tachiyomi) is the beginning of みほん (Mihon)"
Credit to LinkCable, the icon designer, for this poetic quote.
What's New?
Well, nothing, except you now you need Android 8+ to install the app.
[unreleased]: https://github.com/mihonapp/mihon/compare/v0.16.5...HEAD
[v0.16.5]: https://github.com/mihonapp/mihon/compare/v0.16.4...v0.16.5
[v0.16.4]: https://github.com/mihonapp/mihon/compare/v0.16.3...v0.16.4
[v0.16.3]: https://github.com/mihonapp/mihon/compare/v0.16.2...v0.16.3
[v0.16.2]: https://github.com/mihonapp/mihon/compare/v0.16.1...v0.16.2
[v0.16.1]: https://github.com/mihonapp/mihon/compare/v0.16.0...v0.16.1
[v0.16.0]: https://github.com/mihonapp/mihon/releases/tag/v0.16.0

View File

@ -24,10 +24,6 @@ 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/mihon) 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.

View File

@ -29,7 +29,7 @@ Discover and read manga, webtoons, comics, and more easier than ever on your
* Local reading of content. * Local reading of 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.
@ -49,8 +49,8 @@ Before reporting a new issue, take a look at the [FAQ](https://mihon.app/docs/fa
### Repositories ### Repositories
[![mihonapp/website - GitHub](https://github-readme-stats.vercel.app/api/pin/?username=mihonapp&repo=website&bg_color=161B22&text_color=c9d1d9&title_color=0877d2&icon_color=0877d2&border_radius=8&hide_border=true)](https://github.com/mihonapp/website/) [![mihonapp/website - GitHub](https://github-readme-stats.vercel.app/api/pin/?username=mihonapp&repo=website&bg_color=161B22&text_color=c9d1d9&title_color=0877d2&icon_color=0877d2&border_radius=8&hide_border=true&description_lines_count=2)](https://github.com/mihonapp/website/)
[![mihonapp/bitmap.kt - GitHub](https://github-readme-stats.vercel.app/api/pin/?username=mihonapp&repo=bitmap.kt&bg_color=161B22&text_color=c9d1d9&title_color=0877d2&icon_color=0877d2&border_radius=8&hide_border=true)](https://github.com/mihonapp/bitmap.kt/) [![mihonapp/bitmap.kt - GitHub](https://github-readme-stats.vercel.app/api/pin/?username=mihonapp&repo=bitmap.kt&bg_color=161B22&text_color=c9d1d9&title_color=0877d2&icon_color=0877d2&border_radius=8&hide_border=true&description_lines_count=2)](https://github.com/mihonapp/bitmap.kt/)
### Credits ### Credits

View File

@ -1,20 +1,26 @@
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("com.mikepenz.aboutlibraries.plugin") id("mihon.android.application.compose")
kotlin("android")
kotlin("plugin.serialization")
id("com.github.zellius.shortcut-helper") id("com.github.zellius.shortcut-helper")
kotlin("plugin.serialization")
alias(libs.plugins.aboutLibraries)
} }
if (gradle.startParameter.taskRequests.toString().contains("Standard")) { if (gradle.startParameter.taskRequests.toString().contains("Standard")) {
apply<com.google.gms.googleservices.GoogleServicesPlugin>() pluginManager.apply {
apply(libs.plugins.google.services.get().pluginId)
apply(libs.plugins.firebase.crashlytics.get().pluginId)
}
} }
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"
@ -22,8 +28,8 @@ android {
defaultConfig { defaultConfig {
applicationId = "app.mihon" applicationId = "app.mihon"
versionCode = 6 versionCode = 7
versionName = "0.16.4" versionName = "0.16.5"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"") buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
@ -32,7 +38,7 @@ android {
buildConfigField("boolean", "PREVIEW", "false") buildConfigField("boolean", "PREVIEW", "false")
ndk { ndk {
abiFilters += SUPPORTED_ABIS abiFilters += supportedAbis
} }
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@ -42,7 +48,7 @@ android {
abi { abi {
isEnable = true isEnable = true
reset() reset()
include(*SUPPORTED_ABIS.toTypedArray()) include(*supportedAbis.toTypedArray())
isUniversalApk = true isUniversalApk = true
} }
} }
@ -119,7 +125,6 @@ android {
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
compose = true
buildConfig = true buildConfig = true
// Disable some unused things // Disable some unused things
@ -132,14 +137,11 @@ android {
abortOnError = false abortOnError = false
checkReleaseBuilds = false checkReleaseBuilds = false
} }
composeOptions {
kotlinCompilerExtensionVersion = compose.versions.compiler.get()
}
} }
dependencies { dependencies {
implementation(projects.i18n) implementation(projects.i18n)
implementation(projects.core.archive)
implementation(projects.core.common) implementation(projects.core.common)
implementation(projects.coreMetadata) implementation(projects.coreMetadata)
implementation(projects.sourceApi) implementation(projects.sourceApi)
@ -150,20 +152,19 @@ 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)
@ -208,13 +209,12 @@ dependencies {
// Disk // Disk
implementation(libs.disklrucache) implementation(libs.disklrucache)
implementation(libs.unifile) implementation(libs.unifile)
implementation(libs.bundles.archive)
// Preferences // Preferences
implementation(libs.preferencektx) implementation(libs.preferencektx)
// Dependency injection // Dependency injection
implementation(libs.injekt.core) implementation(libs.injekt)
// Image loading // Image loading
implementation(platform(libs.coil.bom)) implementation(platform(libs.coil.bom))
@ -237,12 +237,16 @@ 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
"standardImplementation"(platform(libs.firebase.bom))
"standardImplementation"(libs.firebase.analytics) "standardImplementation"(libs.firebase.analytics)
"standardImplementation"(libs.firebase.crashlytics)
// Shizuku // Shizuku
implementation(libs.bundles.shizuku) implementation(libs.bundles.shizuku)
@ -253,6 +257,8 @@ dependencies {
// For detecting memory leaks; see https://square.github.io/leakcanary/ // For detecting memory leaks; see https://square.github.io/leakcanary/
// debugImplementation(libs.leakcanary.android) // debugImplementation(libs.leakcanary.android)
implementation(libs.leakcanary.plumber) implementation(libs.leakcanary.plumber)
testImplementation(kotlinx.coroutines.test)
} }
androidComponents { androidComponents {
@ -274,7 +280,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",
@ -285,31 +291,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",
)
} }
} }

View File

@ -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 *; }
@ -43,6 +44,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
@ -72,9 +77,6 @@
# XmlUtil # XmlUtil
-keep public enum nl.adaptivity.xmlutil.EventType { *; } -keep public enum nl.adaptivity.xmlutil.EventType { *; }
# Apache Commons Compress
-keep class * extends org.apache.commons.compress.archivers.zip.ZipExtraField { <init>(); }
# Firebase # Firebase
-keep class com.google.firebase.installations.** { *; } -keep class com.google.firebase.installations.** { *; }
-keep interface com.google.firebase.installations.** { *; } -keep interface com.google.firebase.installations.** { *; }

View File

@ -33,11 +33,6 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<!-- Remove permission from Firebase dependency -->
<uses-permission
android:name="com.google.android.gms.permission.AD_ID"
tools:node="remove" />
<application <application
android:name=".App" android:name=".App"
android:allowBackup="false" android:allowBackup="false"
@ -236,11 +231,6 @@
android:name="android.webkit.WebView.MetricsOptOut" android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" /> android:value="true" />
<!-- Disable advertising ID collection for Firebase -->
<meta-data
android:name="google_analytics_adid_collection_enabled"
android:value="false" />
</application> </application>
</manifest> </manifest>

View File

@ -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
@ -69,6 +77,7 @@ import tachiyomi.domain.manga.interactor.GetMangaWithChapters
import tachiyomi.domain.manga.interactor.NetworkToLocalManga import tachiyomi.domain.manga.interactor.NetworkToLocalManga
import tachiyomi.domain.manga.interactor.ResetViewerFlags import tachiyomi.domain.manga.interactor.ResetViewerFlags
import tachiyomi.domain.manga.interactor.SetMangaChapterFlags import tachiyomi.domain.manga.interactor.SetMangaChapterFlags
import tachiyomi.domain.manga.interactor.SetMangaNotes
import tachiyomi.domain.manga.repository.MangaRepository import tachiyomi.domain.manga.repository.MangaRepository
import tachiyomi.domain.release.interactor.GetApplicationRelease import tachiyomi.domain.release.interactor.GetApplicationRelease
import tachiyomi.domain.release.service.ReleaseService import tachiyomi.domain.release.service.ReleaseService
@ -111,8 +120,10 @@ class DomainModule : InjektModule {
addFactory { GetMangaByUrlAndSourceId(get()) } addFactory { GetMangaByUrlAndSourceId(get()) }
addFactory { GetManga(get()) } addFactory { GetManga(get()) }
addFactory { GetNextChapters(get(), get(), get()) } addFactory { GetNextChapters(get(), get(), get()) }
addFactory { GetUpcomingManga(get()) }
addFactory { ResetViewerFlags(get()) } addFactory { ResetViewerFlags(get()) }
addFactory { SetMangaChapterFlags(get()) } addFactory { SetMangaChapterFlags(get()) }
addFactory { SetMangaNotes(get()) }
addFactory { FetchInterval(get()) } addFactory { FetchInterval(get()) }
addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) } addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) }
addFactory { SetMangaViewerFlags(get()) } addFactory { SetMangaViewerFlags(get()) }
@ -144,6 +155,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()) }
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) } addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
addFactory { GetHistory(get()) } addFactory { GetHistory(get()) }
@ -171,10 +183,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()) }
} }
} }

View File

@ -110,7 +110,10 @@ class SyncChaptersWithSource(
if (shouldUpdateDbChapter.await(dbChapter, chapter)) { if (shouldUpdateDbChapter.await(dbChapter, chapter)) {
val shouldRenameChapter = downloadProvider.isChapterDirNameChanged(dbChapter, chapter) && val shouldRenameChapter = downloadProvider.isChapterDirNameChanged(dbChapter, chapter) &&
downloadManager.isChapterDownloaded( downloadManager.isChapterDownloaded(
dbChapter.name, dbChapter.scanlator, manga.title, manga.source, dbChapter.name,
dbChapter.scanlator,
manga.title,
manga.source,
) )
if (shouldRenameChapter) { if (shouldRenameChapter) {

View File

@ -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()

View File

@ -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
}
}

View File

@ -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()
}
}

View File

@ -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(
@ -40,9 +40,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,

View File

@ -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"
}
} }
} }

View File

@ -48,4 +48,9 @@ class SourcePreferences(
Preference.appStateKey("trusted_extensions"), Preference.appStateKey("trusted_extensions"),
emptySet(), emptySet(),
) )
fun globalSearchFilterState() = preferenceStore.getBoolean(
Preference.appStateKey("has_filters_toggle_state"),
false,
)
} }

View File

@ -19,7 +19,11 @@ class UiPreferences(
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)

View File

@ -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
@ -191,7 +190,7 @@ private fun ExtensionDetails(
key = { it.source.id }, key = { it.source.id },
) { source -> ) { source ->
SourceSwitchPreference( SourceSwitchPreference(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
source = source, source = source,
onClickSourcePreferences = onClickSourcePreferences, onClickSourcePreferences = onClickSourcePreferences,
onClickSource = onClickSource, onClickSource = onClickSource,
@ -233,7 +232,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) {
@ -243,8 +242,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(),
) )
} }
} }
@ -354,10 +353,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
} }

View File

@ -58,7 +58,7 @@ private fun ExtensionFilterContent(
) { ) {
items(state.languages) { language -> items(state.languages) { language ->
SwitchPreferenceWidget( SwitchPreferenceWidget(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
title = LocaleHelper.getSourceDisplayName(language, context), title = LocaleHelper.getSourceDisplayName(language, context),
checked = language in state.enabledLanguages, checked = language in state.enabledLanguages,
onCheckedChanged = { onClickLang(language) }, onCheckedChanged = { onClickLang(language) },

View File

@ -48,6 +48,7 @@ import eu.kanade.presentation.browse.components.ExtensionIcon
import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText
import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
@ -90,7 +91,7 @@ fun ExtensionScreen(
PullRefresh( PullRefresh(
refreshing = state.isRefreshing, refreshing = state.isRefreshing,
onRefresh = onRefresh, onRefresh = onRefresh,
enabled = { !state.isLoading }, enabled = !state.isLoading,
) { ) {
when { when {
state.isLoading -> LoadingScreen(Modifier.padding(contentPadding)) state.isLoading -> LoadingScreen(Modifier.padding(contentPadding))
@ -187,14 +188,14 @@ private fun ExtensionContent(
} }
ExtensionHeader( ExtensionHeader(
textRes = header.textRes, textRes = header.textRes,
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
action = action, action = action,
) )
} }
is ExtensionUiModel.Header.Text -> { is ExtensionUiModel.Header.Text -> {
ExtensionHeader( ExtensionHeader(
text = header.text, text = header.text,
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
) )
} }
} }
@ -212,13 +213,15 @@ private fun ExtensionContent(
}, },
) { item -> ) { item ->
ExtensionItem( ExtensionItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
item = item, item = item,
onClickItem = { onClickItem = {
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,
@ -240,7 +243,9 @@ private fun ExtensionContent(
onOpenExtension(it) onOpenExtension(it)
} }
} }
is Extension.Untrusted -> { trustState = it } is Extension.Untrusted -> {
trustState = it
}
} }
}, },
) )

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import eu.kanade.presentation.browse.components.GlobalSearchCardRow import eu.kanade.presentation.browse.components.GlobalSearchCardRow
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem import eu.kanade.presentation.browse.components.GlobalSearchLoadingResultItem
@ -79,6 +80,7 @@ internal fun GlobalSearchContent(
} ?: source.name, } ?: source.name,
subtitle = LocaleHelper.getLocalizedDisplayName(source.lang), subtitle = LocaleHelper.getLocalizedDisplayName(source.lang),
onClick = { onClickSource(source) }, onClick = { onClickSource(source) },
modifier = Modifier.animateItem(),
) { ) {
when (result) { when (result) {
SearchItemResult.Loading -> { SearchItemResult.Loading -> {

View File

@ -133,7 +133,7 @@ private fun MigrateSourceList(
key = { (source, _) -> "migrate-${source.id}" }, key = { (source, _) -> "migrate-${source.id}" },
) { (source, count) -> ) { (source, count) ->
MigrateSourceItem( MigrateSourceItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
source = source, source = source,
count = count, count = count,
onClickItem = { onClickItem(source) }, onClickItem = { onClickItem(source) },

View File

@ -10,6 +10,7 @@ import androidx.compose.ui.platform.LocalContext
import eu.kanade.presentation.browse.components.BaseSourceItem import eu.kanade.presentation.browse.components.BaseSourceItem
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterScreenModel import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
@ -68,7 +69,7 @@ private fun SourcesFilterContent(
contentType = "source-filter-header", contentType = "source-filter-header",
) { ) {
SourcesFilterHeader( SourcesFilterHeader(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
language = language, language = language,
enabled = enabled, enabled = enabled,
onClickItem = onClickLanguage, onClickItem = onClickLanguage,
@ -81,7 +82,7 @@ private fun SourcesFilterContent(
contentType = { "source-filter-item" }, contentType = { "source-filter-item" },
) { source -> ) { source ->
SourcesFilterItem( SourcesFilterItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
source = source, source = source,
enabled = "${source.id}" !in state.disabledSources, enabled = "${source.id}" !in state.disabledSources,
onClickItem = onClickSource, onClickItem = onClickSource,

View File

@ -28,7 +28,7 @@ import tachiyomi.domain.source.model.Pin
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
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
@ -74,12 +74,12 @@ fun SourcesScreen(
when (model) { when (model) {
is SourceUiModel.Header -> { is SourceUiModel.Header -> {
SourceHeader( SourceHeader(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
language = model.language, language = model.language,
) )
} }
is SourceUiModel.Item -> SourceItem( is SourceUiModel.Item -> SourceItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
source = model.source, source = model.source,
onClickItem = onClickItem, onClickItem = onClickItem,
onLongClickItem = onLongClickItem, onLongClickItem = onLongClickItem,
@ -148,7 +148,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

View File

@ -32,9 +32,10 @@ fun GlobalSearchResultItem(
title: String, title: String,
subtitle: String, subtitle: String,
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier,
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
Column { Column(modifier = modifier) {
Row( Row(
modifier = Modifier modifier = Modifier
.padding( .padding(

View File

@ -107,7 +107,7 @@ private fun CategoryContent(
key = { _, category -> "category-${category.id}" }, key = { _, category -> "category-${category.id}" },
) { index, category -> ) { index, category ->
CategoryListItem( CategoryListItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
category = category, category = category,
canMoveUp = index != 0, canMoveUp = index != 0,
canMoveDown = index != categories.lastIndex, canMoveDown = index != categories.lastIndex,

View File

@ -10,8 +10,7 @@ import androidx.compose.ui.Modifier
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.shouldExpandFAB
import tachiyomi.presentation.core.util.isScrollingUp
@Composable @Composable
fun CategoryFloatingActionButton( fun CategoryFloatingActionButton(
@ -23,7 +22,7 @@ fun CategoryFloatingActionButton(
text = { Text(text = stringResource(MR.strings.action_add)) }, text = { Text(text = stringResource(MR.strings.action_add)) },
icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = null) }, icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = null) },
onClick = onCreate, onClick = onCreate,
expanded = lazyListState.isScrollingUp() || lazyListState.isScrolledToEnd(), expanded = lazyListState.shouldExpandFAB(),
modifier = modifier, modifier = modifier,
) )
} }

View File

@ -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,
) { ) {

View File

@ -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
@ -179,7 +179,7 @@ fun AppBarTitle(
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee( modifier = Modifier.basicMarquee(
delayMillis = 2_000, repeatDelayMillis = 2_000,
), ),
) )
} }
@ -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 = {},
) )
}, },
) )

View File

@ -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) },
) )
} }
} }

View File

@ -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),

View File

@ -18,6 +18,7 @@ import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.components.relativeDateText
import eu.kanade.presentation.history.components.HistoryItem import eu.kanade.presentation.history.components.HistoryItem
import eu.kanade.presentation.theme.TachiyomiPreviewTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.domain.history.model.HistoryWithRelations
@ -113,14 +114,14 @@ private fun HistoryScreenContent(
when (item) { when (item) {
is HistoryUiModel.Header -> { is HistoryUiModel.Header -> {
ListGroupHeader( ListGroupHeader(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
text = relativeDateText(item.date), text = relativeDateText(item.date),
) )
} }
is HistoryUiModel.Item -> { is HistoryUiModel.Item -> {
val value = item.item val value = item.item
HistoryItem( HistoryItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemFastScroll(),
history = value, history = value,
onClickCover = { onClickCover(value) }, onClickCover = { onClickCover(value) },
onClickResume = { onClickResume(value) }, onClickResume = { onClickResume(value) },

View File

@ -9,6 +9,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.FilterChip 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.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -125,7 +126,7 @@ private fun ColumnScope.FilterPage(
) )
} }
val trackers = remember { screenModel.trackers } val trackers by screenModel.trackersFlow.collectAsState()
when (trackers.size) { when (trackers.size) {
0 -> { 0 -> {
// No trackers // No trackers
@ -158,15 +159,15 @@ private fun ColumnScope.SortPage(
category: Category?, category: Category?,
screenModel: LibrarySettingsScreenModel, screenModel: LibrarySettingsScreenModel,
) { ) {
val trackers by screenModel.trackersFlow.collectAsState()
val sortingMode = category.sort.type val sortingMode = category.sort.type
val sortDescending = !category.sort.isAscending val sortDescending = !category.sort.isAscending
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) }
}
listOf( listOf(
MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical, MR.strings.action_sort_alpha to LibrarySort.Type.Alphabetical,

View File

@ -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),
) )
} }
} }

View File

@ -93,7 +93,7 @@ fun LibraryContent(
isRefreshing = false isRefreshing = false
} }
}, },
enabled = { notSelectionMode }, enabled = notSelectionMode,
) { ) {
LibraryPager( LibraryPager(
state = pagerState, state = pagerState,

View File

@ -0,0 +1,144 @@
package eu.kanade.presentation.manga
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle
import com.halilibo.richtext.markdown.Markdown
import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.string.RichTextStringStyle
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.manga.components.MangaNotesTextArea
import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.EmptyScreen
@Composable
fun MangaNotesScreen(
state: MangaNotesScreenState.Success,
navigateUp: () -> Unit,
beginEditing: () -> Unit,
endEditing: () -> Unit,
onSave: (String) -> Unit,
modifier: Modifier = Modifier,
) {
Scaffold(
topBar = { scrollBehavior ->
AppBar(
titleContent = {
AppBarTitle(title = stringResource(MR.strings.action_notes), subtitle = state.manga.title)
},
navigateUp = navigateUp,
scrollBehavior = scrollBehavior,
)
},
floatingActionButton = {
AnimatedVisibility(
true,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.imePadding(),
) {
ExtendedFloatingActionButton(
text = {
Text(
text = stringResource(
if (state.editing) MR.strings.action_apply else MR.strings.action_edit,
),
)
},
icon = {
Icon(
imageVector = if (state.editing) Icons.Filled.Check else Icons.Filled.Edit,
contentDescription = null,
)
},
onClick = { if (state.editing) endEditing() else beginEditing() },
expanded = true,
)
}
},
modifier = modifier
.imePadding(),
) { paddingValues ->
AnimatedVisibility(
state.editing,
enter = fadeIn(),
exit = fadeOut(),
) {
MangaNotesTextArea(
state = state,
onSave = onSave,
modifier = Modifier
.padding(
top = paddingValues.calculateTopPadding() + MaterialTheme.padding.small,
bottom = MaterialTheme.padding.small,
)
.padding(horizontal = MaterialTheme.padding.small)
.windowInsetsPadding(
WindowInsets.navigationBars
.only(WindowInsetsSides.Bottom),
),
)
}
AnimatedVisibility(
!state.editing && state.notes.isNullOrBlank(),
enter = fadeIn(),
exit = fadeOut(),
) {
EmptyScreen(
stringRes = MR.strings.information_no_notes,
modifier = Modifier.padding(paddingValues),
)
}
AnimatedVisibility(
!state.editing && !state.notes.isNullOrBlank(),
enter = fadeIn(),
exit = fadeOut(),
) {
RichText(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth()
.padding(
horizontal = MaterialTheme.padding.medium,
vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium,
),
style = RichTextStyle(
stringStyle = RichTextStringStyle(
linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary),
),
),
) {
Markdown(content = state.notes.orEmpty())
}
}
}
}

View File

@ -55,6 +55,7 @@ import eu.kanade.presentation.manga.components.MangaActionRow
import eu.kanade.presentation.manga.components.MangaBottomActionMenu import eu.kanade.presentation.manga.components.MangaBottomActionMenu
import eu.kanade.presentation.manga.components.MangaChapterListItem import eu.kanade.presentation.manga.components.MangaChapterListItem
import eu.kanade.presentation.manga.components.MangaInfoBox import eu.kanade.presentation.manga.components.MangaInfoBox
import eu.kanade.presentation.manga.components.MangaNotesSection
import eu.kanade.presentation.manga.components.MangaToolbar import eu.kanade.presentation.manga.components.MangaToolbar
import eu.kanade.presentation.manga.components.MissingChapterCountListItem import eu.kanade.presentation.manga.components.MissingChapterCountListItem
import eu.kanade.presentation.util.formatChapterNumber import eu.kanade.presentation.util.formatChapterNumber
@ -75,8 +76,7 @@ import tachiyomi.presentation.core.components.material.ExtendedFloatingActionBut
import tachiyomi.presentation.core.components.material.PullRefresh import tachiyomi.presentation.core.components.material.PullRefresh
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd import tachiyomi.presentation.core.util.shouldExpandFAB
import tachiyomi.presentation.core.util.isScrollingUp
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import java.time.Instant import java.time.Instant
@ -113,6 +113,8 @@ fun MangaScreen(
onEditCategoryClicked: (() -> Unit)?, onEditCategoryClicked: (() -> Unit)?,
onEditFetchIntervalClicked: (() -> Unit)?, onEditFetchIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?,
onNotesClicked: () -> Unit,
onNotesEditClicked: () -> Unit,
// For bottom action menu // For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit, onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
@ -161,6 +163,8 @@ fun MangaScreen(
onEditCategoryClicked = onEditCategoryClicked, onEditCategoryClicked = onEditCategoryClicked,
onEditIntervalClicked = onEditFetchIntervalClicked, onEditIntervalClicked = onEditFetchIntervalClicked,
onMigrateClicked = onMigrateClicked, onMigrateClicked = onMigrateClicked,
onNotesClicked = onNotesClicked,
onNotesEditClicked = onNotesEditClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
@ -196,6 +200,8 @@ fun MangaScreen(
onEditCategoryClicked = onEditCategoryClicked, onEditCategoryClicked = onEditCategoryClicked,
onEditIntervalClicked = onEditFetchIntervalClicked, onEditIntervalClicked = onEditFetchIntervalClicked,
onMigrateClicked = onMigrateClicked, onMigrateClicked = onMigrateClicked,
onNotesClicked = onNotesClicked,
onNotesEditClicked = onNotesEditClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
@ -241,6 +247,8 @@ private fun MangaScreenSmallImpl(
onEditCategoryClicked: (() -> Unit)?, onEditCategoryClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?, onEditIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?,
onNotesClicked: () -> Unit,
onNotesEditClicked: () -> Unit,
// For bottom action menu // For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit, onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
@ -306,6 +314,7 @@ private fun MangaScreenSmallImpl(
onClickEditCategory = onEditCategoryClicked, onClickEditCategory = onEditCategoryClicked,
onClickRefresh = onRefresh, onClickRefresh = onRefresh,
onClickMigrate = onMigrateClicked, onClickMigrate = onMigrateClicked,
onClickNotes = onNotesClicked,
actionModeCounter = selectedChapterCount, actionModeCounter = selectedChapterCount,
onSelectAll = { onAllChapterSelected(true) }, onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() }, onInvertSelection = { onInvertSelection() },
@ -346,7 +355,7 @@ private fun MangaScreenSmallImpl(
}, },
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) }, icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading, onClick = onContinueReading,
expanded = chapterListState.isScrollingUp() || chapterListState.isScrolledToEnd(), expanded = chapterListState.shouldExpandFAB(),
) )
} }
}, },
@ -356,7 +365,7 @@ private fun MangaScreenSmallImpl(
PullRefresh( PullRefresh(
refreshing = state.isRefreshingData, refreshing = state.isRefreshingData,
onRefresh = onRefresh, onRefresh = onRefresh,
enabled = { !isAnySelected }, enabled = !isAnySelected,
indicatorPadding = PaddingValues(top = topPadding), indicatorPadding = PaddingValues(top = topPadding),
) { ) {
val layoutDirection = LocalLayoutDirection.current val layoutDirection = LocalLayoutDirection.current
@ -381,13 +390,9 @@ private fun MangaScreenSmallImpl(
MangaInfoBox( MangaInfoBox(
isTabletUi = false, isTabletUi = false,
appBarPadding = topPadding, appBarPadding = topPadding,
title = state.manga.title, manga = state.manga,
author = state.manga.author,
artist = state.manga.artist,
sourceName = remember { state.source.getNameForMangaInfo() }, sourceName = remember { state.source.getNameForMangaInfo() },
isStubSource = remember { state.source is StubSource }, isStubSource = remember { state.source is StubSource },
coverDataProvider = { state.manga },
status = state.manga.status,
onCoverClick = onCoverClicked, onCoverClick = onCoverClicked,
doSearch = onSearch, doSearch = onSearch,
) )
@ -424,6 +429,16 @@ private fun MangaScreenSmallImpl(
) )
} }
item(
key = MangaScreenItem.NOTES_SECTION,
contentType = MangaScreenItem.NOTES_SECTION,
) {
MangaNotesSection(
onClickNotes = onNotesEditClicked,
content = state.manga.notes,
)
}
item( item(
key = MangaScreenItem.CHAPTER_HEADER, key = MangaScreenItem.CHAPTER_HEADER,
contentType = MangaScreenItem.CHAPTER_HEADER, contentType = MangaScreenItem.CHAPTER_HEADER,
@ -489,6 +504,8 @@ fun MangaScreenLargeImpl(
onEditCategoryClicked: (() -> Unit)?, onEditCategoryClicked: (() -> Unit)?,
onEditIntervalClicked: (() -> Unit)?, onEditIntervalClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?,
onNotesClicked: () -> Unit,
onNotesEditClicked: () -> Unit,
// For bottom action menu // For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit, onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
@ -547,6 +564,7 @@ fun MangaScreenLargeImpl(
onClickEditCategory = onEditCategoryClicked, onClickEditCategory = onEditCategoryClicked,
onClickRefresh = onRefresh, onClickRefresh = onRefresh,
onClickMigrate = onMigrateClicked, onClickMigrate = onMigrateClicked,
onClickNotes = onNotesClicked,
actionModeCounter = selectedChapterCount, actionModeCounter = selectedChapterCount,
onSelectAll = { onAllChapterSelected(true) }, onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() }, onInvertSelection = { onInvertSelection() },
@ -594,7 +612,7 @@ fun MangaScreenLargeImpl(
}, },
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) }, icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading, onClick = onContinueReading,
expanded = chapterListState.isScrollingUp() || chapterListState.isScrolledToEnd(), expanded = chapterListState.shouldExpandFAB(),
) )
} }
}, },
@ -602,7 +620,7 @@ fun MangaScreenLargeImpl(
PullRefresh( PullRefresh(
refreshing = state.isRefreshingData, refreshing = state.isRefreshingData,
onRefresh = onRefresh, onRefresh = onRefresh,
enabled = { !isAnySelected }, enabled = !isAnySelected,
indicatorPadding = PaddingValues( indicatorPadding = PaddingValues(
start = insetPadding.calculateStartPadding(layoutDirection), start = insetPadding.calculateStartPadding(layoutDirection),
top = with(density) { topBarHeight.toDp() }, top = with(density) { topBarHeight.toDp() },
@ -623,13 +641,9 @@ fun MangaScreenLargeImpl(
MangaInfoBox( MangaInfoBox(
isTabletUi = true, isTabletUi = true,
appBarPadding = contentPadding.calculateTopPadding(), appBarPadding = contentPadding.calculateTopPadding(),
title = state.manga.title, manga = state.manga,
author = state.manga.author,
artist = state.manga.artist,
sourceName = remember { state.source.getNameForMangaInfo() }, sourceName = remember { state.source.getNameForMangaInfo() },
isStubSource = remember { state.source is StubSource }, isStubSource = remember { state.source is StubSource },
coverDataProvider = { state.manga },
status = state.manga.status,
onCoverClick = onCoverClicked, onCoverClick = onCoverClicked,
doSearch = onSearch, doSearch = onSearch,
) )
@ -652,6 +666,10 @@ fun MangaScreenLargeImpl(
onTagSearch = onTagSearch, onTagSearch = onTagSearch,
onCopyTagToClipboard = onCopyTagToClipboard, onCopyTagToClipboard = onCopyTagToClipboard,
) )
MangaNotesSection(
onClickNotes = onNotesEditClicked,
content = state.manga.notes,
)
} }
}, },
endContent = { endContent = {

View File

@ -17,6 +17,7 @@ enum class MangaScreenItem {
INFO_BOX, INFO_BOX,
ACTION_ROW, ACTION_ROW,
DESCRIPTION_WITH_TAG, DESCRIPTION_WITH_TAG,
NOTES_SECTION,
CHAPTER_HEADER, CHAPTER_HEADER,
CHAPTER, CHAPTER,
} }

View File

@ -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

View File

@ -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),
) )
} }

View File

@ -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
@ -30,11 +29,11 @@ import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.DoneAll import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.RemoveDone import androidx.compose.material.icons.outlined.RemoveDone
import androidx.compose.material.ripple
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
@ -82,7 +81,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) }
@ -191,7 +190,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,
@ -238,7 +237,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 = remember { mutableStateListOf(false, false, false, false, false) } val confirm = remember { mutableStateListOf(false, false, false, false, false) }

View File

@ -30,7 +30,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
@ -41,8 +40,8 @@ import eu.kanade.tachiyomi.data.download.model.Download
import me.saket.swipe.SwipeableActionsBox import me.saket.swipe.SwipeableActionsBox
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ReadItemAlpha import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.selectedBackground import tachiyomi.presentation.core.util.selectedBackground
@ -66,9 +65,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,
@ -133,15 +129,20 @@ fun MangaChapterListItem(
Text( Text(
text = title, text = title,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = LocalContentColor.current.copy(alpha = textAlpha),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
onTextLayout = { textHeight = it.size.height }, onTextLayout = { textHeight = it.size.height },
color = LocalContentColor.current.copy(alpha = if (read) DISABLED_ALPHA else 1f),
) )
} }
Row(modifier = Modifier.alpha(textSubtitleAlpha)) { Row {
ProvideTextStyle(value = MaterialTheme.typography.bodySmall) { val subtitleStyle = MaterialTheme.typography.bodySmall
.merge(
color = LocalContentColor.current
.copy(alpha = if (read) DISABLED_ALPHA else SECONDARY_ALPHA),
)
ProvideTextStyle(value = subtitleStyle) {
if (date != null) { if (date != null) {
Text( Text(
text = date, text = date,
@ -155,7 +156,7 @@ fun MangaChapterListItem(
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) DotSeparatorText() if (scanlator != null) DotSeparatorText()
} }

View File

@ -37,6 +37,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
@ -55,7 +56,7 @@ import tachiyomi.presentation.core.util.clickableNoIndication
@Composable @Composable
fun MangaCoverDialog( fun MangaCoverDialog(
coverDataProvider: () -> Manga, manga: Manga,
isCustomCover: Boolean, isCustomCover: Boolean,
snackbarHostState: SnackbarHostState, snackbarHostState: SnackbarHostState,
onShareClick: () -> Unit, onShareClick: () -> Unit,
@ -165,7 +166,7 @@ fun MangaCoverDialog(
}, },
update = { view -> update = { view ->
val request = ImageRequest.Builder(view.context) val request = ImageRequest.Builder(view.context)
.data(coverDataProvider()) .data(manga)
.size(Size.ORIGINAL) .size(Size.ORIGINAL)
.memoryCachePolicy(CachePolicy.DISABLED) .memoryCachePolicy(CachePolicy.DISABLED)
.target { image -> .target { image ->

View File

@ -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))

View File

@ -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
@ -42,7 +43,7 @@ import androidx.compose.material.icons.outlined.Sync
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.ProvideTextStyle
@ -74,12 +75,15 @@ 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 coil3.compose.AsyncImage import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import coil3.request.crossfade
import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.system.copyToClipboard 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.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
@ -96,13 +100,9 @@ private val whitespaceLineRegex = Regex("[\\r\\n]{2,}", setOf(RegexOption.MULTIL
fun MangaInfoBox( fun MangaInfoBox(
isTabletUi: Boolean, isTabletUi: Boolean,
appBarPadding: Dp, appBarPadding: Dp,
title: String, manga: Manga,
author: String?,
artist: String?,
sourceName: String, sourceName: String,
isStubSource: Boolean, isStubSource: Boolean,
coverDataProvider: () -> Manga,
status: Long,
onCoverClick: () -> Unit, onCoverClick: () -> Unit,
doSearch: (query: String, global: Boolean) -> Unit, doSearch: (query: String, global: Boolean) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -114,7 +114,10 @@ fun MangaInfoBox(
MaterialTheme.colorScheme.background, MaterialTheme.colorScheme.background,
) )
AsyncImage( AsyncImage(
model = coverDataProvider(), model = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
@ -134,28 +137,20 @@ fun MangaInfoBox(
if (!isTabletUi) { if (!isTabletUi) {
MangaAndSourceTitlesSmall( MangaAndSourceTitlesSmall(
appBarPadding = appBarPadding, appBarPadding = appBarPadding,
coverDataProvider = coverDataProvider, manga = manga,
onCoverClick = onCoverClick,
title = title,
doSearch = doSearch,
author = author,
artist = artist,
status = status,
sourceName = sourceName, sourceName = sourceName,
isStubSource = isStubSource, isStubSource = isStubSource,
onCoverClick = onCoverClick,
doSearch = doSearch,
) )
} else { } else {
MangaAndSourceTitlesLarge( MangaAndSourceTitlesLarge(
appBarPadding = appBarPadding, appBarPadding = appBarPadding,
coverDataProvider = coverDataProvider, manga = manga,
onCoverClick = onCoverClick,
title = title,
doSearch = doSearch,
author = author,
artist = artist,
status = status,
sourceName = sourceName, sourceName = sourceName,
isStubSource = isStubSource, isStubSource = isStubSource,
onCoverClick = onCoverClick,
doSearch = doSearch,
) )
} }
} }
@ -176,7 +171,7 @@ fun MangaActionRow(
onEditCategory: (() -> Unit)?, onEditCategory: (() -> Unit)?,
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) {
@ -271,7 +266,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("") }
@ -335,15 +331,11 @@ fun ExpandableMangaDescription(
@Composable @Composable
private fun MangaAndSourceTitlesLarge( private fun MangaAndSourceTitlesLarge(
appBarPadding: Dp, appBarPadding: Dp,
coverDataProvider: () -> Manga, manga: Manga,
onCoverClick: () -> Unit,
title: String,
doSearch: (query: String, global: Boolean) -> Unit,
author: String?,
artist: String?,
status: Long,
sourceName: String, sourceName: String,
isStubSource: Boolean, isStubSource: Boolean,
onCoverClick: () -> Unit,
doSearch: (query: String, global: Boolean) -> Unit,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@ -353,19 +345,22 @@ private fun MangaAndSourceTitlesLarge(
) { ) {
MangaCover.Book( MangaCover.Book(
modifier = Modifier.fillMaxWidth(0.65f), modifier = Modifier.fillMaxWidth(0.65f),
data = coverDataProvider(), data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover), contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick, onClick = onCoverClick,
) )
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
MangaContentInfo( MangaContentInfo(
title = title, title = manga.title,
doSearch = doSearch, author = manga.author,
author = author, artist = manga.artist,
artist = artist, status = manga.status,
status = status,
sourceName = sourceName, sourceName = sourceName,
isStubSource = isStubSource, isStubSource = isStubSource,
doSearch = doSearch,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
} }
@ -374,15 +369,11 @@ private fun MangaAndSourceTitlesLarge(
@Composable @Composable
private fun MangaAndSourceTitlesSmall( private fun MangaAndSourceTitlesSmall(
appBarPadding: Dp, appBarPadding: Dp,
coverDataProvider: () -> Manga, manga: Manga,
onCoverClick: () -> Unit,
title: String,
doSearch: (query: String, global: Boolean) -> Unit,
author: String?,
artist: String?,
status: Long,
sourceName: String, sourceName: String,
isStubSource: Boolean, isStubSource: Boolean,
onCoverClick: () -> Unit,
doSearch: (query: String, global: Boolean) -> Unit,
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -395,7 +386,10 @@ private fun MangaAndSourceTitlesSmall(
modifier = Modifier modifier = Modifier
.sizeIn(maxWidth = 100.dp) .sizeIn(maxWidth = 100.dp)
.align(Alignment.Top), .align(Alignment.Top),
data = coverDataProvider(), data = ImageRequest.Builder(LocalContext.current)
.data(manga)
.crossfade(true)
.build(),
contentDescription = stringResource(MR.strings.manga_cover), contentDescription = stringResource(MR.strings.manga_cover),
onClick = onCoverClick, onClick = onCoverClick,
) )
@ -403,13 +397,13 @@ private fun MangaAndSourceTitlesSmall(
verticalArrangement = Arrangement.spacedBy(2.dp), verticalArrangement = Arrangement.spacedBy(2.dp),
) { ) {
MangaContentInfo( MangaContentInfo(
title = title, title = manga.title,
doSearch = doSearch, author = manga.author,
author = author, artist = manga.artist,
artist = artist, status = manga.status,
status = status,
sourceName = sourceName, sourceName = sourceName,
isStubSource = isStubSource, isStubSource = isStubSource,
doSearch = doSearch,
) )
} }
} }
@ -418,12 +412,12 @@ private fun MangaAndSourceTitlesSmall(
@Composable @Composable
private fun ColumnScope.MangaContentInfo( private fun ColumnScope.MangaContentInfo(
title: String, title: String,
doSearch: (query: String, global: Boolean) -> Unit,
author: String?, author: String?,
artist: String?, artist: String?,
status: Long, status: Long,
sourceName: String, sourceName: String,
isStubSource: Boolean, isStubSource: Boolean,
doSearch: (query: String, global: Boolean) -> Unit,
textAlign: TextAlign? = LocalTextStyle.current.textAlign, textAlign: TextAlign? = LocalTextStyle.current.textAlign,
) { ) {
val context = LocalContext.current val context = LocalContext.current
@ -649,7 +643,7 @@ private fun TagsChip(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { CompositionLocalProvider(LocalMinimumInteractiveComponentSize provides 0.dp) {
SuggestionChip( SuggestionChip(
modifier = modifier, modifier = modifier,
onClick = onClick, onClick = onClick,

View File

@ -0,0 +1,101 @@
package eu.kanade.presentation.manga.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import com.halilibo.richtext.markdown.Markdown
import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.string.RichTextStringStyle
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Button
import tachiyomi.presentation.core.components.material.ButtonDefaults
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
@Composable
fun MangaNotesSection(
onClickNotes: () -> Unit,
content: String?,
modifier: Modifier = Modifier,
) {
Column(modifier.fillMaxWidth()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth(),
) {
if (!content.isNullOrBlank()) {
RichText(
modifier = Modifier
.fillMaxWidth()
.padding(MaterialTheme.padding.medium),
style = RichTextStyle(
stringStyle = RichTextStringStyle(
linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary),
),
),
) {
Markdown(content = content)
}
}
Button(
onClick = onClickNotes,
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.primary,
),
shape = RoundedCornerShape(8.dp),
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 4.dp),
) {
Row(
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Outlined.Edit,
contentDescription = null,
modifier = Modifier
.size(16.dp),
)
Text(
stringResource(
if (content.isNullOrBlank()) {
MR.strings.action_add_notes
} else {
MR.strings.action_edit_notes
},
),
)
}
}
}
}
}
@PreviewLightDark
@Composable
private fun MangaNotesSectionPreview() {
MangaNotesSection(
onClickNotes = {},
content = "# Hello world\ntest1234 hi there!",
)
}

View File

@ -0,0 +1,78 @@
package eu.kanade.presentation.manga.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState
private const val MAX_LENGTH = 10_000
@Composable
fun MangaNotesTextArea(
state: MangaNotesScreenState.Success,
onSave: (String) -> Unit,
modifier: Modifier = Modifier,
) {
var text by remember {
mutableStateOf(TextFieldValue(state.notes.orEmpty(), TextRange(Int.MAX_VALUE)))
}
val focusRequester = remember { FocusRequester() }
Box(
modifier = modifier
.fillMaxSize(),
) {
OutlinedTextField(
value = text,
onValueChange = { if (it.text.length <= MAX_LENGTH) text = it },
modifier = Modifier
.fillMaxSize()
.focusRequester(focusRequester),
supportingText = {
val displayWarning = text.text.length > MAX_LENGTH / 10 * 9
if (!displayWarning) {
Text(
text = "0",
modifier = Modifier.alpha(0f),
)
}
AnimatedVisibility(
displayWarning,
enter = fadeIn(),
exit = fadeOut(),
) {
Text(
text = "${text.text.length} / $MAX_LENGTH",
)
}
},
)
}
LaunchedEffect(focusRequester) {
focusRequester.requestFocus()
}
DisposableEffect(Unit) {
onDispose {
onSave(text.text)
}
}
}

View File

@ -44,6 +44,7 @@ fun MangaToolbar(
onClickEditCategory: (() -> Unit)?, onClickEditCategory: (() -> Unit)?,
onClickRefresh: () -> Unit, onClickRefresh: () -> Unit,
onClickMigrate: (() -> Unit)?, onClickMigrate: (() -> Unit)?,
onClickNotes: () -> Unit,
// For action mode // For action mode
actionModeCounter: Int, actionModeCounter: Int,
@ -149,6 +150,13 @@ fun MangaToolbar(
), ),
) )
} }
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_notes),
onClick = onClickNotes,
),
)
} }
.build(), .build(),
) )

View File

@ -31,8 +31,6 @@ import tachiyomi.i18n.MR
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.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrolledToStart
@Composable @Composable
fun ScanlatorFilterDialog( fun ScanlatorFilterDialog(
@ -96,8 +94,8 @@ fun ScanlatorFilterDialog(
} }
} }
} }
if (!state.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter)) if (state.canScrollBackward) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
if (!state.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter)) if (state.canScrollForward) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
} }
}, },
properties = DialogProperties( properties = DialogProperties(
@ -110,8 +108,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) {

View File

@ -75,7 +75,7 @@ private fun NewUpdateScreenPreview() {
changelogInfo = """ changelogInfo = """
## Yay ## Yay
Foobar Foobar
### More info ### More info
- Hello - Hello
- World - World

View File

@ -28,11 +28,11 @@ 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 androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.LocalLifecycleOwner
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission
import tachiyomi.i18n.MR import tachiyomi.i18n.MR

View File

@ -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)

View File

@ -264,6 +264,7 @@ object SettingsAdvancedScreen : SearchableSettings {
try { try {
// OkHttp checks for valid values internally // OkHttp checks for valid values internally
Headers.Builder().add("User-Agent", it) Headers.Builder().add("User-Agent", it)
context.toast(MR.strings.requires_app_restart)
} catch (_: IllegalArgumentException) { } catch (_: IllegalArgumentException) {
context.toast(MR.strings.error_user_agent_string_invalid) context.toast(MR.strings.error_user_agent_string_invalid)
return@EditTextPreference false return@EditTextPreference false
@ -340,7 +341,7 @@ object SettingsAdvancedScreen : SearchableSettings {
chooseColorProfile.launch(arrayOf("*/*")) chooseColorProfile.launch(arrayOf("*/*"))
}, },
), ),
) ),
) )
} }

View File

@ -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.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -13,11 +14,11 @@ import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
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.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.pluralStringResource 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 uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -33,7 +34,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)
return listOf( return listOf(
Preference.PreferenceGroup( Preference.PreferenceGroup(
@ -45,7 +48,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())
}, },

View File

@ -111,7 +111,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())

View File

@ -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(

View File

@ -71,9 +71,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() }
@ -95,7 +92,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(

View File

@ -14,6 +14,7 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf 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.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
@ -61,12 +62,8 @@ object SettingsReaderScreen : SearchableSettings {
pref = readerPref.pageTransitions(), pref = readerPref.pageTransitions(),
title = stringResource(MR.strings.pref_page_transitions), title = stringResource(MR.strings.pref_page_transitions),
), ),
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),
@ -122,6 +119,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(

View File

@ -13,8 +13,10 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.clearText
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.Close
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -28,11 +30,8 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.NonRestartableComposable import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
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.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
@ -43,7 +42,6 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -88,7 +86,7 @@ class SettingsSearchScreen : Screen() {
focusRequester.requestFocus() focusRequester.requestFocus()
} }
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue()) } val textFieldState = rememberTextFieldState()
Scaffold( Scaffold(
topBar = { topBar = {
Column { Column {
@ -103,20 +101,19 @@ class SettingsSearchScreen : Screen() {
}, },
title = { title = {
BasicTextField( BasicTextField(
value = textFieldValue, state = textFieldState,
onValueChange = { textFieldValue = it },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(focusRequester) .focusRequester(focusRequester)
.runOnEnterKeyPressed(action = focusManager::clearFocus), .runOnEnterKeyPressed(action = focusManager::clearFocus),
textStyle = MaterialTheme.typography.bodyLarge textStyle = MaterialTheme.typography.bodyLarge
.copy(color = MaterialTheme.colorScheme.onSurface), .copy(color = MaterialTheme.colorScheme.onSurface),
singleLine = true, lineLimits = TextFieldLineLimits.SingleLine,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(onSearch = { focusManager.clearFocus() }), onKeyboardAction = { focusManager.clearFocus() },
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
decorationBox = { decorator = {
if (textFieldValue.text.isEmpty()) { if (textFieldState.text.isEmpty()) {
Text( Text(
text = stringResource(MR.strings.action_search_settings), text = stringResource(MR.strings.action_search_settings),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
@ -128,8 +125,8 @@ class SettingsSearchScreen : Screen() {
) )
}, },
actions = { actions = {
if (textFieldValue.text.isNotEmpty()) { if (textFieldState.text.isNotEmpty()) {
IconButton(onClick = { textFieldValue = TextFieldValue() }) { IconButton(onClick = { textFieldState.clearText() }) {
Icon( Icon(
imageVector = Icons.Outlined.Close, imageVector = Icons.Outlined.Close,
contentDescription = null, contentDescription = null,
@ -144,7 +141,7 @@ class SettingsSearchScreen : Screen() {
}, },
) { contentPadding -> ) { contentPadding ->
SearchResult( SearchResult(
searchKey = textFieldValue.text, searchKey = textFieldState.text.toString(),
listState = listState, listState = listState,
contentPadding = contentPadding, contentPadding = contentPadding,
) { result -> ) { result ->

View File

@ -55,10 +55,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() {
@ -269,11 +268,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
} }

View File

@ -37,7 +37,7 @@ class OpenSourceLicensesScreen : Screen() {
name = it.name, name = it.name,
website = it.website, website = it.website,
license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(), license = it.licenses.firstOrNull()?.htmlReadyLicenseContent.orEmpty(),
) ),
) )
}, },
) )

View File

@ -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) {

View File

@ -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() {

View File

@ -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,
) { ) {
@ -43,9 +46,10 @@ fun ExtensionReposContent(
repos.forEach { repos.forEach {
item { item {
ExtensionRepoListItem( ExtensionRepoListItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItem(),
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)
}, },
) { ) {

View File

@ -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))
}
},
)
}

View File

@ -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,
) )
} }

View File

@ -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
@ -68,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 {
@ -103,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,

View File

@ -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()

View File

@ -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)
}, },
), ),
), ),

View File

@ -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(),

View File

@ -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()

View File

@ -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,
) { ) {

View File

@ -26,8 +26,6 @@ import androidx.compose.ui.unit.dp
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrolledToStart
@Composable @Composable
fun <T> ListPreferenceWidget( fun <T> ListPreferenceWidget(
@ -69,8 +67,8 @@ fun <T> ListPreferenceWidget(
} }
} }
} }
if (!state.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter)) if (state.canScrollBackward) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
if (!state.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter)) if (state.canScrollForward) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
} }
}, },
confirmButton = { confirmButton = {

View File

@ -30,11 +30,11 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrolledToStart
private enum class State { private enum class State {
CHECKED, INVERSED, UNCHECKED CHECKED,
INVERSED,
UNCHECKED,
} }
@Composable @Composable
@ -115,16 +115,8 @@ fun <T> TriStateListDialog(
} }
} }
if (!listState.isScrolledToStart()) { if (listState.canScrollBackward) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
HorizontalDivider( if (listState.canScrollForward) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
modifier = Modifier.align(Alignment.TopCenter),
)
}
if (!listState.isScrolledToEnd()) {
HorizontalDivider(
modifier = Modifier.align(Alignment.BottomCenter),
)
}
} }
} }
}, },

View File

@ -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,
) )

View File

@ -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,

View File

@ -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)
}
} }
} }

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Arrangement
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
@ -28,14 +29,12 @@ import tachiyomi.presentation.core.i18n.stringResource
fun ReaderPageActionsDialog( fun ReaderPageActionsDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
onSetAsCover: () -> Unit, onSetAsCover: () -> Unit,
onShare: () -> Unit, onShare: (Boolean) -> Unit,
onSave: () -> Unit, onSave: () -> Unit,
) { ) {
var showSetCoverDialog by remember { mutableStateOf(false) } var showSetCoverDialog by remember { mutableStateOf(false) }
AdaptiveSheet( AdaptiveSheet(onDismissRequest = onDismissRequest) {
onDismissRequest = onDismissRequest,
) {
Row( Row(
modifier = Modifier.padding(vertical = 16.dp), modifier = Modifier.padding(vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
@ -46,12 +45,21 @@ fun ReaderPageActionsDialog(
icon = Icons.Outlined.Photo, icon = Icons.Outlined.Photo,
onClick = { showSetCoverDialog = true }, onClick = { showSetCoverDialog = true },
) )
ActionButton(
modifier = Modifier.weight(1f),
title = stringResource(MR.strings.action_copy_to_clipboard),
icon = Icons.Outlined.ContentCopy,
onClick = {
onShare(true)
onDismissRequest()
},
)
ActionButton( ActionButton(
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
title = stringResource(MR.strings.action_share), title = stringResource(MR.strings.action_share),
icon = Icons.Outlined.Share, icon = Icons.Outlined.Share,
onClick = { onClick = {
onShare() onShare(false)
onDismissRequest() onDismissRequest()
}, },
) )

View File

@ -45,6 +45,7 @@ fun ReaderAppBars(
onClickTopAppBar: () -> Unit, onClickTopAppBar: () -> Unit,
bookmarked: Boolean, bookmarked: Boolean,
onToggleBookmarked: () -> Unit, onToggleBookmarked: () -> Unit,
onOpenInBrowser: (() -> Unit)?,
onOpenInWebView: (() -> Unit)?, onOpenInWebView: (() -> Unit)?,
onShare: (() -> Unit)?, onShare: (() -> Unit)?,
@ -119,6 +120,14 @@ fun ReaderAppBars(
onClick = onToggleBookmarked, onClick = onToggleBookmarked,
), ),
) )
onOpenInBrowser?.let {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_open_in_browser),
onClick = it,
),
)
}
onOpenInWebView?.let { onOpenInWebView?.let {
add( add(
AppBar.OverflowAction( AppBar.OverflowAction(

View File

@ -23,15 +23,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
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.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.util.isTabletUi import eu.kanade.presentation.util.isTabletUi
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@ -49,7 +53,7 @@ fun ChapterNavigator(
onSliderValueChange: (Int) -> Unit, onSliderValueChange: (Int) -> Unit,
) { ) {
val isTabletUi = isTabletUi() val isTabletUi = isTabletUi()
val horizontalPadding = if (isTabletUi) 24.dp else 16.dp val horizontalPadding = if (isTabletUi) 24.dp else 8.dp
val layoutDirection = if (isRtl) LayoutDirection.Rtl else LayoutDirection.Ltr val layoutDirection = if (isRtl) LayoutDirection.Rtl else LayoutDirection.Ltr
val haptic = LocalHapticFeedback.current val haptic = LocalHapticFeedback.current
@ -137,3 +141,21 @@ fun ChapterNavigator(
} }
} }
} }
@Preview
@Composable
private fun ChapterNavigatorPreview() {
var currentPage by remember { mutableIntStateOf(1) }
TachiyomiPreviewTheme {
ChapterNavigator(
isRtl = false,
onNextChapter = {},
enabledNext = true,
onPreviousChapter = {},
enabledPrevious = true,
currentPage = currentPage,
totalPages = 10,
onSliderValueChange = { currentPage = it },
)
}
}

View File

@ -5,10 +5,13 @@ 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.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
@ -19,9 +22,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(
@ -73,4 +94,33 @@ 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)) },
)
}
}
}
} }

View File

@ -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,
) )
} }
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

View File

@ -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),
) )
} }

Some files were not shown because too many files have changed in this diff Show More