Compare commits

...

176 Commits

Author SHA1 Message Date
Jobobby04 2f54f00bf7 Revert "Minor fix for history url"
This reverts commit 28edaca869.
2024-03-17 20:08:03 -04:00
ɴᴇᴋᴏ 87feb58055 Add files via upload (#1120) 2024-03-17 19:57:33 -04:00
Jobobby04 28edaca869 Minor fix for history url 2024-03-17 19:56:06 -04:00
Jobobby04 d14f012bbb Update firebase 2024-03-17 19:53:23 -04:00
Jobobby04 adc6bbf54f Minor doc fix 2024-03-17 19:53:12 -04:00
Jobobby04 2b064baca1 Update baseline 2024-03-17 19:52:59 -04:00
Jobobby04 983a80ba42 History url is not globally unique 2024-03-17 19:52:38 -04:00
Fermín Cirella 911e959fcf Add option to reset custom manga info (#1118)
* Add option to reset custom manga info

* Remove extra line

* Update app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt

---------

Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com>
2024-03-16 23:59:19 -04:00
KaiserBh a425cae73b fix: The trigger for library update wasn't working properly. (#1119)
Missed them, so it was always updating library without actually syncing even when the trigger was on.

Signed-off-by: KaiserBh <kaiserbh@proton.me>
2024-03-16 23:56:00 -04:00
Jobobby04 d12a9d329b [skip ci] Add instructions for supporting Cloud Sync Google Drive Impl 2024-03-16 15:59:00 -04:00
Jobobby04 9018757496 Oops 2024-03-16 13:47:55 -04:00
ɴᴇᴋᴏ b0d91fa83f Update zh-rTW (#1117)
* Update plurals.xml

* Update strings.xml

* Update plurals.xml

* Update strings.xml

* Update plurals.xml

* Update plurals.xml

* Update strings.xml

* Update plurals.xml

* plurals.xml

* plurals.xml

* Delete i18n/src/commonMain/resources/MR/zh-rTW/strings.xml

* Add files via upload
2024-03-16 13:46:27 -04:00
Jobobby04 1caa929aa0 Add preview prefix 2024-03-16 13:45:47 -04:00
Jobobby04 04e5be12e1 Write client_secrets.json on build 2024-03-16 13:37:41 -04:00
Jobobby04 1136644a57 Remove Client Secrets 2024-03-16 13:32:58 -04:00
Jobobby04 d70258b956 Cleanup sync code 2024-03-16 13:14:40 -04:00
Jobobby04 54cb379a50 Update Detekt baseline 2024-03-16 12:36:51 -04:00
Jobobby04 0e959c4594 Move strings to SY strings 2024-03-16 12:23:30 -04:00
Shamicen 6719f22eff implement mihonapp/mihon#326 (#1104)
* implement mihonapp/mihon#326

Archives are now being read from channels

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

* disable parallelisms for loading into memory

* switched to mutex

* detekt changes

* more detekt baseline changes

---------

Co-authored-by: FooIbar <118464521+FooIbar@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-03-16 11:59:00 -04:00
Jobobby04 45711cd394 Update Client Secret 2024-03-16 11:55:48 -04:00
KaiserBh 334e9fb680 feat: add cross device sync (#1005)
* feat: add cross device sync.

* chore: add google api.

* chore: add SY specifics.

* feat: add backupSource, backupPref, and "SY" backupSavedSearches.

I forgot to add the data into the merging logic, So remote always have empty value :(. Better late than never.

* feat(sync): Allow to choose what to sync.

Various improvement and added the option to choose what they want to sync. Added sync library button to LibraryTab as well.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* oops.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* refactor: fix up the sync triggers, and update imports.

* refactor

* chore: review pointers.

* refactor: update imports

* refactor: add more error guard for gdrive.

Also changed it to be app specific, we don't want them to use sync data from SY or other forks as some of the model and backup is different. So if people using other forks they should use the same data and not mismatch.

* fix: conflict and refactor.

* refactor: update imports.

* chore: fix some of detekt error.

* refactor: add breaks and max retries.

I think we were reaching deadlock or infinite loop causing the sync to go forever.

* feat: db changes to accommodate new syncing logic.

Using timestamp to sync is a bit skewed due to system clock etc and therefore there was a lot of issues with it such as removing a manga that shouldn't have been removed. Marking chapters as unread even though it was marked as a read. Hopefully by using versioning system it should eliminate those issues.

* chore: add migrations

* chore: version and is_syncing fields.

* chore: add SY only stuff.

* fix: oops wrong index.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* chore: review pointers.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* chore: remove the option to reset timestamp

We don't need this anymore since we are utilizing versioning system.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* refactor: Forgot to use the new versioning system.

I forgot to cherry pick this from mihon branch.

* chore: remove isSyncing from Chapter/Manga model.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* chore: remove unused import.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* chore: remove isSyncing leftover.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* chore: remove isSyncing.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

* refactor: make sure the manga version is bumped.

When there is changes in the chapters table such as reading or updating last read page we should bump the manga version. This way the manga is synced properly as in the History and last_read history is synced properly. This should fix the sorting issue.

Signed-off-by: KaiserBh <kaiserbh@proton.me>

---------

Signed-off-by: KaiserBh <kaiserbh@proton.me>
2024-03-16 11:53:20 -04:00
ɴᴇᴋᴏ 6e0bc981a6 Update README.md (#1113)
Tachi -> Mihon
2024-03-15 20:36:28 -04:00
Cuong M. Tran b7e55bc9f8 Update detekt's baseline & run detekt for future build (#1106)
* Update detekt baseline from mihon

* Update detekt baseline to current code & enable gradle's detekt task for future build
2024-03-15 20:35:39 -04:00
Shamicen a069e577ba Change preferences containing passwords to appStateKeys (#1083)
* Change preferences containing passwords to appStateKeys

* Change versionCode to 65

* fix merge conflict and add instructions to get library back after migration
2024-03-15 20:28:37 -04:00
Jobobby04 0eb622643b Use github run_number to create tag 2024-03-15 20:18:44 -04:00
Jobobby04 d93d0eea89 Shorten Anilst UA(hopefully Cloudflare likes this one) 2024-03-15 20:14:37 -04:00
AntsyLich 82846205b2 Fix crash in track date selection dialog
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit f08713587685ddb27cb8ce7184e2dd21ae7968ae)
2024-03-15 20:08:14 -04:00
AntsyLich 4a4fecb1e8 Bump default user agent
(cherry picked from commit f66f52c244b786ae09f8e4ae683575907068d15f)
2024-03-15 20:08:06 -04:00
renovate[bot] ee6bc20f27 Update dependency io.nlopez.compose.rules:detekt to v0.3.12 (#500)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 0d6f426dbd8874c7861b6cc245f9e6ff43dbbe2c)
2024-03-15 20:07:56 -04:00
Weblate (bot) 446a5cd5b3 Translations update from Hosted Weblate (#445)
* Translated using Weblate (Esperanto)

Currently translated at 65.1% (517 of 794 strings)

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

* Translated using Weblate (Spanish)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Croatian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Serbian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (794 of 794 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% (794 of 794 strings)

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

* 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 (Croatian)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Serbian)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Filipino)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Filipino)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Polish)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Polish)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Russian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Russian)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Japanese)

Currently translated at 100.0% (794 of 794 strings)

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

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (18 of 18 strings)

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

* Translated using Weblate (Dutch)

Currently translated at 94.2% (748 of 794 strings)

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

* Translated using Weblate (Dutch)

Currently translated at 94.4% (17 of 18 strings)

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

* 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/

---------

Co-authored-by: Radoŝ Porka <animatorzPolski@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: David Katrinka <davidkatrinka1995@gmail.com>
Co-authored-by: gekka <1778962971@qq.com>
Co-authored-by: ɴᴇᴋᴏ <s99095lkjjim@gmail.com>
Co-authored-by: Infy's Tagalog Translations <ced.paltep10@gmail.com>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Co-authored-by: FateXBlood <zecrofelix@gmail.com>
Co-authored-by: Eryk Michalak <gnu.ewm@protonmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
Co-authored-by: Tim Bolhoeve <bolhoevetim@gmail.com>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
(cherry picked from commit edd7d0522c305a8aec8ab524214d3a26106dac31)

# Conflicts:
#	i18n/src/commonMain/resources/MR/hu/strings.xml
#	i18n/src/commonMain/resources/MR/sr/strings.xml
#	i18n/src/commonMain/resources/MR/zh-rTW/strings.xml
2024-03-15 20:07:49 -04:00
KaiserBh cdb07c893b feat: db changes to accommodate new cross device syncing logic. (#450)
* feat: db changes to accommodate new syncing logic.

Using timestamp to sync is a bit skewed due to system clock etc and therefore there was a lot of issues with it such as removing a manga that shouldn't have been removed. Marking chapters as unread even though it was marked as a read. Hopefully by using versioning system it should eliminate those issues.

* chore: add new line.

* chore: remove isSyncing from Chapter/Manga model.

* chore: remove isSyncing leftover.

* chore: remove isSyncing.

* refactor: remove isSync guard.

Just use it directly to 1 now since we don't have the isSyncing field in Manga or Chapter.

* Lint and stuff

* Add missing ,

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 4ae9dbe52487185ef9ee25f58fabe5025bb2278b)

# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupChapter.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupManga.kt
#	data/src/main/java/tachiyomi/data/chapter/ChapterRepositoryImpl.kt
#	data/src/main/sqldelight/tachiyomi/migrations/2.sqm
#	domain/src/main/java/tachiyomi/domain/manga/model/MangaUpdate.kt
2024-03-15 20:06:20 -04:00
Redjard a4d88515fb Fix shizuku being buggy for multi user setups (#494)
* Fix #493

Fetch the current userid separately because shizuku always runs as the main user and would otherwise install and update for the main user

* Update app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 402e579a69391e7633754066eb8e6480bd9f247d)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt
2024-03-15 19:55:36 -04:00
FooIbar 345d0821c6 Fix dual page split for local source (#485)
`InputStream.available()` is implementation-dependent, should never assume it will return the total number of bytes in the stream.

(cherry picked from commit d0e64d3a66d227ca61fc8d956b03cab5ac3b84f0)

# Conflicts:
#	core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt
2024-03-15 19:54:06 -04:00
az4521 a9fd1f8811 Update image-decoder (#466)
Use newer image-decoder lib

fixes crashing when trying to load corrupt images below 12 bytes in size

(cherry picked from commit 154f4d327caea9ceef6a53e739324ee0a9ed959d)

# Conflicts:
#	gradle/libs.versions.toml
2024-03-15 19:53:26 -04:00
Jobobby04 31e5ba4caf Fix multiple issues regarding sources loading too late 2024-03-15 19:51:56 -04:00
Jobobby04 202900edf0 Fix build error after Android Gradle 8.3 2024-03-03 22:39:58 -05:00
AntsyLich f79959c7bc Fix ChapterDownloadIndicator
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit d8b9a9f593911569ff2bceb49b4f020978d0d2e1)
2024-03-03 22:01:15 -05:00
AntsyLich 237d8d6b33 Small cleanup
(cherry picked from commit b7e091d5d039e00cababc7daf555280df6cf9c03)
2024-03-03 22:01:05 -05:00
renovate[bot] 117e0d5792 Update dependency com.android.tools.build:gradle to v8.3.0 (#471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 31e052ac15679496f9f2c3882e53096119e0e6cf)
2024-03-03 22:00:56 -05:00
renovate[bot] 64bbe941a4 Update dependency io.mockk:mockk to v1.13.10 (#470)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 60480686daa9456c78d7cb45c5ad2e23644d1bd2)
2024-03-03 22:00:49 -05:00
Jobobby04 dcd44c42ed Merge branch 'release' 2024-03-02 15:39:33 -05:00
Jobobby04 6c563d7619 Fix for duplicate read 2024-03-02 15:38:32 -05:00
Jobobby04 97f22c500b 1.10.5 2024-03-02 15:38:05 -05:00
Jobobby04 9cbeccfa15 Fix for duplicate read 2024-03-02 15:34:28 -05:00
MajorTanya 86722a31d0 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.

(cherry picked from commit 617bf491eee1d1010dc23c3f6df5d148700feb44)
2024-03-02 15:32:56 -05:00
AntsyLich 589b33a673 Fix detekt issue
(cherry picked from commit 9254079957e383e4aa5c914ccd9705612e0892d0)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt
2024-03-02 15:32:31 -05:00
AntsyLich dae0348710 Don't add custom User Agent for MAL
Closes #298

(cherry picked from commit 7974a1fc0c2b0e237d5704a033a60ec0fd60cdbc)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt
2024-03-02 15:32:29 -05:00
Jobobby04 a7f6155627 Ignore chapters with 0 or under chapter numbers
(cherry picked from commit d8082de1db)
2024-03-02 15:31:38 -05:00
Jobobby04 7f5bc4a3e5 Use new gradle workflow 2024-03-02 15:28:40 -05:00
Jobobby04 ec32278f1a Throw IOException 2024-03-02 14:25:31 -05:00
AntsyLich c02c5aa915 Revert changes to gradle.properties
(cherry picked from commit d6ba3c824972c8a2196516edd42e9e8be6385f36)
2024-03-02 14:24:34 -05:00
AntsyLich f267f2ad5b detekt my beloved
(cherry picked from commit c56f4665ef0276c54f5abebd9ab93e2e283739a6)
2024-03-02 14:24:25 -05:00
renovate[bot] 03bc09c1aa Update dependency me.saket.swipe:swipe to v1.3.0 (#343)
* Update dependency me.saket.swipe:swipe to v1.3.0

* Update MangaChapterListItem.kt

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit b51a0a38bd9849b573bc2de0d936d6ab2becb83c)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/manga/components/MangaChapterListItem.kt
2024-03-02 14:24:16 -05:00
AntsyLich c4df418081 Switch to Coil3
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit f72b6e4d7c1f2f93d705402e4d80c94160bef54d)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/App.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt
2024-03-02 14:22:54 -05:00
AntsyLich a9c79d5fb3 Remove custom Pager
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit 84984ef7e1d7242924120cd2f171cb9dd75bc916)
2024-03-02 14:02:34 -05:00
AntsyLich 529100a947 Enable experimental Compose compiler optimization
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit 9f48def1e2718abd5b4aad3cb6ee8af6b39e76cc)
2024-03-02 14:02:12 -05:00
AntsyLich 062f6d5aa0 ChapterDownloadIndicator: Remove composed modifier usage
Co-authored-by: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com>
(cherry picked from commit e83bfb0d3511f3c049d1dfe6ca13e74467655e08)
2024-03-02 14:01:43 -05:00
AntsyLich deb0a95985 Upgrade Compose
(cherry picked from commit 0301362430af6f74678dcae801b70d6aeb371a56)
2024-03-02 14:01:34 -05:00
Shamicen ca70f80900 Made some changes to ComicInfo metadata (#459)
* Made some changes to ComicInfo metadata

The web field now contains a " " separated list of source and tracker urls.
The translator field will now use the source name if the scanlator field is empty.

* lint

* use already existing source instance

* made translator not nullable

* implemented requested changes

created new Mihon exclusive ComicInfo source field  and populated it with SourceName

reverted previous changes to translator field

* Update core-metadata/src/main/java/tachiyomi/core/metadata/comicinfo/ComicInfo.kt

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

* Update app/src/main/java/eu/kanade/domain/manga/model/Manga.kt

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

* Update app/src/main/java/eu/kanade/domain/manga/model/Manga.kt

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

* Update app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt

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

* Update app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 4bfc5e7b51452a1a9cac3a3644e6343d1c47aa95)

# Conflicts:
#	app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt
#	core-metadata/src/main/java/tachiyomi/core/metadata/comicinfo/ComicInfo.kt
2024-03-02 14:01:12 -05:00
renovate[bot] 23e3ec20b6 Update Kotlin (#422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 802a2c5c1ea73c79967fb5b535b6249506df1870)
2024-03-02 13:59:43 -05:00
renovate[bot] 32d97ed194 Update dependency io.coil-kt:coil-bom to v2.6.0 (#447)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit c1c174698525e982107cc955d8dff711c4498989)
2024-03-02 13:59:34 -05:00
renovate[bot] 167a4e9820 Update dependency org.junit.jupiter:junit-jupiter to v5.10.2 (#419)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 4fcbd80a8ec72f4113d0ee9d457c000dcd8e7440)
2024-03-02 13:59:25 -05:00
renovate[bot] aef0b50663 Update dependency com.google.firebase:firebase-analytics-ktx to v21.5.1 (#417)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 16969193c718cc8e6cabb473ecb1d0d7bc02f33e)

# Conflicts:
#	gradle/libs.versions.toml
2024-03-02 13:59:16 -05:00
renovate[bot] 5b5e6c8f44 Update dependency androidx.test.uiautomator:uiautomator to v2.3.0 (#416)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 55637ddfe154c2ed60efb5d9d1466d2106c97f9f)
2024-03-02 13:58:48 -05:00
renovate[bot] 5dc96384bd Update detekt to v1.23.5 (#267)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit e50358dc4be7cbd866a79d052edc62689f0e4ca5)
2024-03-02 13:58:39 -05:00
AntsyLich affdea3ec2 Fix detekt issue
(cherry picked from commit 9254079957e383e4aa5c914ccd9705612e0892d0)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt
2024-03-02 13:57:49 -05:00
AntsyLich 1436d86c7e Don't add custom User Agent for MAL
Closes #298

(cherry picked from commit 7974a1fc0c2b0e237d5704a033a60ec0fd60cdbc)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt
2024-03-02 13:56:42 -05:00
renovate[bot] b7c9eaa981 Update dependency com.squareup.okio:okio to v3.8.0 (#423)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 1521c359412518731ef7338255cdd280321faa70)
2024-03-02 13:56:12 -05:00
Splintor db99ab526a Allow disabling reader's zoom out (#302)
* Allow disabling reader's zoom out (#62)

* Renamed disable zoom out pref and string

* Zoom to default rate if the scale is inferior

* Fixed null value check and formatting

* Fixed detekt

(cherry picked from commit c15f3f2fd5b11cc9c2088ae2fa444f4fe35ea740)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonFrame.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonRecyclerView.kt
2024-03-02 13:55:43 -05:00
renovate[bot] 133c34dee2 Update dependency com.google.gms:google-services to v4.4.1 (#418)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 21020e1797ae9c0373e5132e1dbcd9a64455c17f)
2024-03-02 13:48:11 -05:00
Weblate (bot) 775cf258ba Translations update from Hosted Weblate (#301)
* 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 (Indonesian)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chuvash)

Currently translated at 75.7% (601 of 793 strings)

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

* 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 (Chuvash)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Esperanto)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Japanese)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Polish)

Currently translated at 100.0% (793 of 793 strings)

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

* 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 (Hungarian)

Currently translated at 97.3% (772 of 793 strings)

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

* Translated using Weblate (Hungarian)

Currently translated at 94.1% (16 of 17 strings)

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

* 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 (Romanian)

Currently translated at 99.3% (788 of 793 strings)

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

* Translated using Weblate (Romanian)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (17 of 17 strings)

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

* 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 (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 (Nepali)

Currently translated at 100.0% (793 of 793 strings)

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

* 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 (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 (French)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Esperanto)

Currently translated at 62.0% (492 of 793 strings)

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

* Translated using Weblate (Esperanto)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Esperanto)

Currently translated at 63.6% (505 of 793 strings)

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

---------

Co-authored-by: bapeey <90949336+bapeey@users.noreply.github.com>
Co-authored-by: Eji-san <ejierubani@gmail.com>
Co-authored-by: C201 <derasetad@gmail.com>
Co-authored-by: Swyter <swyterzone@gmail.com>
Co-authored-by: Radoŝ Porka <animatorzPolski@gmail.com>
Co-authored-by: Deniz <denizgezgin365@gmail.com>
Co-authored-by: Uzuki Shimamura <hzy980512@126.com>
Co-authored-by: sebastians17 <sebastians117.ss@gmail.com>
Co-authored-by: ɴᴇᴋᴏ <s99095lkjjim@gmail.com>
Co-authored-by: B4LiN7 <B4LiN7@users.noreply.hosted.weblate.org>
Co-authored-by: Saft Octavian <saftoctavian@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: FateXBlood <zecrofelix@gmail.com>
Co-authored-by: Naga <yz2000.pro@gmail.com>
(cherry picked from commit 7edecae57f77ece7a5a3b457620c61e225fdc906)
2024-03-02 13:48:00 -05:00
Maddie Witman ed34807a58 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

(cherry picked from commit 07f963d5ae16c3c8d7be025a7e9439ad2110ac71)
2024-03-02 13:47:43 -05:00
beerpsi 31acbbdcdc [ExtensionLoader] Prioritize extension classpath over app classpath (#433)
(cherry picked from commit ab02568ac6e9dabc7a41036bb3d8c77138125544)
2024-03-02 13:47:21 -05:00
MajorTanya ef7708e324 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.

(cherry picked from commit 617bf491eee1d1010dc23c3f6df5d148700feb44)
2024-03-02 13:47:09 -05:00
MajorTanya de353c3334 Address overridePendingTransition deprecation (#410)
This function is deprecated starting with API 34 "UpsideDownCake" and
should be replaced with `overrideActivityTransition`.

(cherry picked from commit 840b647b4b4e738fac546b7437dd5449679232a1)
2024-03-02 13:46:42 -05:00
AntsyLich b47a317c48 Tweak detekt config
(cherry picked from commit 1b0bbb84401005801e61107a0c36443af691b8e6)
2024-03-02 13:44:22 -05:00
AntsyLich 2b163c91a9 Cleanup [BaseColorScheme.getColorScheme]
(cherry picked from commit 95d4df9ca80a88e87e633fc24c7fec677bc9d9b6)
2024-03-02 13:44:13 -05:00
AntsyLich d380a078a2 Update gradle.properties
(cherry picked from commit fb86c470f6cfcb0b6c1bb7b2790366e0d0c0662e)
2024-03-02 13:43:09 -05:00
AntsyLich 556afacd13 Small cleanup in WorkerInfoScreen
(cherry picked from commit 5aec8f8018236a38106483da08f9cbc28261ac9b)
2024-03-02 13:42:56 -05:00
AntsyLich 598d622d0b Revert a mishap in 7ff95e21babda98dd1b479912278d6029cd15f0d
(cherry picked from commit e183cbb231c6d48a17c573dbd3f2c8ce04ff7031)
2024-03-02 13:42:37 -05:00
AntsyLich 3a1d0d65bf Ignore detekt [LongParameterList] for composables
(cherry picked from commit 6bdb37be65757ca903c5c2a249ca03331b04d673)
2024-03-02 13:41:52 -05:00
Jobobby04 cc7b8a9b69 Improve duplicate chapter set as read 2024-03-02 13:41:35 -05:00
Maddie Witman 6c6f09ac5a 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

(cherry picked from commit 7ff95e21babda98dd1b479912278d6029cd15f0d)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt
2024-03-02 13:41:18 -05:00
MajorTanya 1fe309f363 Minor refactor of theming when expressions (#396)
* Minor refactor of theming when expressions

Avoids triggering detekt's CyclomaticComplexMethod warning because of
too many when branches, which would happen with one more theme being
added in these two locations.

In TachiyomiTheme, the Monet theme is separated because it requires
the current Compose context to function. The other themes do not and
are delegated to a Map.

* Implement requested changes

- moved themeResources out of the ThemingDelegate interface
- replaced single condition when with if expression

(cherry picked from commit 96c236e5c38248c875f2ac7596cd51845aa651ea)
2024-03-02 12:10:21 -05:00
renovate[bot] 3417fdb1a4 Update dependency androidx.test.ext:junit-ktx to v1.2.0-alpha03 (#340)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 72f3756a3b89de292d75d41fe6b5a59172039c45)
2024-03-02 12:10:13 -05:00
renovate[bot] a6394672e7 Update dependency androidx.test.espresso:espresso-core to v3.6.0-alpha03 (#339)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 0780385d2ebc9caca0bda0151d828ea6e036c768)
2024-03-02 12:10:07 -05:00
renovate[bot] 1fc97e4b7a Update lifecycle.version to v2.7.0 (#268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 31e9273b1ff4ecfd1992beaa8ad10fa27f726cc2)
2024-03-02 12:09:58 -05:00
renovate[bot] fe853aa1c5 Update dependency com.github.requery:sqlite-android to v3.45.0 (#260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 088e37b2d8d4d790e926eda34119377c2f94ccf6)

# Conflicts:
#	gradle/libs.versions.toml
2024-03-02 12:09:47 -05:00
renovate[bot] 9c3f805eab Update dependency io.github.fornewid:material-motion-compose-core to v1.2.0 (#257)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 5b88f1bd94ae3c696681fe34a22453575e747ff6)
2024-03-02 12:08:30 -05:00
renovate[bot] 410eda6d6c Update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.3 (#255)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 18beb20aac774a83d6cb13f6dc276c3683aaf9a2)
2024-03-02 12:08:21 -05:00
renovate[bot] 719c24fb38 Update dependency gradle to v8.6 (#341)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 9bff20cb1a0918d7789b281952624fed890fbab7)
2024-03-02 12:08:04 -05:00
Jobobby04 a7cb182bbe Cleanup 2024-03-02 12:01:49 -05:00
Fermín Cirella dbb970d7b5 Make manga page preview row count configurable (#1087)
* Make manga page preview row count configurable

* Replace string with plural
2024-03-02 11:58:16 -05:00
Dexroneum 887a27cf3e [RU] Translations (#1085) 2024-03-02 11:57:24 -05:00
Shamicen eed8ffb9d4 fix password protect downloads and copying ComicInfo files in LocalSource (#1084)
* fix password protect downloads

* fixed copying of ComicInfo file in LocalSource.kt

* Return correct archive file

* Applied upstream fix

* Use tempFileManager instead of file path

* Use streams instead of files
2024-03-02 11:56:57 -05:00
Cuong M. Tran dd412e33ad Rename MangaDex's FollowStatus's property to better reflect its type (#1082) 2024-03-02 11:56:11 -05:00
ɴᴇᴋᴏ 94e5c33785 Update zh-rTW strings.xml (#1080)
* Update strings.xml

* Update new zh-rTW strings.xml

* Update strings.xml

https://github.com/jobobby04/TachiyomiSY/pull/1079#issue-2140674661
2024-03-02 11:55:47 -05:00
Luqman 6f3f109723 add mark read dupes on reading (#1079)
* Feature: mark read dupes

* dupe chapter reading add summary

* Update ReaderViewModel.kt

* Update i18n/src/commonMain/resources/MR/base/strings.xml

* Update app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt

---------

Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com>
2024-03-02 11:55:09 -05:00
Jobobby04 d8082de1db Ignore chapters with 0 or under chapter numbers 2024-02-18 11:47:19 -05:00
Jobobby04 2daccb57b5 1.10.4 2024-02-17 18:58:06 -05:00
Jobobby04 e64bddf9d5 Fix crashes related to MangaCover 2024-02-17 18:55:03 -05:00
pabalaba 9f6f15f64d Update workflow dependencies (#310)
* feat: updated build_pull_request actions version

* feat: updated build_push actions version

* feat: updated issue_moderator action version

* feat: updated deprecated arguments in build_pull_request

* feat: updated deprecated arguments in build_push

* feat: removed explicit declaration of gradle version

(cherry picked from commit 170daf9fb2e566fea598eb5dc0cd710f979c7b7a)

# Conflicts:
#	.github/workflows/build_pull_request.yml
#	.github/workflows/build_push.yml
2024-02-17 18:50:58 -05:00
Jobobby04 ad28c9a482 1.10.3 2024-02-17 16:34:00 -05:00
Jobobby04 8404fb5738 Should fix password protect downloads 2024-02-17 16:14:10 -05:00
Jobobby04 75c057e83e Fix compile 2024-02-17 15:57:20 -05:00
ouovouo d44e2df55e update zh-rTW strings.xml (#1038) 2024-02-17 15:54:39 -05:00
Luqman aebc15d4e4 Add Hide Feed tab toggle (#1058) 2024-02-17 15:50:38 -05:00
Luqman c835140fe8 Add custom Thumbnail Url. Support backup & restore (#1059)
* Add custom thumbnail url. Support backup & restore

- add custom thumbnail url in edit info/custom
- include it in backup n restore

* increase chop char

* edit chop char again to match screenshoot

* tweak truncating middle part

* apply edited cover to history, updates , others

* simplify placeholder logic

---------

Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com>
2024-02-17 15:50:00 -05:00
Luqman f35031db7e Fix blank box if empty (#1069) 2024-02-17 15:46:48 -05:00
Luqman ca81f48c1c add toggle to auto mark read dupe chapter (#1078)
* add toggle to auto mark read dupe chapter

https: //github.com/tachiyomiorg/tachiyomi/pull/9662
Co-Authored-By: Trace <49712094+traceltrc@users.noreply.github.com>

* Update LibraryUpdateJob.kt

---------

Co-authored-by: Trace <49712094+traceltrc@users.noreply.github.com>
2024-02-17 15:46:23 -05:00
AntsyLich 30dcc6801a Remove old ISSUE_TEMPLATE.md
(cherry picked from commit 1581b876cfc9d98620e164a48084be88c348457e)

# Conflicts:
#	.github/ISSUE_TEMPLATE.md
2024-02-17 15:23:44 -05:00
AntsyLich 46ba4ac182 Don't throw MALTokenExpired whenever we fail to refresh MAL token
Also cleanup

(cherry picked from commit 0f4de03d7a77b52490dc9a95e96a308b93b26e4f)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListInterceptor.kt
2024-02-17 15:23:20 -05:00
AntsyLich 2c6a57ab39 [skip ci] Increase size of the message indicating which apk to download
(cherry picked from commit ddbe8efbc5cb0665be0775b128e70ace8cee2b12)

# Conflicts:
#	.github/workflows/build_push.yml
2024-02-17 15:17:45 -05:00
Weblate (bot) 79a3aedf5c Translations update from Hosted Weblate (#269)
* Translated using Weblate (Persian)

Currently translated at 84.8% (673 of 793 strings)

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

* Translated using Weblate (Finnish)

Currently translated at 85.3% (677 of 793 strings)

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

* Translated using Weblate (Chuvash)

Currently translated at 88.2% (15 of 17 strings)

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

---------

Co-authored-by: Arash <ara.khoram95@gmail.com>
Co-authored-by: A <ogloppi@mailbox.org>
Co-authored-by: C201 <derasetad@gmail.com>
(cherry picked from commit 63146e717ba2cf178b79ae3de4b9b15b0ecc788f)

# Conflicts:
#	i18n/src/commonMain/resources/MR/fi/strings.xml
2024-02-17 15:16:40 -05:00
AntsyLich 38fc1fe805 Lint
(cherry picked from commit b2d22f86c647e24eed6d9b19f36ac2c444525c87)

# Conflicts:
#	app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
2024-02-17 15:15:12 -05:00
AwkwardPeak7 5daf5e82f4 Fix new extension install not registering in app. (#275)
* Fix extension install not registering

* fix duplicate key compose error on extension update

* fix doubling of extension after update

* not needed

(cherry picked from commit 79f46b25f663c7f49fbd4e292f0f5f210e266dc9)
2024-02-17 15:14:33 -05:00
AntsyLich dacfb8a740 Move :core to :core:common
(cherry picked from commit aa498360db90350f2642e6320dc55e7d474df1fd)

# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/eu/kanade/domain/base/BasePreferences.kt
#	app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt
#	app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/App.kt
#	app/src/main/java/eu/kanade/tachiyomi/Migrations.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt
#	app/src/main/java/eu/kanade/tachiyomi/util/CrashLogUtil.kt
#	core/common/src/main/kotlin/eu/kanade/tachiyomi/util/storage/CbzCrypto.kt
#	data/src/main/java/tachiyomi/data/manga/MangaRepositoryImpl.kt
#	data/src/main/java/tachiyomi/data/source/SourcePagingSource.kt
#	domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt
#	domain/src/main/java/tachiyomi/domain/manga/model/Manga.kt
#	settings.gradle.kts
#	source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt
#	source-local/src/androidMain/kotlin/tachiyomi/source/local/image/LocalCoverManager.kt
2024-02-17 15:14:24 -05:00
AntsyLich fec9f1f10c Address build warning in :i18n
And small cleanup

(cherry picked from commit 4811cf07cdbf052dc3ddd2916e56ed81b6dc652a)
2024-02-17 14:49:08 -05:00
MajorTanya 293fb7597c Add click-to-copy extension debug info (#271)
* Add click-to-copy extension debug info

Adds some debug info about an extension to the user's clipboard when
tapping the logo/name/package name area at the top of the details
screen. Modeled after the debug info from the About screen.

Closes #168.

* Fix linting failure

* Slight cleanup

* Address detekt

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit b71c793fad46b91309da5d505ff49f99847b4f68)
2024-02-17 14:48:17 -05:00
AntsyLich 0cf6a6ef2d Upgrade combose-bom to latest
(cherry picked from commit 47e542152788e587f5f77dea4b2676683f2fba47)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt
2024-02-17 14:48:08 -05:00
Theodoro Loureiro mota 4d44e093d5 Fix #197 - Scroll crashing (#272)
Updating compose bom.

(cherry picked from commit 5dc6501688d541da990eaa1f687d93dc9e18e20e)
2024-02-17 14:47:29 -05:00
Theodoro Loureiro mota 2c75649a3c Adding Detekt in the project (#216)
* Removing ktlint

* Removing compose lint

* Adding initial Detekt config

* Setting up detekt config

* Adding detekt baseline

* Fixing workflows

* Moving to a module based solution

* Adding new line

* Adding new line

* Updating baseline

* Addressing PR suggestions

* Regenerating baseline.xml

* Cleanup

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit cc09230e266c3cd7ed748affe92922d775523695)

# Conflicts:
#	.github/workflows/build_pull_request.yml
#	.github/workflows/build_push.yml
2024-02-17 14:47:23 -05:00
renovate[bot] 1ca599a550 Update dependency com.android.tools.build:gradle to v8.2.2 (#256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
(cherry picked from commit 4bcba0503ae36aa42384335333b814163c0ed0c8)
2024-02-17 14:45:24 -05:00
Jishnu M dc7cd5b3c8 Change extension update error file name (#253)
(cherry picked from commit cf33f250ccfe4e1dde92b8942a5f282827d50fb7)
2024-02-17 14:45:14 -05:00
Theodoro Loureiro mota 67196fb7b6 Fixing bottom sheet UI bug in non-tablet devices (#182)
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Setting decorFitsSystemWindows = true to fix ui bug on Android 11

(cherry picked from commit 915a9671514b25fdd62912a5154aca221470c8a7)
2024-02-17 14:44:57 -05:00
Soitora 9b8e81a063 Hide display cutout setting if fullscreen is off (#241)
- make it behave like the one on more -> setting -> reader

Co-authored-by: Riztard <16263232+Riztard@users.noreply.github.com>
(cherry picked from commit 9cc0c4e0359cf06ef6257fc289f05a6f4fb9cf6e)
2024-02-17 14:44:32 -05:00
AntsyLich 91b7f0c1d0 Make tracker use Mihon's client
(cherry picked from commit 8c910f2a2c27dc339a4b05f03be3386a3afa2194)
2024-01-28 17:33:46 -05:00
Weblate (bot) 32bcf49b97 [skip ci] Translations update from Hosted Weblate (#190)
* Translated using Weblate (Nepali)

Currently translated at 94.1% (747 of 793 strings)

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

* Translated using Weblate (Italian)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Japanese)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 98.3% (780 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 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% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Polish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Swedish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (German)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Swedish)

Currently translated at 100.0% (793 of 793 strings)

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

* 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 (Finnish)

Currently translated at 80.9% (642 of 793 strings)

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

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Arabic)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Persian)

Currently translated at 82.7% (656 of 793 strings)

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

* Translated using Weblate (Finnish)

Currently translated at 80.9% (642 of 793 strings)

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

* Translated using Weblate (Arabic)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Chuvash)

Currently translated at 88.2% (15 of 17 strings)

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

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (17 of 17 strings)

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

---------

Co-authored-by: FateXBlood <zecrofelix@gmail.com>
Co-authored-by: Federico Pierantoni <federico.pieranton@gmail.com>
Co-authored-by: Zero O <godarms2010@live.com>
Co-authored-by: stevenlele <stevenlele@outlook.com>
Co-authored-by: Paweł Waresiak <pwaresia@redhat.com>
Co-authored-by: kret <cihanbeykoroglu@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Lyfja <45209212+lyfja@users.noreply.github.com>
Co-authored-by: dan-malprod <diabolic0240@proton.me>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
Co-authored-by: A <ogloppi@mailbox.org>
Co-authored-by: Christian Elbrianno <crse@protonmail.ch>
Co-authored-by: abdelbasset jabrane <ribago9317@cubene.com>
Co-authored-by: Arash <ara.khoram95@gmail.com>
Co-authored-by: C201 <derasetad@gmail.com>
Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
(cherry picked from commit 8489b0dd8be7371b53367755a2785de2a881107d)
2024-01-28 17:29:09 -05:00
AntsyLich 6a9efe3a41 Lint
(cherry picked from commit 88ed634978948a48bc9b6eab9eaf0d41d45db62a)
2024-01-28 17:28:31 -05:00
AntsyLich 945d5ebf75 Refactor MAL code to not spam refresh token when it fails
(cherry picked from commit 32188f9f65009a18250674ef1bd6e57d351c1fba)
2024-01-28 17:28:17 -05:00
AntsyLich d38b1d27d0 Update types of legacy tracker model to match to domain one (#245)
* `score` to Double

* `tracker_id` to Long

* `last_chapter_read` to Double

* `total_chapters` to Long

* `status` to Long

(cherry picked from commit 05efc4ebeb197cabd2bc494d36fbb27fea923292)
2024-01-28 17:27:08 -05:00
CodeSpoof 6ad618b494 [skip ci] Remove official extensions check from issue templates (#233)
* Update report_issue.yml

There are no official extensions anymore and the URL was for the tachiyomi repo anyway

* Update request_feature.yml

No more official extensions

(cherry picked from commit b8a9998bbd2b4f937095728c19e834122e580230)
2024-01-28 17:13:35 -05:00
Weblate (bot) a63f7b4e62 Translations update from Hosted Weblate (#225)
* Translated using Weblate (Swedish)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (17 of 17 strings)

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

---------

Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
(cherry picked from commit d736bec00361c4192bddb8ec27908a5a833a00bf)
2024-01-28 17:12:25 -05:00
Secozzi 6e57a62e2a Fix refreshing from enhanced tracker (#219)
fix refreshing from enhanced tracker

(cherry picked from commit 348b23a9fd833d9040cfbdd60b11f9d5ce6e5fb7)
2024-01-28 17:12:06 -05:00
Theodoro Loureiro mota 100f16000e Fix #126: Inconsistent button height with some languages in "Data and storage" (#202)
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Fixing bug in the MultiChoiceSegmentedButtonRow

* Rollback file

(cherry picked from commit 1dd130df9ee389fbacb200ee7a13b6d625b372fc)
2024-01-28 17:11:40 -05:00
Theodoro Loureiro mota 78c7facf6c Adding Type-safe project accessors (#194)
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Enabling TYPESAFE_PROJECT_ACCESSORS

* Adding typesafe project accessors in the app module

* Adding typesafe project accessors in the core module

* Adding typesafe project accessors in the core-metadata module

* Adding typesafe project accessors in the data module

* Adding typesafe project accessors in the domain module

* Adding typesafe project accessors in the presentation-core module

* Adding typesafe project accessors in the presentation-widget module

* Adding typesafe project accessors in the source-local module

* Adding typesafe project accessors in the source-api module

* Rolling back

* Changing TYPESAFE_PROJECT_ACCESSORS line

* Removing extra spaces

(cherry picked from commit e17d87f35749715946a96dc0e654792227c6722d)
2024-01-28 17:11:26 -05:00
AntsyLich b210491db5 Lint
(cherry picked from commit 58085336a5399a066b04baf679445bb0e047cc5d)
2024-01-28 14:16:17 -05:00
Jobobby04 ca944f3f38 Swap over to Mihon.app 2024-01-28 14:14:51 -05:00
AntsyLich 2eca6dc707 Use own client for trackers + custom user agents
Closes #114
Closes #143

Co-authored-by: Med <45147847+kitsumed@users.noreply.github.com>
(cherry picked from commit e3f33e24f5e928ac8a85d1f500fd42d4715fc6b5)
2024-01-28 14:14:24 -05:00
AntsyLich 90835256ff Translations (#189)
* Small fix on french translation. (#104)

Update fr/strings.xml

Remove mentions of "official" extensions repos. (On 18+ extensions warning)

Fixed a setting label who had the first letter in lowercase.

* Updated Turkish suffixes (#125)

Update strings.xml

* Fix zh-rTW Translation (#118)

fix zh-tw translate

* Update Filipino Plurals (#112)

Updated some Filipino Plurals to make sense grammatically

* Update Filipino Strings (#111)

Changed/updated a few grammatical strings for the Filipino Translation

---------

Co-authored-by: Med <45147847+kitsumed@users.noreply.github.com>
Co-authored-by: NukeSource <123626751+NukeSource@users.noreply.github.com>
Co-authored-by: ɴᴇᴋᴏ <111511925+NeKoOuO@users.noreply.github.com>
Co-authored-by: InfinityDouki56 <31158494+infyProductions@users.noreply.github.com>
(cherry picked from commit 9fd1419142647455e86851413353c97bb9491990)
2024-01-28 14:07:35 -05:00
AntsyLich 80351cd594 Fix issues when updating extensions
(cherry picked from commit cb068984303f811692531bf6f14902ae118d8ac7)
2024-01-28 14:06:22 -05:00
AntsyLich 7cdfa68d77 Remove usage of .not() where possible
(cherry picked from commit 39407407f282dbb7fa972b12053c26b3e3bd66d8)
2024-01-28 14:06:13 -05:00
AntsyLich 3f74a6d33f Fix faulty MangaUpdates score in db
Closes #117

(cherry picked from commit a024218410953a389b8af4880fa7ae6cc30124a2)
2024-01-28 14:04:54 -05:00
jobobby04 27d8896937 Backup and Restore Excluded scanlators (#166)
* Backup and Restore Excluded scanlators

* Improve performance

* This looks better

(cherry picked from commit e0deeb800890c5e3be67c4ebe32ebe34d97e0e25)
2024-01-28 14:01:41 -05:00
AntsyLich 7b92d06eee Fix "Flash on page change" gives black screen on page change
Fixes #108

(cherry picked from commit 38d6ab80ce868707829dbc81de4170afe3c2f2a5)
2024-01-28 13:59:56 -05:00
KaiserBh cbfb433e55 refactor: db changes for syncing. (#113)
fix: sync marking chapter unread when we do library update before syncing.

So this should have been 0 on insert instead of the current time on insert. Essentially this issue arises: https://discord.com/channels/1099009852791083058/1099009853864812708/1190022356060614756

Signed-off-by: KaiserBh <kaiserbh@proton.me>
(cherry picked from commit e4a65656e7fd5807475323373b8337b1f53ff1f9)
2024-01-28 13:59:38 -05:00
Jobobby04 c3503dbd3c Remove funding 2024-01-17 23:37:25 -05:00
NeKo 7e151ddb83 Update strings.xml (#1021) 2024-01-17 23:29:49 -05:00
Howard Wu 2204435d29 zh-rCN translation updates (#1013)
Translation mistakes correction and missing translation additions
2024-01-17 23:29:30 -05:00
Jobobby04 c85d6ec1d0 v1.10.2 2024-01-17 23:28:39 -05:00
Jobobby04 9b9655df90 Update AboutScreen with new links 2024-01-17 23:28:24 -05:00
AntsyLich 7cc6b7147f Fix score issue with MangaUpdates
Also add custom user agent

Potentially fix #17

(cherry picked from commit 99fd2731f5d9d374700e89fa67d4d5bf611bbafa)
2024-01-17 23:19:44 -05:00
DavidK004 84e4a66b08 Fixed Serbian translation (#75)
(cherry picked from commit e34043f1feb03dab31f18bd8cd12bf37bcb7f56c)
2024-01-17 23:18:44 -05:00
Chris ea9427026d Fix Indonesian translation (#68)
Fix minor Indonesian translation

(cherry picked from commit 0a2df21c5b5a16a63cd80ff3cd256eb0521450fb)
2024-01-17 23:18:17 -05:00
Dexroneum c1af389eea [RU] Translations (#998) 2024-01-13 21:14:07 -05:00
NeKo 0ee0df3471 Update zh-tw strings.xml (#999)
* Update strings.xml

Word precise

* Update strings.xml

Localization Some Terminology
Improvement Some Terminology
2024-01-13 21:14:00 -05:00
Jobobby04 0af70d23dd Release 1.10.1 2024-01-13 21:12:22 -05:00
Jobobby04 d741685836 Update Readme Screens 2024-01-13 20:58:22 -05:00
Jobobby04 f59b6e393e Put merge in overflow for now 2024-01-13 18:23:46 -05:00
Jobobby04 6632589027 Remove some links in About 2024-01-13 16:40:24 -05:00
Jobobby04 a009d5d080 Change support server 2024-01-13 16:39:52 -05:00
arkon 29bbf77e7c Install build-tools 29.0.3
(cherry picked from commit a9c7cbf2c43959ae7ad9df3baa2306a254dd57e3)
2024-01-13 14:18:06 -05:00
Weblate (bot) 5a4bb2c5d3 Translations update from Hosted Weblate (#10393)
Weblate translations

Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/bg/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ca/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/de/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/fil/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/hr/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/id/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/it/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ru/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/uk/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/bg/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/de/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/eo/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/fil/
Translation: Tachiyomi/Tachiyomi plurals.xml
Translation: Tachiyomi/Tachiyomi strings.xml

Co-authored-by: Boyan Alexiev <nneauu@gmail.com>
Co-authored-by: Denis \"Samilton <d.bogdan99@gmail.com>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: Eduard Ereza Martínez <eduard@ereza.cat>
Co-authored-by: Giorgio Sanna <sannagiorgio1997@gmail.com>
Co-authored-by: Lyfja <yassinelaoud@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Radoŝ Porka <animatorzPolski@gmail.com>
Co-authored-by: Shiratori <kuromaruhatake@gmail.com>
Co-authored-by: TheKingTermux <achmadmaulana0233@gmail.com>
(cherry picked from commit 899bd269567e5b2aa0c9e7ccded3cb49f151cc11)
2024-01-13 14:16:52 -05:00
arkon e28878c5ee Better message for empty extensions list
(cherry picked from commit a37f3eb70922557cd0e4ed0c05d3563850b49757)
2024-01-13 00:18:51 -05:00
arkon a80a765ee5 Update Compose compiler and Kotlin
(cherry picked from commit 9ae71dfe93291e6d170f5e6af994f2c52c4158a1)
2024-01-13 00:18:45 -05:00
arkon a96079c14c Fixed tap controls not working when zoomed in (#10378)
Co-authored-by: Paloys <Paloys@users.noreply.github.com>
(cherry picked from commit c65a9aecf5ed228550fd994e62a16fc2300c344d)
2024-01-13 00:18:36 -05:00
Jobobby04 d99b3b1203 Revert "Add extension repo mentions to more places"
This reverts commit 8625e75a2b.
2024-01-13 00:18:20 -05:00
Jobobby04 ba2b85c3ee Revert "Actual right arrow"
This reverts commit 7934d4ee01.
2024-01-13 00:18:19 -05:00
arkon 320eb3f16a Minor extension repo enhancements
- Shortcut to settings from extensions tab
- Don't show error toast anymore if nothing's loaded
- Ability to copy extension repo URL to clipboard

(cherry picked from commit 02e50411de8e233dfd0f2bd9671f39a4e71d297c)
2024-01-13 00:17:07 -05:00
Weblate (bot) 5dced2d173 Translations update from Hosted Weblate (#10386)
Weblate translations

Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/cs/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/de/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/el/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/eo/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/es/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/fil/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/hr/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/id/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ja/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ko/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ms/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ne/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/pt/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/ru/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/sv/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/te/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/th/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/tr/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/zh_Hans/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/strings/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/cs/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/de/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/el/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/hr/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/ja/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/ms/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/ne/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/pt/
Translate-URL: https://hosted.weblate.org/projects/tachiyomi/tachiyomi-plurals-xml/zh_Hans/
Translation: Tachiyomi/Tachiyomi plurals.xml
Translation: Tachiyomi/Tachiyomi strings.xml

Co-authored-by: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com>
Co-authored-by: Andreas E <andreas.everos@gmail.com>
Co-authored-by: CodeSpoof <nao.s_l_t_e_e_l@protonmail.com>
Co-authored-by: Crazyom <naxom@laposte.net>
Co-authored-by: Daedren <lord.raikon@gmail.com>
Co-authored-by: DarKCroX <DarKCroX@users.noreply.hosted.weblate.org>
Co-authored-by: Dexroneum <Rozhenkov69@gmail.com>
Co-authored-by: Gianluca Starke <gianlucastarke@gmail.com>
Co-authored-by: ID-86 <id86dev@gmail.com>
Co-authored-by: InfinityDouki56 <ced.paltep10@gmail.com>
Co-authored-by: Khori Hutama <khori.qq@gmail.com>
Co-authored-by: Kirito ._ <kiritokunn18@gmail.com>
Co-authored-by: Lyfja <yassinelaoud@gmail.com>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
Co-authored-by: Manjul Tamrakar <manjultamrakar4@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Paavalen Lingachetti <p.lingachetti@gmail.com>
Co-authored-by: Pitpe11 <giorgos2550@gmail.com>
Co-authored-by: Radoŝ Porka <animatorzPolski@gmail.com>
Co-authored-by: Sup Kelelawar <apkfile007@gmail.com>
Co-authored-by: Swyter <swyterzone@gmail.com>
Co-authored-by: Uzuki Shimamura <hzy980512@126.com>
Co-authored-by: Zero O <godarms2010@live.com>
Co-authored-by: altinat <altinat@duck.com>
Co-authored-by: dan-malprod <diabolic0240@proton.me>
Co-authored-by: jinu147 <nesqea20@gmail.com>
Co-authored-by: orkan gökçe alaz aşina <examplehuman@outlook.com>
Co-authored-by: stevenlele <stevenlele@outlook.com>
(cherry picked from commit 6e822dfd5b12a1560bb79723008ed3146ce0bcc0)
2024-01-13 00:16:59 -05:00
Caleb Morris 09a18be5b9 [download-cache] Fixed init logic to skip when cache file is missing (#10362)
There are several possible causes of the cache file to not exist, including user
 action. By skipping these couple steps during initialization when the file is
 missing, a renew action is allowed to start and the cache will rebuild and
 hopefully work as expected.

Simple fix for #10360

(cherry picked from commit 7292dadd5fbbf9b394f047f2207f4de13c8229d0)
2024-01-13 00:16:51 -05:00
KaiserBh f6407805d3 Use transaction on restore to go brr. (#10375)
refactor: use transaction to go brr.

This improve the restore speed on fresh db and non fresh db.

Signed-off-by: KaiserBh <kaiserbh@proton.me>
(cherry picked from commit b1067b942ef5c8d53e5ab838ef078789b9c0627a)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaRestorer.kt
2024-01-13 00:16:39 -05:00
stevenyomi f24d50af44 Fix extension interceptors receiving compressed responses (#10388)
(cherry picked from commit d6c4af89c4a2df213f06ed4c3d714a2608117afb)
2024-01-13 00:15:15 -05:00
Caleb Morris a13de19c81 Fixed dev UI preview (#10385)
The TachiyomiTheme introduced a dependency-injection construct that didn't
 exist at the time of rendering previews, so I've changed the preview function
 to use a preview version of the theme that uses declarative configuration
 over dependency injection

(cherry picked from commit cf6f7c521cde88f20c1eef3a6a63a2b73601523f)
2024-01-13 00:14:57 -05:00
Jobobby04 efb95864cd Fix Mangadex Auth not properly handling bad responses 2024-01-13 00:10:10 -05:00
Jobobby04 14da34de64 Remove ktlint check 2024-01-09 19:19:33 -05:00
624 changed files with 10648 additions and 3567 deletions
-1
View File
@@ -1 +0,0 @@
ko_fi: inorichi
-34
View File
@@ -1,34 +0,0 @@
**PLEASE READ THIS**
I acknowledge that:
- I have updated:
- To the latest version of the app (stable is v1.10.0)
- All extensions
- I have gone through the FAQ (https://tachiyomi.org/docs/faq/general) and troubleshooting guide (https://tachiyomi.org/docs/guides/troubleshooting/)
- If this is an issue with an official extension, that I should be opening an issue in https://github.com/tachiyomiorg/extensions
- I have searched the existing issues and this is new ticket **NOT** a duplicate or related to another open or closed issue
- I will fill out the title and the information in this template
Note that the issue will be automatically closed if you do not fill out the title or requested information.
**DELETE THIS SECTION IF YOU HAVE READ AND ACKNOWLEDGED IT**
---
## Device information
* Tachiyomi version: ?
* Android version: ?
* Device: ?
## Steps to reproduce
1. First step
2. Second step
## Issue/Request
?
## Other details
Additional details and attachments.
If you're experiencing crashes, share the crash logs from More → Settings → Advanced → Dump crash logs.
+2 -8
View File
@@ -1,11 +1,5 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Extension/source issue - name: 🖥 Mihon website
url: https://github.com/tachiyomiorg/extensions/issues/new/choose url: https://mihon.app/
about: Issues and requests for official extensions and sources should be opened in the extensions repository instead
- name: 📦 Tachiyomi extensions
url: https://tachiyomi.org/extensions/
about: List of all available extensions with download links
- name: 🖥️ Tachiyomi website
url: https://tachiyomi.org/
about: Guides, troubleshooting, and answers to common questions about: Guides, troubleshooting, and answers to common questions
+7 -11
View File
@@ -1,5 +1,5 @@
name: 🐞 Issue report name: 🐞 Issue report
description: Report an issue in Tachiyomi description: Report an issue in TachiyomiSY
labels: [Bug] labels: [Bug]
body: body:
@@ -48,12 +48,12 @@ body:
You can paste the crash logs in plain text or upload it as an attachment. You can paste the crash logs in plain text or upload it as an attachment.
- type: input - type: input
id: tachiyomi-version id: tachiyomisy-version
attributes: attributes:
label: Tachiyomi version label: TachiyomiSY version
description: You can find your Tachiyomi version in **More → About**. description: You can find your TachiyomiSY version in **More → About**.
placeholder: | placeholder: |
Example: "1.9.4" Example: "1.10.5"
validations: validations:
required: true required: true
@@ -90,17 +90,13 @@ body:
label: Acknowledgements label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this. description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options: options:
- label: This is a TachiyomiSY specific issue that does not happen in [Tachiyomi Preview](https://github.com/tachiyomiorg/tachiyomi/).
required: true
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue. - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
required: true 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: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose). - label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https:/mihon.app/docs/guides/troubleshooting/).
required: true required: true
- label: I have gone through the [FAQ](https://tachiyomi.org/docs/faq/general) and [troubleshooting guide](https://tachiyomi.org/docs/guides/troubleshooting/). - label: I have updated the app to version **[1.10.5](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
required: true
- label: I have updated the app to version **[1.10.0](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
required: true required: true
- label: I have updated all installed extensions. - label: I have updated all installed extensions.
required: true required: true
+3 -5
View File
@@ -1,5 +1,5 @@
name: ⭐ Feature request name: ⭐ Feature request
description: Suggest a feature to improve Tachiyomi description: Suggest a feature to improve TachiyomiSY
labels: [Feature request] labels: [Feature request]
body: body:
@@ -7,7 +7,7 @@ body:
id: feature-description id: feature-description
attributes: attributes:
label: Describe your suggested feature label: Describe your suggested feature
description: How can Tachiyomi be improved? description: How can TachiyomiSY be improved?
placeholder: | placeholder: |
Example: Example:
"It should work like this..." "It should work like this..."
@@ -31,9 +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: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose). - label: I have updated the app to version **[1.10.5](https://github.com/jobobby04/tachiyomisy/releases/latest)**.
required: true
- label: I have updated the app to version **[1.10.0](https://github.com/jobobby04/tachiyomisy/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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 KiB

After

Width:  |  Height:  |  Size: 713 KiB

+4 -3
View File
@@ -32,10 +32,11 @@ jobs:
java-version: 17 java-version: 17
distribution: adopt distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
- name: Build app - name: Build app
uses: gradle/gradle-command-action@v2 run: ./gradlew detekt assembleDevDebug
with:
arguments: assembleDevDebug
- name: Upload APK - name: Upload APK
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
+18 -4
View File
@@ -18,7 +18,11 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v2
- name: Setup Android SDK
run: |
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3"
- name: Set up JDK - name: Set up JDK
uses: actions/setup-java@v4 uses: actions/setup-java@v4
@@ -26,6 +30,9 @@ jobs:
java-version: 17 java-version: 17
distribution: adopt distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
# SY <-- # SY <--
- name: Write google-services.json - name: Write google-services.json
uses: DamianReeves/write-file-action@v1.2 uses: DamianReeves/write-file-action@v1.2
@@ -33,12 +40,17 @@ jobs:
path: app/google-services.json path: app/google-services.json
contents: ${{ secrets.GOOGLE_SERVICES_TEXT }} contents: ${{ secrets.GOOGLE_SERVICES_TEXT }}
write-mode: overwrite write-mode: overwrite
- name: Write client_secrets.json
uses: DamianReeves/write-file-action@v1.2
with:
path: app/src/main/assets/client_secrets.json
contents: ${{ secrets.CLIENT_SECRETS_TEXT }}
write-mode: overwrite
# SY --> # SY -->
- name: Build app and run unit tests - name: Build app and run unit tests
uses: gradle/gradle-command-action@v2 run: ./gradlew detekt assembleStandardRelease testStandardReleaseUnitTest --stacktrace
with:
arguments: ktlintCheck assembleStandardRelease testStandardReleaseUnitTest --stacktrace
- name: Sign APK - name: Sign APK
uses: r0adkll/sign-android-release@v1 uses: r0adkll/sign-android-release@v1
@@ -90,6 +102,8 @@ jobs:
| armeabi-v7a | ${{ env.APK_ARMEABI_V7A_SHA }} | | armeabi-v7a | ${{ env.APK_ARMEABI_V7A_SHA }} |
| x86 | ${{ env.APK_X86_SHA }} | | x86 | ${{ env.APK_X86_SHA }} |
| x86_64 | ${{ env.APK_X86_64_SHA }} | | x86_64 | ${{ env.APK_X86_64_SHA }} |
## If you are unsure which version to choose then go with TachiyomiSY.apk
files: | files: |
TachiyomiSY.apk TachiyomiSY.apk
TachiyomiSY-arm64-v8a.apk TachiyomiSY-arm64-v8a.apk
+4 -7
View File
@@ -18,13 +18,10 @@ jobs:
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v1
- name: TAG - Bump version and push tag - name: Create Tag
uses: anothrNick/github-tag-action@1.39.0 run: |
env: git tag "preview-${{ github.run_number }}"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} git push origin "preview-${{ github.run_number }}"
WITH_V: true
RELEASE_BRANCHES: master
DEFAULT_BUMP: patch
- name: PING - Dispatch initiating repository event - name: PING - Dispatch initiating repository event
run: | run: |
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Moderate issues - name: Moderate issues
uses: tachiyomiorg/issue-moderator-action@v2 uses: tachiyomiorg/issue-moderator-action@v2.6.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
duplicate-label: Duplicate duplicate-label: Duplicate
@@ -39,7 +39,7 @@ jobs:
"regex": ".*(?:fail(?:ed|ure|s)?|can\\s*(?:no|')?t|(?:not|un).*able|(?<!n[o']?t )blocked by|error) (?:to )?(?:get past|by ?pass|penetrate)?.*cloud ?fl?are.*", "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, "ignoreCase": true,
"labels": ["Cloudflare protected"], "labels": ["Cloudflare protected"],
"message": "Refer to the **Solving Cloudflare issues** section at https://tachiyomi.org/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection." "message": "Refer to the **Solving Cloudflare issues** section at https://mihon.app/docs/guides/troubleshooting/#cloudflare. If it doesn't work, migrate to other sources or wait until they lower their protection."
} }
] ]
auto-close-ignore-label: do-not-autoclose auto-close-ignore-label: do-not-autoclose
+1
View File
@@ -22,3 +22,4 @@ TODO.md
CHANGELOG.md CHANGELOG.md
/captures /captures
build.sh build.sh
/app/src/main/assets/client_secrets.json
+1 -1
View File
@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community moderators responsible for enforcement at reported to the community moderators responsible for enforcement at
the [Tachiyomi Discord server](https://discord.gg/tachiyomi). the [Mihon Discord server](https://discord.gg/mihon).
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community moderators are obligated to respect the privacy and security of the All community moderators are obligated to respect the privacy and security of the
+17
View File
@@ -52,3 +52,20 @@ When creating a fork, remember to:
- To avoid having your data polluting the main app's analytics and crash report services: - To avoid having your data polluting the main app's analytics and crash report services:
- If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/standard/google-services.json) with your own - If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/standard/google-services.json) with your own
- If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts) with your own - If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts) with your own
### Supporting Cloud Sync - Google Drive Implementation
1. Go to [Google Cloud Console](https://console.cloud.google.com)
2. Create a new project
3. Go to API & Services -> Library -> Google Drive API and click enable
4. Go to API & Services -> Oauth consent screen
5. Create it, fill in the app name, user support email, and developer contact information
6. In the next screen, click add or remove scopes, and add the `.../auth/drive.appdata` and `.../auth/drive.file` scopes
7. Don't add any test users and go back to the dashboard
8. Click publish
9. Go to API & Services -> Credentials
10. Click Create credentials -> Oauth client ID
11. Select Android, give it a name, and set `eu.kanade.google.oauth` as the package name
12. To get the SHA-1 key, run `keytool -printcert -jarfile app-standard-universal-release.apk` on your apk, and copy the listed SHA-1
13. Expand advanced settings, and enable Custom URL scheme
14. After that just download the json, name it to `client_secrets.json` and put it in `app/src/main/assets/`
+7 -8
View File
@@ -1,16 +1,16 @@
| Preview Builds | Release Builds | Tachiyomi Support Server | | Preview Builds | Release Builds | Mihon Support Server |
|-------|----------|----------| |-------|----------|----------|
| [![Preview](https://github.com/jobobby04/TachiyomiSYPreview/workflows/Remote%20Dispatch%20Build%20App/badge.svg)](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [![stable release](https://img.shields.io/github/release/jobobby04/tachiyomisy.svg?maxAge=3600&label=download)](https://github.com/jobobby04/tachiyomisy/releases/latest) | [![Discord](https://img.shields.io/discord/349436576037732353.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/tachiyomi) | | [![Preview](https://github.com/jobobby04/TachiyomiSYPreview/workflows/Remote%20Dispatch%20Build%20App/badge.svg)](https://github.com/jobobby04/TachiyomiSYPreview/releases) | [![stable release](https://img.shields.io/github/release/jobobby04/tachiyomisy.svg?maxAge=3600&label=download)](https://github.com/jobobby04/tachiyomisy/releases/latest) | [![Discord](https://img.shields.io/discord/1195734228319617024.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/mihon) |
# ![app icon](./.github/readme-images/app-icon.png)TachiyomiSY # ![app icon](./.github/readme-images/app-icon.png)TachiyomiSY
Tachiyomi is a free and open source manga reader for Android 6.0 and above. This version of Tachiyomi, TachiyomiSY was based off TachiyomiAZ. This version is meant to push forward in the ways of usability and features. TachiyomiSY tries to push forward where it can, but staying in a place where it can easily grab updates and features from the main app, it tries to make new features, or take features from other forks like J2K and Neko. Mihon is a free and open source manga reader for Android 6.0 and above. This version of Mihon, TachiyomiSY was based off TachiyomiAZ. This version is meant to push forward in the ways of usability and features. TachiyomiSY tries to push forward where it can, but staying in a place where it can easily grab updates and features from the main app, it tries to make new features, or take features from other forks like J2K and Neko.
![screenshots of app](./.github/readme-images/screens.png) ![screenshots of app](./.github/readme-images/screens.png)
## Features ## Features
Features of Tachiyomi(original) include: Features of Mihon(original) include:
* Online reading from a variety of sources * Online reading from a variety of sources
* Local reading of downloaded content * Local reading of downloaded content
* A configurable reader with multiple viewers, reading directions and other settings. * A configurable reader with multiple viewers, reading directions and other settings.
@@ -42,7 +42,6 @@ Features of TachiyomiSY include:
* Page preload customization * Page preload customization
* Customize image cache size * Customize image cache size
* Batch import of custom sources and featured extensions * Batch import of custom sources and featured extensions
* Automatic CAPTCHA solving
* Advanced source settings page, searching, enable/disable all * Advanced source settings page, searching, enable/disable all
* Click tag for local search, long click tag for global search * Click tag for local search, long click tag for global search
* Merge multiple of the same manga from different sources * Merge multiple of the same manga from different sources
@@ -75,7 +74,7 @@ Please make sure to read the full guidelines. Your issue may be closed without w
<details><summary>Issues</summary> <details><summary>Issues</summary>
1. **Before reporting a new issue, take a look at the [FAQ](https://tachiyomi.org/docs/faq/general), the [changelog](https://github.com/jobobby04/tachiyomisy/releases) and the already opened [issues](https://github.com/jobobby04/tachiyomisy/issues).** 1. **Before reporting a new issue, take a look at the [FAQ](https://tachiyomi.org/docs/faq/general), the [changelog](https://github.com/jobobby04/tachiyomisy/releases) and the already opened [issues](https://github.com/jobobby04/tachiyomisy/issues).**
2. If you are unsure, ask here: [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/tachiyomi) 2. If you are unsure, ask here: [![Discord](https://img.shields.io/discord/1195734228319617024.svg)](https://discord.gg/mihon)
</details> </details>
@@ -115,5 +114,5 @@ See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
## FAQ ## FAQ
[See our website.](https://tachiyomi.org/) [See our website.](https://mihon.app/)
You can also reach out to us on [Discord](https://discord.gg/tachiyomi). You can also reach out to us on [Discord](https://discord.gg/mihon).
+23 -15
View File
@@ -26,8 +26,8 @@ android {
defaultConfig { defaultConfig {
applicationId = "eu.kanade.tachiyomi.sy" applicationId = "eu.kanade.tachiyomi.sy"
versionCode = 60 versionCode = 66
versionName = "1.10.0" versionName = "1.10.5"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"") buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
@@ -140,18 +140,18 @@ android {
} }
dependencies { dependencies {
implementation(project(":i18n")) implementation(projects.i18n)
// SY --> // SY -->
implementation(project(":i18n-sy")) implementation(projects.i18nSy)
// SY <-- // SY <--
implementation(project(":core")) implementation(projects.core.common)
implementation(project(":core-metadata")) implementation(projects.coreMetadata)
implementation(project(":source-api")) implementation(projects.sourceApi)
implementation(project(":source-local")) implementation(projects.sourceLocal)
implementation(project(":data")) implementation(projects.data)
implementation(project(":domain")) implementation(projects.domain)
implementation(project(":presentation-core")) implementation(projects.presentationCore)
implementation(project(":presentation-widget")) implementation(projects.presentationWidget)
// Compose // Compose
implementation(platform(compose.bom)) implementation(platform(compose.bom))
@@ -167,7 +167,6 @@ dependencies {
implementation(compose.ui.util) implementation(compose.ui.util)
implementation(compose.accompanist.webview) implementation(compose.accompanist.webview)
implementation(compose.accompanist.systemuicontroller) implementation(compose.accompanist.systemuicontroller)
lintChecks(compose.lintchecks)
implementation(androidx.paging.runtime) implementation(androidx.paging.runtime)
implementation(androidx.paging.compose) implementation(androidx.paging.compose)
@@ -216,7 +215,7 @@ dependencies {
// Disk // Disk
implementation(libs.disklrucache) implementation(libs.disklrucache)
implementation(libs.unifile) implementation(libs.unifile)
implementation(libs.junrar) implementation(libs.bundles.archive)
// SY --> // SY -->
implementation(libs.zip4j) implementation(libs.zip4j)
// SY <-- // SY <--
@@ -249,6 +248,9 @@ dependencies {
implementation(libs.compose.materialmotion) implementation(libs.compose.materialmotion)
implementation(libs.swipe) implementation(libs.swipe)
implementation(libs.google.api.services.drive)
implementation(libs.google.api.client.oauth)
// Logging // Logging
implementation(libs.logcat) implementation(libs.logcat)
@@ -311,7 +313,7 @@ tasks {
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
"-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=coil.annotation.ExperimentalCoilApi", "-opt-in=coil3.annotation.ExperimentalCoilApi",
"-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi", "-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",
@@ -331,6 +333,12 @@ tasks {
project.layout.buildDirectory.dir("compose_metrics").get().asFile.absolutePath, 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",
)
} }
} }
+25 -1
View File
@@ -122,10 +122,19 @@
# 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.** { *; }
# Google Drive
-keep class com.google.api.services.** { *; }
# Google OAuth
-keep class com.google.api.client.** { *; }
# SY --> # SY -->
# SqlCipher # SqlCipher
-keepclassmembers class net.zetetic.database.sqlcipher.SQLiteCustomFunction { *; } -keepclassmembers class net.zetetic.database.sqlcipher.SQLiteCustomFunction { *; }
@@ -260,6 +269,9 @@
-keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference -keep,allowoptimization class * extends uy.kohesive.injekt.api.TypeReference
-keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; } -keep,allowoptimization public class io.requery.android.database.sqlite.SQLiteConnection { *; }
# Keep apache http client
-keep class org.apache.http.** { *; }
# Suggested rules # Suggested rules
-dontwarn com.oracle.svm.core.annotate.AutomaticFeature -dontwarn com.oracle.svm.core.annotate.AutomaticFeature
-dontwarn com.oracle.svm.core.annotate.Delete -dontwarn com.oracle.svm.core.annotate.Delete
@@ -272,4 +284,16 @@
-dontwarn org.slf4j.impl.StaticLoggerBinder -dontwarn org.slf4j.impl.StaticLoggerBinder
-dontwarn java.lang.Module -dontwarn java.lang.Module
-dontwarn org.graalvm.nativeimage.hosted.RuntimeResourceAccess -dontwarn org.graalvm.nativeimage.hosted.RuntimeResourceAccess
-dontwarn org.jspecify.annotations.NullMarked -dontwarn org.jspecify.annotations.NullMarked
-dontwarn javax.naming.InvalidNameException
-dontwarn javax.naming.NamingException
-dontwarn javax.naming.directory.Attribute
-dontwarn javax.naming.directory.Attributes
-dontwarn javax.naming.ldap.LdapName
-dontwarn javax.naming.ldap.Rdn
-dontwarn org.ietf.jgss.GSSContext
-dontwarn org.ietf.jgss.GSSCredential
-dontwarn org.ietf.jgss.GSSException
-dontwarn org.ietf.jgss.GSSManager
-dontwarn org.ietf.jgss.GSSName
-dontwarn org.ietf.jgss.Oid
+15 -1
View File
@@ -180,7 +180,7 @@
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tachiyomi" /> <data android:scheme="mihon" />
<data android:host="anilist-auth" /> <data android:host="anilist-auth" />
<data android:host="bangumi-auth" /> <data android:host="bangumi-auth" />
@@ -188,6 +188,20 @@
<data android:host="shikimori-auth" /> <data android:host="shikimori-auth" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".ui.setting.track.GoogleDriveLoginActivity"
android:label="GoogleDrive"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="eu.kanade.google.oauth" />
</intent-filter>
</activity>
<activity <activity
android:name="exh.ui.login.EhLoginActivity" android:name="exh.ui.login.EhLoginActivity"
@@ -1,7 +1,7 @@
package eu.kanade.core.preference package eu.kanade.core.preference
import androidx.compose.ui.state.ToggleableState import androidx.compose.ui.state.ToggleableState
import tachiyomi.core.preference.CheckboxState import tachiyomi.core.common.preference.CheckboxState
fun <T> CheckboxState.TriState<T>.asToggleableState() = when (this) { fun <T> CheckboxState.TriState<T>.asToggleableState() = when (this) {
is CheckboxState.TriState.Exclude -> ToggleableState.Indeterminate is CheckboxState.TriState.Exclude -> ToggleableState.Indeterminate
@@ -5,7 +5,7 @@ import androidx.compose.runtime.mutableStateOf
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
class PreferenceMutableState<T>( class PreferenceMutableState<T>(
private val preference: Preference<T>, private val preference: Preference<T>,
@@ -4,8 +4,8 @@ import android.content.Context
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
class BasePreferences( class BasePreferences(
@@ -5,9 +5,9 @@ import eu.kanade.domain.base.BasePreferences.ExtensionInstaller
import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller
import eu.kanade.tachiyomi.util.system.isShizukuInstalled import eu.kanade.tachiyomi.util.system.isShizukuInstalled
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.preference.getEnum import tachiyomi.core.common.preference.getEnum
class ExtensionInstallerPreference( class ExtensionInstallerPreference(
private val context: Context, private val context: Context,
@@ -3,8 +3,8 @@ package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.download.interactor.DeleteDownload import eu.kanade.domain.download.interactor.DeleteDownload
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.interactor.GetMergedChaptersByMangaId import tachiyomi.domain.chapter.interactor.GetMergedChaptersByMangaId
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.model.ChapterUpdate import tachiyomi.domain.chapter.model.ChapterUpdate
@@ -171,7 +171,7 @@ class SyncChaptersWithSource(
var updatedToAdd = newChapters.map { toAddItem -> var updatedToAdd = newChapters.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--) var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--)
if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter if (!chapter.isRecognizedNumber || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
chapter = chapter.copy( chapter = chapter.copy(
read = chapter.chapterNumber in deletedReadChapterNumbers, read = chapter.chapterNumber in deletedReadChapterNumbers,
@@ -39,4 +39,5 @@ fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
it.date_upload = dateUpload it.date_upload = dateUpload
it.chapter_number = chapterNumber.toFloat() it.chapter_number = chapterNumber.toFloat()
it.source_order = sourceOrder.toInt() it.source_order = sourceOrder.toInt()
it.last_modified = lastModifiedAt
} }
@@ -1,7 +1,7 @@
package eu.kanade.domain.download.interactor package eu.kanade.domain.download.interactor
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
@@ -1,7 +1,7 @@
package eu.kanade.domain.extension.interactor package eu.kanade.domain.extension.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.plusAssign import tachiyomi.core.common.preference.plusAssign
class CreateExtensionRepo(private val preferences: SourcePreferences) { class CreateExtensionRepo(private val preferences: SourcePreferences) {
@@ -1,7 +1,7 @@
package eu.kanade.domain.extension.interactor package eu.kanade.domain.extension.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.minusAssign import tachiyomi.core.common.preference.minusAssign
class DeleteExtensionRepo(private val preferences: SourcePreferences) { class DeleteExtensionRepo(private val preferences: SourcePreferences) {
@@ -23,7 +23,7 @@ class GetExtensionSources(
ExtensionSourceItem( ExtensionSourceItem(
source = source, source = source,
enabled = source.isEnabled(), enabled = source.isEnabled(),
labelAsName = isMultiSource && isMultiLangSingleSource.not(), labelAsName = isMultiSource && !isMultiLangSingleSource,
) )
} }
} }
@@ -22,10 +22,10 @@ class GetExtensionsByType(
extensionManager.availableExtensionsFlow, extensionManager.availableExtensionsFlow,
) { _activeLanguages, _installed, _untrusted, _available -> ) { _activeLanguages, _installed, _untrusted, _available ->
val (updates, installed) = _installed val (updates, installed) = _installed
.filter { (showNsfwSources || it.isNsfw.not()) } .filter { (showNsfwSources || !it.isNsfw) }
.sortedWith( .sortedWith(
compareBy<Extension.Installed> { compareBy<Extension.Installed> {
it.isObsolete.not() /* SY --> */ && it.isRedundant.not() /* SY <-- */ !it.isObsolete /* SY --> */ && !it.isRedundant /* SY <-- */
}.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name }, }.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name },
) )
.partition { it.hasUpdate } .partition { it.hasUpdate }
@@ -37,7 +37,7 @@ class GetExtensionsByType(
.filter { extension -> .filter { extension ->
_installed.none { it.pkgName == extension.pkgName } && _installed.none { it.pkgName == extension.pkgName } &&
_untrusted.none { it.pkgName == extension.pkgName } && _untrusted.none { it.pkgName == extension.pkgName } &&
(showNsfwSources || extension.isNsfw.not()) (showNsfwSources || !extension.isNsfw)
} }
.flatMap { ext -> .flatMap { ext ->
if (ext.sources.isEmpty()) { if (ext.sources.isEmpty()) {
@@ -3,7 +3,7 @@ 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 tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
class TrustExtension( class TrustExtension(
private val preferences: SourcePreferences, private val preferences: SourcePreferences,
@@ -1,6 +1,6 @@
package eu.kanade.domain.manga.interactor package eu.kanade.domain.manga.interactor
import tachiyomi.core.preference.plusAssign import tachiyomi.core.common.preference.plusAssign
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
class CreateSortTag( class CreateSortTag(
@@ -6,9 +6,9 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import eu.kanade.tachiyomi.util.storage.CbzCrypto import eu.kanade.tachiyomi.util.storage.CbzCrypto
import tachiyomi.core.common.preference.TriState
import tachiyomi.core.metadata.comicinfo.ComicInfo import tachiyomi.core.metadata.comicinfo.ComicInfo
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
import tachiyomi.core.preference.TriState
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@@ -55,6 +55,7 @@ fun Manga.copyFrom(other: SManga): Manga {
// SY --> // SY -->
val author = other.author ?: ogAuthor val author = other.author ?: ogAuthor
val artist = other.artist ?: ogArtist val artist = other.artist ?: ogArtist
val thumbnailUrl = other.thumbnail_url ?: ogThumbnailUrl
val description = other.description ?: ogDescription val description = other.description ?: ogDescription
val genres = if (other.genre != null) { val genres = if (other.genre != null) {
other.getGenres() other.getGenres()
@@ -62,15 +63,14 @@ fun Manga.copyFrom(other: SManga): Manga {
ogGenre ogGenre
} }
// SY <-- // SY <--
val thumbnailUrl = other.thumbnail_url ?: thumbnailUrl
return this.copy( return this.copy(
// SY --> // SY -->
ogAuthor = author, ogAuthor = author,
ogArtist = artist, ogArtist = artist,
ogThumbnailUrl = thumbnailUrl,
ogDescription = description, ogDescription = description,
ogGenre = genres, ogGenre = genres,
// SY <-- // SY <--
thumbnailUrl = thumbnailUrl,
// SY --> // SY -->
ogStatus = other.status.toLong(), ogStatus = other.status.toLong(),
// SY <-- // SY <--
@@ -86,11 +86,11 @@ fun SManga.toDomainManga(sourceId: Long): Manga {
ogTitle = title, ogTitle = title,
ogArtist = artist, ogArtist = artist,
ogAuthor = author, ogAuthor = author,
ogThumbnailUrl = thumbnail_url,
ogDescription = description, ogDescription = description,
ogGenre = getGenres(), ogGenre = getGenres(),
ogStatus = status.toLong(), ogStatus = status.toLong(),
// SY <-- // SY <--
thumbnailUrl = thumbnail_url,
updateStrategy = update_strategy, updateStrategy = update_strategy,
initialized = initialized, initialized = initialized,
source = sourceId, source = sourceId,
@@ -104,7 +104,13 @@ fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean {
/** /**
* Creates a ComicInfo instance based on the manga and chapter metadata. * Creates a ComicInfo instance based on the manga and chapter metadata.
*/ */
fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories: List<String>?) = ComicInfo( fun getComicInfo(
manga: Manga,
chapter: Chapter,
urls: List<String>,
categories: List<String>?,
sourceName: String,
) = ComicInfo(
title = ComicInfo.Title(chapter.name), title = ComicInfo.Title(chapter.name),
series = ComicInfo.Series(manga.title), series = ComicInfo.Series(manga.title),
number = chapter.chapterNumber.takeIf { it >= 0 }?.let { number = chapter.chapterNumber.takeIf { it >= 0 }?.let {
@@ -114,7 +120,7 @@ fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories:
ComicInfo.Number(it.toString()) ComicInfo.Number(it.toString())
} }
}, },
web = ComicInfo.Web(chapterUrl), web = ComicInfo.Web(urls.joinToString(" ")),
summary = manga.description?.let { ComicInfo.Summary(it) }, summary = manga.description?.let { ComicInfo.Summary(it) },
writer = manga.author?.let { ComicInfo.Writer(it) }, writer = manga.author?.let { ComicInfo.Writer(it) },
penciller = manga.artist?.let { ComicInfo.Penciller(it) }, penciller = manga.artist?.let { ComicInfo.Penciller(it) },
@@ -124,6 +130,7 @@ fun getComicInfo(manga: Manga, chapter: Chapter, chapterUrl: String, categories:
ComicInfoPublishingStatus.toComicInfoValue(manga.status), ComicInfoPublishingStatus.toComicInfoValue(manga.status),
), ),
categories = categories?.let { ComicInfo.CategoriesTachiyomi(it.joinToString()) }, categories = categories?.let { ComicInfo.CategoriesTachiyomi(it.joinToString()) },
source = ComicInfo.SourceMihon(sourceName),
// SY --> // SY -->
padding = CbzCrypto.createComicInfoPadding()?.let { ComicInfo.PaddingTachiyomiSY(it) }, padding = CbzCrypto.createComicInfoPadding()?.let { ComicInfo.PaddingTachiyomiSY(it) },
// SY <-- // SY <--
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.plusAssign import tachiyomi.core.common.preference.plusAssign
class CreateSourceCategory(private val preferences: SourcePreferences) { class CreateSourceCategory(private val preferences: SourcePreferences) {
@@ -1,8 +1,8 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.core.preference.minusAssign import tachiyomi.core.common.preference.minusAssign
class DeleteSourceCategory(private val preferences: SourcePreferences) { class DeleteSourceCategory(private val preferences: SourcePreferences) {
@@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.source.interactor.GetSavedSearchById import tachiyomi.domain.source.interactor.GetSavedSearchById
import tachiyomi.domain.source.interactor.GetSavedSearchBySourceId import tachiyomi.domain.source.interactor.GetSavedSearchBySourceId
import tachiyomi.domain.source.model.EXHSavedSearch import tachiyomi.domain.source.model.EXHSavedSearch
@@ -3,7 +3,7 @@ package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import tachiyomi.core.util.lang.compareToWithCollator import tachiyomi.core.common.util.lang.compareToWithCollator
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
import tachiyomi.domain.source.repository.SourceRepository import tachiyomi.domain.source.repository.SourceRepository
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
@@ -34,15 +34,15 @@ class GetSourcesWithFavoriteCount(
when (sorting) { when (sorting) {
SetMigrateSorting.Mode.ALPHABETICAL -> { SetMigrateSorting.Mode.ALPHABETICAL -> {
when { when {
a.first.isStub && b.first.isStub.not() -> -1 a.first.isStub && !b.first.isStub -> -1
b.first.isStub && a.first.isStub.not() -> 1 b.first.isStub && !a.first.isStub -> 1
else -> a.first.name.lowercase().compareToWithCollator(b.first.name.lowercase()) else -> a.first.name.lowercase().compareToWithCollator(b.first.name.lowercase())
} }
} }
SetMigrateSorting.Mode.TOTAL -> { SetMigrateSorting.Mode.TOTAL -> {
when { when {
a.first.isStub && b.first.isStub.not() -> -1 a.first.isStub && !b.first.isStub -> -1
b.first.isStub && a.first.isStub.not() -> 1 b.first.isStub && !a.first.isStub -> 1
else -> a.second.compareTo(b.second) else -> a.second.compareTo(b.second)
} }
} }
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
class RenameSourceCategory( class RenameSourceCategory(
private val preferences: SourcePreferences, private val preferences: SourcePreferences,
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
class SetSourceCategories( class SetSourceCategories(
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
class ToggleExcludeFromDataSaver( class ToggleExcludeFromDataSaver(
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
class ToggleLanguage( class ToggleLanguage(
val preferences: SourcePreferences, val preferences: SourcePreferences,
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
class ToggleSource( class ToggleSource(
@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
class ToggleSourcePin( class ToggleSourcePin(
@@ -2,9 +2,9 @@ package eu.kanade.domain.source.service
import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.domain.source.interactor.SetMigrateSorting
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.preference.getEnum import tachiyomi.core.common.preference.getEnum
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
class SourcePreferences( class SourcePreferences(
@@ -0,0 +1,89 @@
package eu.kanade.domain.sync
import eu.kanade.domain.sync.models.SyncSettings
import eu.kanade.tachiyomi.data.sync.models.SyncTriggerOptions
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import java.util.UUID
class SyncPreferences(
private val preferenceStore: PreferenceStore,
) {
fun clientHost() = preferenceStore.getString("sync_client_host", "https://sync.tachiyomi.org")
fun clientAPIKey() = preferenceStore.getString("sync_client_api_key", "")
fun lastSyncTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_sync_timestamp"), 0L)
fun syncInterval() = preferenceStore.getInt("sync_interval", 0)
fun syncService() = preferenceStore.getInt("sync_service", 0)
fun googleDriveAccessToken() = preferenceStore.getString(
Preference.appStateKey("google_drive_access_token"),
"",
)
fun googleDriveRefreshToken() = preferenceStore.getString(
Preference.appStateKey("google_drive_refresh_token"),
"",
)
fun uniqueDeviceID(): String {
val uniqueIDPreference = preferenceStore.getString("unique_device_id", "")
// Retrieve the current value of the preference
var uniqueID = uniqueIDPreference.get()
if (uniqueID.isBlank()) {
uniqueID = UUID.randomUUID().toString()
uniqueIDPreference.set(uniqueID)
}
return uniqueID
}
fun isSyncEnabled(): Boolean {
return syncService().get() != 0
}
fun getSyncSettings(): SyncSettings {
return SyncSettings(
libraryEntries = preferenceStore.getBoolean("library_entries", true).get(),
categories = preferenceStore.getBoolean("categories", true).get(),
chapters = preferenceStore.getBoolean("chapters", true).get(),
tracking = preferenceStore.getBoolean("tracking", true).get(),
history = preferenceStore.getBoolean("history", true).get(),
appSettings = preferenceStore.getBoolean("appSettings", true).get(),
sourceSettings = preferenceStore.getBoolean("sourceSettings", true).get(),
privateSettings = preferenceStore.getBoolean("privateSettings", true).get(),
)
}
fun setSyncSettings(syncSettings: SyncSettings) {
preferenceStore.getBoolean("library_entries", true).set(syncSettings.libraryEntries)
preferenceStore.getBoolean("categories", true).set(syncSettings.categories)
preferenceStore.getBoolean("chapters", true).set(syncSettings.chapters)
preferenceStore.getBoolean("tracking", true).set(syncSettings.tracking)
preferenceStore.getBoolean("history", true).set(syncSettings.history)
preferenceStore.getBoolean("appSettings", true).set(syncSettings.appSettings)
preferenceStore.getBoolean("sourceSettings", true).set(syncSettings.sourceSettings)
preferenceStore.getBoolean("privateSettings", true).set(syncSettings.privateSettings)
}
fun getSyncTriggerOptions(): SyncTriggerOptions {
return SyncTriggerOptions(
syncOnChapterRead = preferenceStore.getBoolean("sync_on_chapter_read", false).get(),
syncOnChapterOpen = preferenceStore.getBoolean("sync_on_chapter_open", false).get(),
syncOnAppStart = preferenceStore.getBoolean("sync_on_app_start", false).get(),
syncOnAppResume = preferenceStore.getBoolean("sync_on_app_resume", false).get(),
)
}
fun setSyncTriggerOptions(syncTriggerOptions: SyncTriggerOptions) {
preferenceStore.getBoolean("sync_on_chapter_read", false)
.set(syncTriggerOptions.syncOnChapterRead)
preferenceStore.getBoolean("sync_on_chapter_open", false)
.set(syncTriggerOptions.syncOnChapterOpen)
preferenceStore.getBoolean("sync_on_app_start", false)
.set(syncTriggerOptions.syncOnAppStart)
preferenceStore.getBoolean("sync_on_app_resume", false)
.set(syncTriggerOptions.syncOnAppResume)
}
}
@@ -0,0 +1,12 @@
package eu.kanade.domain.sync.models
data class SyncSettings(
val libraryEntries: Boolean = true,
val categories: Boolean = true,
val chapters: Boolean = true,
val tracking: Boolean = true,
val history: Boolean = true,
val appSettings: Boolean = true,
val sourceSettings: Boolean = true,
val privateSettings: Boolean = false,
)
@@ -8,9 +8,9 @@ import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.history.interactor.GetHistory import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
@@ -30,9 +30,9 @@ class RefreshTracks(
.map { (track, service) -> .map { (track, service) ->
async { async {
return@async try { return@async try {
val updatedTrack = service!!.refresh(track.toDbTrack()) val updatedTrack = service!!.refresh(track.toDbTrack()).toDomainTrack()!!
insertTrack.await(updatedTrack.toDomainTrack()!!) insertTrack.await(updatedTrack)
syncChapterProgressWithTrack.await(mangaId, track, service) syncChapterProgressWithTrack.await(mangaId, updatedTrack, service)
null null
} catch (e: Throwable) { } catch (e: Throwable) {
service to e service to e
@@ -4,7 +4,7 @@ import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.EnhancedTracker
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.chapter.interactor.UpdateChapter import tachiyomi.domain.chapter.interactor.UpdateChapter
import tachiyomi.domain.chapter.model.toChapterUpdate import tachiyomi.domain.chapter.model.toChapterUpdate
@@ -11,8 +11,8 @@ import exh.md.utils.FollowStatus
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack import tachiyomi.domain.track.interactor.InsertTrack
@@ -23,7 +23,7 @@ class TrackChapter(
private val delayedTrackingStore: DelayedTrackingStore, private val delayedTrackingStore: DelayedTrackingStore,
) { ) {
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) { suspend fun await(context: Context, mangaId: Long, chapterNumber: Double, setupJobOnFailure: Boolean = true) {
withNonCancellableContext { withNonCancellableContext {
val tracks = getTracks.await(mangaId) val tracks = getTracks.await(mangaId)
if (tracks.isEmpty()) return@withNonCancellableContext if (tracks.isEmpty()) return@withNonCancellableContext
@@ -34,7 +34,7 @@ class TrackChapter(
service == null || service == null ||
!service.isLoggedIn || !service.isLoggedIn ||
chapterNumber <= track.lastChapterRead /* SY --> */ || chapterNumber <= track.lastChapterRead /* SY --> */ ||
(service is MdList && track.status == FollowStatus.UNFOLLOWED.int.toLong())/* SY <-- */ (service is MdList && track.status == FollowStatus.UNFOLLOWED.long)/* SY <-- */
) { ) {
return@mapNotNull null return@mapNotNull null
} }
@@ -50,7 +50,9 @@ class TrackChapter(
delayedTrackingStore.remove(track.id) delayedTrackingStore.remove(track.id)
} catch (e: Exception) { } catch (e: Exception) {
delayedTrackingStore.add(track.id, chapterNumber) delayedTrackingStore.add(track.id, chapterNumber)
DelayedTrackingUpdateJob.setupTask(context) if (setupJobOnFailure) {
DelayedTrackingUpdateJob.setupTask(context)
}
throw e throw e
} }
} }
@@ -19,30 +19,28 @@ fun Track.toDbTrack(): DbTrack = DbTrack.create(trackerId).also {
it.remote_id = remoteId it.remote_id = remoteId
it.library_id = libraryId it.library_id = libraryId
it.title = title it.title = title
it.last_chapter_read = lastChapterRead.toFloat() it.last_chapter_read = lastChapterRead
it.total_chapters = totalChapters.toInt() it.total_chapters = totalChapters
it.status = status.toInt() it.status = status
it.score = score.toFloat() it.score = score
it.tracking_url = remoteUrl it.tracking_url = remoteUrl
it.started_reading_date = startDate it.started_reading_date = startDate
it.finished_reading_date = finishDate it.finished_reading_date = finishDate
} }
fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? { fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
val trackId = id ?: if (idRequired.not()) -1 else return null val trackId = id ?: if (!idRequired) -1 else return null
return Track( return Track(
id = trackId, id = trackId,
mangaId = manga_id, mangaId = manga_id,
trackerId = tracker_id.toLong(), trackerId = tracker_id,
remoteId = remote_id, remoteId = remote_id,
libraryId = library_id, libraryId = library_id,
title = title, title = title,
lastChapterRead = last_chapter_read.toDouble(), lastChapterRead = last_chapter_read,
totalChapters = total_chapters.toLong(), totalChapters = total_chapters,
status = status.toLong(), status = status,
// Jank workaround due to precision issues while converting score = score,
// See https://github.com/tachiyomiorg/tachiyomi/issues/10343
score = score.toString().toDouble(),
remoteUrl = tracking_url, remoteUrl = tracking_url,
startDate = started_reading_date, startDate = started_reading_date,
finishDate = finished_reading_date, finishDate = finished_reading_date,
@@ -12,8 +12,8 @@ import eu.kanade.domain.track.interactor.TrackChapter
import eu.kanade.domain.track.store.DelayedTrackingStore import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.GetTracks
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@@ -45,7 +45,7 @@ class DelayedTrackingUpdateJob(private val context: Context, workerParams: Worke
logcat(LogPriority.DEBUG) { logcat(LogPriority.DEBUG) {
"Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}" "Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}"
} }
trackChapter.await(context, track.mangaId, track.lastChapterRead) trackChapter.await(context, track.mangaId, track.lastChapterRead, setupJobOnFailure = false)
} }
} }
@@ -2,8 +2,8 @@ package eu.kanade.domain.track.service
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.anilist.Anilist import eu.kanade.tachiyomi.data.track.anilist.Anilist
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
class TrackPreferences( class TrackPreferences(
private val preferenceStore: PreferenceStore, private val preferenceStore: PreferenceStore,
@@ -19,9 +19,15 @@ class TrackPreferences(
"", "",
) )
fun trackAuthExpired(tracker: Tracker) = preferenceStore.getBoolean(
Preference.privateKey("pref_tracker_auth_expired_${tracker.id}"),
false,
)
fun setCredentials(tracker: Tracker, username: String, password: String) { fun setCredentials(tracker: Tracker, username: String, password: String) {
trackUsername(tracker).set(username) trackUsername(tracker).set(username)
trackPassword(tracker).set(password) trackPassword(tracker).set(password)
trackAuthExpired(tracker).set(false)
} }
fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "") fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")
@@ -3,7 +3,7 @@ package eu.kanade.domain.track.store
import android.content.Context import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
class DelayedTrackingStore(context: Context) { class DelayedTrackingStore(context: Context) {
@@ -6,10 +6,10 @@ import eu.kanade.domain.ui.model.TabletUiMode
import eu.kanade.domain.ui.model.ThemeMode import eu.kanade.domain.ui.model.ThemeMode
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.preference.getEnum import tachiyomi.core.common.preference.getEnum
import java.text.DateFormat import java.time.format.DateTimeFormatter
import java.text.SimpleDateFormat import java.time.format.FormatStyle
import java.util.Locale import java.util.Locale
class UiPreferences( class UiPreferences(
@@ -38,11 +38,15 @@ class UiPreferences(
fun expandFilters() = preferenceStore.getBoolean("eh_expand_filters", false) fun expandFilters() = preferenceStore.getBoolean("eh_expand_filters", false)
fun hideFeedTab() = preferenceStore.getBoolean("hide_latest_tab", false)
fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false) fun feedTabInFront() = preferenceStore.getBoolean("latest_tab_position", false)
fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", false) fun recommendsInOverflow() = preferenceStore.getBoolean("recommends_in_overflow", false)
fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", false) fun mergeInOverflow() = preferenceStore.getBoolean("merge_in_overflow", true)
fun previewsRowCount() = preferenceStore.getInt("pref_previews_row_count", 4)
fun useNewSourceNavigation() = preferenceStore.getBoolean("use_new_source_navigation", true) fun useNewSourceNavigation() = preferenceStore.getBoolean("use_new_source_navigation", true)
@@ -55,9 +59,9 @@ class UiPreferences(
// SY <-- // SY <--
companion object { companion object {
fun dateFormat(format: String): DateFormat = when (format) { fun dateFormat(format: String): DateTimeFormatter = when (format) {
"" -> DateFormat.getDateInstance(DateFormat.SHORT) "" -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
else -> SimpleDateFormat(format, Locale.getDefault()) else -> DateTimeFormatter.ofPattern(format, Locale.getDefault())
} }
} }
} }
@@ -28,7 +28,7 @@ import exh.source.isEhBasedSource
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.model.StubSource import tachiyomi.domain.source.model.StubSource
@@ -53,6 +53,7 @@ import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@@ -232,7 +233,31 @@ private fun DetailsHeader(
end = MaterialTheme.padding.medium, end = MaterialTheme.padding.medium,
top = MaterialTheme.padding.medium, top = MaterialTheme.padding.medium,
bottom = MaterialTheme.padding.small, bottom = MaterialTheme.padding.small,
), )
.clickable {
val extDebugInfo = buildString {
append(
"""
Extension name: ${extension.name} (lang: ${extension.lang}; package: ${extension.pkgName})
Extension version: ${extension.versionName} (lib: ${extension.libVersion}; version code: ${extension.versionCode})
NSFW: ${extension.isNsfw}
""".trimIndent()
)
if (extension is Extension.Installed) {
append("\n\n")
append(
"""
Update available: ${extension.hasUpdate}
Obsolete: ${extension.isObsolete}
Shared: ${extension.isShared}
Repository: ${extension.repoUrl}
""".trimIndent()
)
}
}
context.copyToClipboard("Extension Debug information", extDebugInfo)
},
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
ExtensionIcon( ExtensionIcon(
@@ -10,13 +10,11 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
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.material.icons.outlined.ErrorOutline
import androidx.compose.material.icons.outlined.GetApp import androidx.compose.material.icons.outlined.GetApp
import androidx.compose.material.icons.outlined.Public import androidx.compose.material.icons.outlined.Public
import androidx.compose.material.icons.outlined.Refresh import androidx.compose.material.icons.outlined.Refresh
@@ -40,14 +38,16 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.presentation.browse.components.BaseBrowseItem import eu.kanade.presentation.browse.components.BaseBrowseItem
import eu.kanade.presentation.browse.components.ExtensionIcon 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.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
@@ -55,6 +55,7 @@ import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission import eu.kanade.tachiyomi.util.system.launchRequestPackageInstallsPermission
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.FastScrollLazyColumn
@@ -63,6 +64,7 @@ import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.components.material.topSmallPaddingValues import tachiyomi.presentation.core.components.material.topSmallPaddingValues
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.EmptyScreenAction
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.theme.header import tachiyomi.presentation.core.theme.header
import tachiyomi.presentation.core.util.plus import tachiyomi.presentation.core.util.plus
@@ -84,6 +86,8 @@ fun ExtensionScreen(
onClickUpdateAll: () -> Unit, onClickUpdateAll: () -> Unit,
onRefresh: () -> Unit, onRefresh: () -> Unit,
) { ) {
val navigator = LocalNavigator.currentOrThrow
PullRefresh( PullRefresh(
refreshing = state.isRefreshing, refreshing = state.isRefreshing,
onRefresh = onRefresh, onRefresh = onRefresh,
@@ -94,16 +98,19 @@ fun ExtensionScreen(
state.isEmpty -> { state.isEmpty -> {
val msg = if (!searchQuery.isNullOrEmpty()) { val msg = if (!searchQuery.isNullOrEmpty()) {
MR.strings.no_results_found MR.strings.no_results_found
// SY -->
} else if (!state.hasExtensionRepos) {
SYMR.strings.no_repos_found
// SY <--
} else { } else {
MR.strings.empty_screen MR.strings.empty_screen
} }
EmptyScreen( EmptyScreen(
msg, msg,
modifier = Modifier.padding(contentPadding), modifier = Modifier.padding(contentPadding),
actions = persistentListOf(
EmptyScreenAction(
stringRes = MR.strings.label_extension_repos,
icon = Icons.Outlined.Settings,
onClick = { navigator.push(ExtensionReposScreen()) },
),
),
) )
} }
else -> { else -> {
@@ -157,31 +164,6 @@ private fun ExtensionContent(
} }
} }
// SY -->
if (!state.hasExtensionRepos) {
item(key = "extension-repos-warning") {
Column(
Modifier
.fillMaxWidth()
.padding(horizontal = MaterialTheme.padding.medium),
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Outlined.ErrorOutline,
contentDescription = null,
tint = MaterialTheme.colorScheme.error,
)
Text(
text = stringResource(SYMR.strings.no_repos_found),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.error,
)
}
}
}
// SY <--
state.items.forEach { (header, items) -> state.items.forEach { (header, items) ->
item( item(
contentType = "header", contentType = "header",
@@ -222,7 +204,13 @@ private fun ExtensionContent(
items( items(
items = items, items = items,
contentType = { "item" }, contentType = { "item" },
key = { "extension-${it.hashCode()}" }, key = { item ->
when (item.extension) {
is Extension.Untrusted -> "extension-untrusted-${item.hashCode()}"
is Extension.Installed -> "extension-installed-${item.hashCode()}"
is Extension.Available -> "extension-available-${item.hashCode()}"
}
},
) { item -> ) { item ->
ExtensionItem( ExtensionItem(
modifier = Modifier.animateItemPlacement(), modifier = Modifier.animateItemPlacement(),
@@ -37,7 +37,7 @@ import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.model.FeedSavedSearch import tachiyomi.domain.source.model.FeedSavedSearch
import tachiyomi.domain.source.model.SavedSearch import tachiyomi.domain.source.model.SavedSearch
@@ -31,7 +31,7 @@ import eu.kanade.presentation.components.AppBarActions
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
@@ -25,13 +25,13 @@ import androidx.compose.ui.res.imageResource
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import coil.compose.AsyncImage import coil3.compose.AsyncImage
import eu.kanade.domain.source.model.icon import eu.kanade.domain.source.model.icon
import eu.kanade.presentation.util.rememberResourceBitmapPainter import eu.kanade.presentation.util.rememberResourceBitmapPainter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.util.ExtensionLoader import eu.kanade.tachiyomi.extension.util.ExtensionLoader
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
@@ -86,7 +86,7 @@ private fun BrowseSourceComfortableGridItem(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f, coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
@@ -86,7 +86,7 @@ private fun BrowseSourceCompactGridItem(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f, coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
@@ -41,8 +41,8 @@ import exh.util.SourceTagsUtil
import exh.util.SourceTagsUtil.GenreColor import exh.util.SourceTagsUtil.GenreColor
import exh.util.floor import exh.util.floor
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import tachiyomi.core.i18n.pluralStringResource import tachiyomi.core.common.i18n.pluralStringResource
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
@@ -50,7 +50,8 @@ import tachiyomi.presentation.core.components.Badge
import tachiyomi.presentation.core.components.BadgeGroup import tachiyomi.presentation.core.components.BadgeGroup
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 java.util.Date import java.time.Instant
import java.time.ZoneId
@Composable @Composable
fun BrowseSourceEHentaiList( fun BrowseSourceEHentaiList(
@@ -128,9 +129,11 @@ fun BrowseSourceEHentaiListItem(
} }
val datePosted by produceState("", metadata) { val datePosted by produceState("", metadata) {
value = withIOContext { value = withIOContext {
runCatching { metadata.datePosted?.let { MetadataUtil.EX_DATE_FORMAT.format(Date(it)) } } runCatching {
.getOrNull() metadata.datePosted?.let {
.orEmpty() MetadataUtil.EX_DATE_FORMAT.format(Instant.ofEpochMilli(it).atZone(ZoneId.systemDefault()))
}
}.getOrNull().orEmpty()
} }
} }
val genre by produceState<Pair<GenreColor, StringResource>?>(null, metadata) { val genre by produceState<Pair<GenreColor, StringResource>?>(null, metadata) {
@@ -79,7 +79,7 @@ private fun BrowseSourceListItem(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f, coverAlpha = if (manga.favorite) CommonMangaItemDefaults.BrowseFavoriteCoverAlpha else 1f,
@@ -27,7 +27,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.Badge import tachiyomi.presentation.core.components.Badge
@@ -25,7 +25,7 @@ import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.util.rememberResourceBitmapPainter import eu.kanade.presentation.util.rememberResourceBitmapPainter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga import eu.kanade.tachiyomi.ui.browse.migration.advanced.process.MigratingManga
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -2,7 +2,7 @@ package eu.kanade.presentation.category
import android.content.Context import android.content.Context
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -31,7 +31,7 @@ import eu.kanade.presentation.category.visualName
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import tachiyomi.core.preference.CheckboxState import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
@@ -97,5 +97,5 @@ fun AdaptiveSheet(
private val dialogProperties = DialogProperties( private val dialogProperties = DialogProperties(
usePlatformDefaultWidth = false, usePlatformDefaultWidth = false,
decorFitsSystemWindows = false, decorFitsSystemWindows = true,
) )
@@ -9,20 +9,26 @@ import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
@Composable @Composable
fun relativeDateText( fun relativeDateText(
dateEpochMillis: Long, dateEpochMillis: Long,
): String { ): String {
return relativeDateText( return relativeDateText(
date = Date(dateEpochMillis).takeIf { dateEpochMillis > 0L }, localDate = LocalDate.ofInstant(
Instant.ofEpochMilli(dateEpochMillis),
ZoneId.systemDefault(),
)
.takeIf { dateEpochMillis > 0L },
) )
} }
@Composable @Composable
fun relativeDateText( fun relativeDateText(
date: Date?, localDate: LocalDate?,
): String { ): String {
val context = LocalContext.current val context = LocalContext.current
@@ -30,11 +36,10 @@ fun relativeDateText(
val relativeTime = remember { preferences.relativeTime().get() } val relativeTime = remember { preferences.relativeTime().get() }
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) } val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) }
return date return localDate?.toRelativeString(
?.toRelativeString( context = context,
context = context, relative = relativeTime,
relative = relativeTime, dateFormat = dateFormat,
dateFormat = dateFormat, )
)
?: stringResource(MR.strings.not_applicable) ?: stringResource(MR.strings.not_applicable)
} }
@@ -6,7 +6,7 @@ import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
@@ -15,7 +15,7 @@ import tachiyomi.presentation.core.screens.EmptyScreenAction
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun NoActionPreview() { private fun NoActionPreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
Surface { Surface {
EmptyScreen( EmptyScreen(
stringRes = MR.strings.empty_screen, stringRes = MR.strings.empty_screen,
@@ -27,7 +27,7 @@ private fun NoActionPreview() {
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun WithActionPreview() { private fun WithActionPreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
Surface { Surface {
EmptyScreen( EmptyScreen(
stringRes = MR.strings.empty_screen, stringRes = MR.strings.empty_screen,
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@@ -29,7 +30,6 @@ import androidx.compose.ui.util.fastForEachIndexed
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.HorizontalPager
import tachiyomi.presentation.core.components.material.TabText import tachiyomi.presentation.core.components.material.TabText
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -78,9 +78,8 @@ fun TabbedDialog(
modifier = Modifier.animateContentSize(), modifier = Modifier.animateContentSize(),
state = pagerState, state = pagerState,
verticalAlignment = Alignment.Top, verticalAlignment = Alignment.Top,
) { page -> pageContent = { page -> content(page) }
content(page) )
}
} }
} }
} }
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow import androidx.compose.material3.PrimaryTabRow
@@ -24,7 +25,6 @@ import dev.icerock.moko.resources.StringResource
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.presentation.core.components.HorizontalPager
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.TabText import tachiyomi.presentation.core.components.material.TabText
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -101,6 +101,6 @@ data class TabContent(
val titleRes: StringResource, val titleRes: StringResource,
val badgeNumber: Int? = null, val badgeNumber: Int? = null,
val searchEnabled: Boolean = false, val searchEnabled: Boolean = false,
val actions: ImmutableList<AppBar.Action> = persistentListOf(), val actions: ImmutableList<AppBar.AppBarAction> = persistentListOf(),
val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit, val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit,
) )
@@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.tachiyomi.util.CrashLogUtil import eu.kanade.tachiyomi.util.CrashLogUtil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@@ -63,7 +63,7 @@ fun CrashScreen(
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun CrashScreenPreview() { private fun CrashScreenPreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
CrashScreen(exception = RuntimeException("Dummy")) {} CrashScreen(exception = RuntimeException("Dummy")) {}
} }
} }
@@ -17,7 +17,7 @@ import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.components.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.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@@ -29,7 +29,7 @@ import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
import java.util.Date import java.time.LocalDate
@Composable @Composable
fun HistoryScreen( fun HistoryScreen(
@@ -134,7 +134,7 @@ private fun HistoryScreenContent(
} }
sealed interface HistoryUiModel { sealed interface HistoryUiModel {
data class Header(val date: Date) : HistoryUiModel data class Header(val date: LocalDate) : HistoryUiModel
data class Item(val item: HistoryWithRelations) : HistoryUiModel data class Item(val item: HistoryWithRelations) : HistoryUiModel
} }
@@ -144,7 +144,7 @@ internal fun HistoryScreenPreviews(
@PreviewParameter(HistoryScreenModelStateProvider::class) @PreviewParameter(HistoryScreenModelStateProvider::class)
historyState: HistoryScreenModel.State, historyState: HistoryScreenModel.State,
) { ) {
TachiyomiTheme { TachiyomiPreviewTheme {
HistoryScreen( HistoryScreen(
state = historyState, state = historyState,
snackbarHostState = SnackbarHostState(), snackbarHostState = SnackbarHostState(),
@@ -7,6 +7,7 @@ import kotlinx.collections.immutable.toImmutableList
import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.domain.history.model.HistoryWithRelations
import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.MangaCover
import java.time.Instant import java.time.Instant
import java.time.LocalDate
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import java.util.Date import java.util.Date
import kotlin.random.Random import kotlin.random.Random
@@ -73,10 +74,10 @@ class HistoryScreenModelStateProvider : PreviewParameterProvider<HistoryScreenMo
private object HistoryUiModelExamples { private object HistoryUiModelExamples {
val headerToday = header() val headerToday = header()
val headerTomorrow = val headerTomorrow =
HistoryUiModel.Header(Date.from(Instant.now().plus(1, ChronoUnit.DAYS))) HistoryUiModel.Header(LocalDate.now().plusDays(1))
fun header(instantBuilder: (Instant) -> Instant = { it }) = fun header(instantBuilder: (Instant) -> Instant = { it }) =
HistoryUiModel.Header(Date.from(instantBuilder(Instant.now()))) HistoryUiModel.Header(LocalDate.from(instantBuilder(Instant.now())))
fun items() = sequence { fun items() = sequence {
var count = 1 var count = 1
@@ -103,7 +104,7 @@ class HistoryScreenModelStateProvider : PreviewParameterProvider<HistoryScreenMo
mangaId = Random.nextLong(), mangaId = Random.nextLong(),
sourceId = Random.nextLong(), sourceId = Random.nextLong(),
isMangaFavorite = Random.nextBoolean(), isMangaFavorite = Random.nextBoolean(),
url = "https://example.com/cover.png", ogUrl = "https://example.com/cover.png",
lastModified = Random.nextLong(), lastModified = Random.nextLong(),
), ),
), ),
@@ -12,7 +12,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.LabeledCheckbox
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
@@ -91,7 +91,7 @@ fun HistoryDeleteAllDialog(
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun HistoryDeleteDialogPreview() { private fun HistoryDeleteDialogPreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
HistoryDeleteDialog( HistoryDeleteDialog(
onDismissRequest = {}, onDismissRequest = {},
onDelete = {}, onDelete = {},
@@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.manga.components.MangaCover import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.util.formatChapterNumber import eu.kanade.presentation.util.formatChapterNumber
import eu.kanade.tachiyomi.util.lang.toTimestampString import eu.kanade.tachiyomi.util.lang.toTimestampString
import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.domain.history.model.HistoryWithRelations
@@ -98,7 +98,7 @@ private fun HistoryItemPreviews(
@PreviewParameter(HistoryWithRelationsProvider::class) @PreviewParameter(HistoryWithRelationsProvider::class)
historyWithRelations: HistoryWithRelations, historyWithRelations: HistoryWithRelations,
) { ) {
TachiyomiTheme { TachiyomiPreviewTheme {
Surface { Surface {
HistoryItem( HistoryItem(
history = historyWithRelations, history = historyWithRelations,
@@ -20,7 +20,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
mangaId = 3L, mangaId = 3L,
sourceId = 4L, sourceId = 4L,
isMangaFavorite = false, isMangaFavorite = false,
url = "https://example.com/cover.png", ogUrl = "https://example.com/cover.png",
lastModified = 5L, lastModified = 5L,
), ),
) )
@@ -39,7 +39,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
mangaId = 3L, mangaId = 3L,
sourceId = 4L, sourceId = 4L,
isMangaFavorite = false, isMangaFavorite = false,
url = "https://example.com/cover.png", ogUrl = "https://example.com/cover.png",
lastModified = 5L, lastModified = 5L,
), ),
) )
@@ -58,7 +58,7 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider<HistoryWi
mangaId = 3L, mangaId = 3L,
sourceId = 4L, sourceId = 4L,
isMangaFavorite = false, isMangaFavorite = false,
url = "https://example.com/cover.png", ogUrl = "https://example.com/cover.png",
lastModified = 5L, lastModified = 5L,
), ),
) )
@@ -10,7 +10,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import tachiyomi.core.preference.CheckboxState import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.LabeledCheckbox
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -26,7 +26,7 @@ import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import tachiyomi.core.preference.TriState import tachiyomi.core.common.preference.TriState
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.library.model.LibraryGroup import tachiyomi.domain.library.model.LibraryGroup
@@ -6,7 +6,7 @@ import androidx.compose.material.icons.outlined.Folder
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import tachiyomi.presentation.core.components.Badge import tachiyomi.presentation.core.components.Badge
@Composable @Composable
@@ -50,7 +50,7 @@ internal fun LanguageBadge(
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun BadgePreview() { private fun BadgePreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
Column { Column {
DownloadsBadge(count = 10) DownloadsBadge(count = 10)
UnreadBadge(count = 10) UnreadBadge(count = 10)
@@ -41,7 +41,7 @@ internal fun LibraryComfortableGrid(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
coverBadgeStart = { coverBadgeStart = {
@@ -42,7 +42,7 @@ internal fun LibraryCompactGrid(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
coverBadgeStart = { coverBadgeStart = {
@@ -51,7 +51,7 @@ internal fun LibraryList(
mangaId = manga.id, mangaId = manga.id,
sourceId = manga.source, sourceId = manga.source,
isMangaFavorite = manga.favorite, isMangaFavorite = manga.favorite,
url = manga.thumbnailUrl, ogUrl = manga.thumbnailUrl,
lastModified = manga.coverLastModified, lastModified = manga.coverLastModified,
), ),
badge = { badge = {
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@@ -22,7 +23,6 @@ import eu.kanade.tachiyomi.ui.library.LibraryItem
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.HorizontalPager
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.util.plus import tachiyomi.presentation.core.util.plus
@@ -38,6 +38,7 @@ fun LibraryToolbar(
onClickRefresh: () -> Unit, onClickRefresh: () -> Unit,
onClickGlobalUpdate: () -> Unit, onClickGlobalUpdate: () -> Unit,
onClickOpenRandomManga: () -> Unit, onClickOpenRandomManga: () -> Unit,
onClickSyncNow: () -> Unit,
// SY --> // SY -->
onClickSyncExh: (() -> Unit)?, onClickSyncExh: (() -> Unit)?,
// SY <-- // SY <--
@@ -60,6 +61,7 @@ fun LibraryToolbar(
onClickRefresh = onClickRefresh, onClickRefresh = onClickRefresh,
onClickGlobalUpdate = onClickGlobalUpdate, onClickGlobalUpdate = onClickGlobalUpdate,
onClickOpenRandomManga = onClickOpenRandomManga, onClickOpenRandomManga = onClickOpenRandomManga,
onClickSyncNow = onClickSyncNow,
// SY --> // SY -->
onClickSyncExh = onClickSyncExh, onClickSyncExh = onClickSyncExh,
// SY <-- // SY <--
@@ -77,6 +79,7 @@ private fun LibraryRegularToolbar(
onClickRefresh: () -> Unit, onClickRefresh: () -> Unit,
onClickGlobalUpdate: () -> Unit, onClickGlobalUpdate: () -> Unit,
onClickOpenRandomManga: () -> Unit, onClickOpenRandomManga: () -> Unit,
onClickSyncNow: () -> Unit,
// SY --> // SY -->
onClickSyncExh: (() -> Unit)?, onClickSyncExh: (() -> Unit)?,
// SY <-- // SY <--
@@ -125,7 +128,10 @@ private fun LibraryRegularToolbar(
title = stringResource(MR.strings.action_open_random_manga), title = stringResource(MR.strings.action_open_random_manga),
onClick = onClickOpenRandomManga, onClick = onClickOpenRandomManga,
), ),
AppBar.OverflowAction(
title = stringResource(MR.strings.sync_library),
onClick = onClickSyncNow,
),
).builder().apply { ).builder().apply {
// SY --> // SY -->
if (onClickSyncExh != null) { if (onClickSyncExh != null) {
@@ -14,7 +14,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import exh.favorites.FavoritesSyncStatus import exh.favorites.FavoritesSyncStatus
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
@@ -13,7 +13,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat
import exh.util.toAnnotatedString import exh.util.toAnnotatedString
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@@ -31,7 +31,7 @@ import eu.kanade.domain.manga.model.forceDownloaded
import eu.kanade.presentation.components.TabbedDialog import eu.kanade.presentation.components.TabbedDialog
import eu.kanade.presentation.components.TabbedDialogPaddings import eu.kanade.presentation.components.TabbedDialogPaddings
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.preference.TriState import tachiyomi.core.common.preference.TriState
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.LabeledCheckbox import tachiyomi.presentation.core.components.LabeledCheckbox
@@ -106,7 +106,8 @@ import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrollingUp import tachiyomi.presentation.core.util.isScrollingUp
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import java.time.Instant import java.time.Instant
import java.util.Date import java.time.ZoneId
import java.time.ZonedDateTime
@Composable @Composable
fun MangaScreen( fun MangaScreen(
@@ -150,6 +151,7 @@ fun MangaScreen(
onMergeWithAnotherClicked: () -> Unit, onMergeWithAnotherClicked: () -> Unit,
onOpenPagePreview: (Int) -> Unit, onOpenPagePreview: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit, onMorePreviewsClicked: () -> Unit,
previewsRowCount: Int,
// SY <-- // SY <--
// For bottom action menu // For bottom action menu
@@ -208,6 +210,7 @@ fun MangaScreen(
onMergeWithAnotherClicked = onMergeWithAnotherClicked, onMergeWithAnotherClicked = onMergeWithAnotherClicked,
onOpenPagePreview = onOpenPagePreview, onOpenPagePreview = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked, onMorePreviewsClicked = onMorePreviewsClicked,
previewsRowCount = previewsRowCount,
// SY <-- // SY <--
onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
@@ -253,6 +256,7 @@ fun MangaScreen(
onMergeWithAnotherClicked = onMergeWithAnotherClicked, onMergeWithAnotherClicked = onMergeWithAnotherClicked,
onOpenPagePreview = onOpenPagePreview, onOpenPagePreview = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked, onMorePreviewsClicked = onMorePreviewsClicked,
previewsRowCount = previewsRowCount,
// SY <-- // SY <--
onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
@@ -308,6 +312,7 @@ private fun MangaScreenSmallImpl(
onMergeWithAnotherClicked: () -> Unit, onMergeWithAnotherClicked: () -> Unit,
onOpenPagePreview: (Int) -> Unit, onOpenPagePreview: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit, onMorePreviewsClicked: () -> Unit,
previewsRowCount: Int,
// SY <-- // SY <--
// For bottom action menu // For bottom action menu
@@ -544,13 +549,14 @@ private fun MangaScreenSmallImpl(
} }
} }
if (state.pagePreviewsState !is PagePreviewState.Unused) { if (state.pagePreviewsState !is PagePreviewState.Unused && previewsRowCount > 0) {
PagePreviewItems( PagePreviewItems(
pagePreviewState = state.pagePreviewsState, pagePreviewState = state.pagePreviewsState,
onOpenPage = onOpenPagePreview, onOpenPage = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked, onMorePreviewsClicked = onMorePreviewsClicked,
maxWidth = maxWidth, maxWidth = maxWidth,
setMaxWidth = { maxWidth = it } setMaxWidth = { maxWidth = it },
rowCount = previewsRowCount,
) )
} }
// SY <-- // SY <--
@@ -632,6 +638,7 @@ fun MangaScreenLargeImpl(
onMergeWithAnotherClicked: () -> Unit, onMergeWithAnotherClicked: () -> Unit,
onOpenPagePreview: (Int) -> Unit, onOpenPagePreview: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit, onMorePreviewsClicked: () -> Unit,
previewsRowCount: Int,
// SY <-- // SY <--
// For bottom action menu // For bottom action menu
@@ -832,11 +839,12 @@ fun MangaScreenLargeImpl(
onMergeWithAnotherClicked = onMergeWithAnotherClicked, onMergeWithAnotherClicked = onMergeWithAnotherClicked,
) )
} }
if (state.pagePreviewsState !is PagePreviewState.Unused) { if (state.pagePreviewsState !is PagePreviewState.Unused && previewsRowCount > 0) {
PagePreviews( PagePreviews(
pagePreviewState = state.pagePreviewsState, pagePreviewState = state.pagePreviewsState,
onOpenPage = onOpenPagePreview, onOpenPage = onOpenPagePreview,
onMorePreviewsClicked = onMorePreviewsClicked, onMorePreviewsClicked = onMorePreviewsClicked,
rowCount = previewsRowCount,
) )
} }
// SY <-- // SY <--
@@ -979,9 +987,10 @@ private fun LazyListScope.sharedChapterItems(
?.let { ?.let {
// SY --> // SY -->
if (manga.isEhBasedManga()) { if (manga.isEhBasedManga()) {
MetadataUtil.EX_DATE_FORMAT.format(Date(it)) MetadataUtil.EX_DATE_FORMAT
.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(it), ZoneId.systemDefault()))
} else { } else {
relativeDateText(Date(item.chapter.dateUpload)) relativeDateText(item.chapter.dateUpload)
} }
// SY <-- // SY <--
}, },
@@ -2,7 +2,6 @@ package eu.kanade.presentation.manga.components
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@@ -10,7 +9,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.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.rememberRipple 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
@@ -24,8 +23,9 @@ 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.composed
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.hapticfeedback.HapticFeedback
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
@@ -91,6 +91,7 @@ private fun NotDownloadedIndicator(
.size(IconButtonTokens.StateLayerSize) .size(IconButtonTokens.StateLayerSize)
.commonClickable( .commonClickable(
enabled = enabled, enabled = enabled,
hapticFeedback = LocalHapticFeedback.current,
onLongClick = { onClick(ChapterDownloadAction.START_NOW) }, onLongClick = { onClick(ChapterDownloadAction.START_NOW) },
onClick = { onClick(ChapterDownloadAction.START) }, onClick = { onClick(ChapterDownloadAction.START) },
) )
@@ -120,6 +121,7 @@ private fun DownloadingIndicator(
.size(IconButtonTokens.StateLayerSize) .size(IconButtonTokens.StateLayerSize)
.commonClickable( .commonClickable(
enabled = enabled, enabled = enabled,
hapticFeedback = LocalHapticFeedback.current,
onLongClick = { onClick(ChapterDownloadAction.CANCEL) }, onLongClick = { onClick(ChapterDownloadAction.CANCEL) },
onClick = { isMenuExpanded = true }, onClick = { isMenuExpanded = true },
), ),
@@ -136,6 +138,8 @@ private fun DownloadingIndicator(
modifier = IndicatorModifier, modifier = IndicatorModifier,
color = strokeColor, color = strokeColor,
strokeWidth = IndicatorStrokeWidth, strokeWidth = IndicatorStrokeWidth,
trackColor = Color.Transparent,
strokeCap = StrokeCap.Butt,
) )
} else { } else {
val animatedProgress by animateFloatAsState( val animatedProgress by animateFloatAsState(
@@ -152,6 +156,9 @@ private fun DownloadingIndicator(
modifier = IndicatorModifier, modifier = IndicatorModifier,
color = strokeColor, color = strokeColor,
strokeWidth = IndicatorSize / 2, strokeWidth = IndicatorSize / 2,
trackColor = Color.Transparent,
strokeCap = StrokeCap.Butt,
gapSize = 0.dp,
) )
} }
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) { DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
@@ -191,6 +198,7 @@ private fun DownloadedIndicator(
.size(IconButtonTokens.StateLayerSize) .size(IconButtonTokens.StateLayerSize)
.commonClickable( .commonClickable(
enabled = enabled, enabled = enabled,
hapticFeedback = LocalHapticFeedback.current,
onLongClick = { isMenuExpanded = true }, onLongClick = { isMenuExpanded = true },
onClick = { isMenuExpanded = true }, onClick = { isMenuExpanded = true },
), ),
@@ -225,6 +233,7 @@ private fun ErrorIndicator(
.size(IconButtonTokens.StateLayerSize) .size(IconButtonTokens.StateLayerSize)
.commonClickable( .commonClickable(
enabled = enabled, enabled = enabled,
hapticFeedback = LocalHapticFeedback.current,
onLongClick = { onClick(ChapterDownloadAction.START) }, onLongClick = { onClick(ChapterDownloadAction.START) },
onClick = { onClick(ChapterDownloadAction.START) }, onClick = { onClick(ChapterDownloadAction.START) },
), ),
@@ -241,26 +250,23 @@ private fun ErrorIndicator(
private fun Modifier.commonClickable( private fun Modifier.commonClickable(
enabled: Boolean, enabled: Boolean,
hapticFeedback: HapticFeedback,
onLongClick: () -> Unit, onLongClick: () -> Unit,
onClick: () -> Unit, onClick: () -> Unit,
) = composed { ) = this.combinedClickable(
val haptic = LocalHapticFeedback.current enabled = enabled,
onLongClick = {
Modifier.combinedClickable( onLongClick()
enabled = enabled, hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
onLongClick = { },
onLongClick() onClick = onClick,
haptic.performHapticFeedback(HapticFeedbackType.LongPress) role = Role.Button,
}, interactionSource = null,
onClick = onClick, indication = ripple(
role = Role.Button, bounded = false,
interactionSource = remember { MutableInteractionSource() }, radius = IconButtonTokens.StateLayerSize / 2,
indication = rememberRipple( ),
bounded = false, )
radius = IconButtonTokens.StateLayerSize / 2,
),
)
}
private val IndicatorSize = 26.dp private val IndicatorSize = 26.dp
private val IndicatorPadding = 2.dp private val IndicatorPadding = 2.dp
@@ -33,7 +33,7 @@ import androidx.compose.material.icons.outlined.Label
import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.RemoveDone import androidx.compose.material.icons.outlined.RemoveDone
import androidx.compose.material.icons.outlined.SwapCalls import androidx.compose.material.icons.outlined.SwapCalls
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -200,7 +200,7 @@ private fun RowScope.Button(
.weight(animatedWeight) .weight(animatedWeight)
.combinedClickable( .combinedClickable(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false), indication = ripple(bounded = false),
onLongClick = onLongClick, onLongClick = onLongClick,
onClick = onClick, onClick = onClick,
), ),
@@ -239,6 +239,7 @@ fun LibraryBottomActionMenu(
onClickCleanTitles: (() -> Unit)?, onClickCleanTitles: (() -> Unit)?,
onClickMigrate: (() -> Unit)?, onClickMigrate: (() -> Unit)?,
onClickAddToMangaDex: (() -> Unit)?, onClickAddToMangaDex: (() -> Unit)?,
onClickResetInfo: (() -> Unit)?,
// SY <-- // SY <--
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
@@ -267,7 +268,7 @@ fun LibraryBottomActionMenu(
} }
} }
// SY --> // SY -->
val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null val showOverflow = onClickCleanTitles != null || onClickAddToMangaDex != null || onClickResetInfo != null
val configuration = LocalConfiguration.current val configuration = LocalConfiguration.current
val moveMarkPrev = remember { !configuration.isTabletUi() } val moveMarkPrev = remember { !configuration.isTabletUi() }
var overFlowOpen by remember { mutableStateOf(false) } var overFlowOpen by remember { mutableStateOf(false) }
@@ -364,6 +365,12 @@ fun LibraryBottomActionMenu(
onClick = onClickAddToMangaDex, onClick = onClickAddToMangaDex,
) )
} }
if (onClickResetInfo != null) {
DropdownMenuItem(
text = { Text(text = stringResource(SYMR.strings.reset_info)) },
onClick = onClickResetInfo,
)
}
} }
} else { } else {
Button( Button(
@@ -24,36 +24,27 @@ import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
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
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.platform.ViewConfiguration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import me.saket.swipe.SwipeableActionsBox import me.saket.swipe.SwipeableActionsBox
import me.saket.swipe.rememberSwipeableActionsState
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.ReadItemAlpha
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
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 kotlin.math.absoluteValue
@Composable @Composable
fun MangaChapterListItem( fun MangaChapterListItem(
@@ -78,158 +69,127 @@ fun MangaChapterListItem(
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit, onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val haptic = LocalHapticFeedback.current
val density = LocalDensity.current
val textAlpha = if (read) ReadItemAlpha else 1f val textAlpha = if (read) ReadItemAlpha else 1f
val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha val textSubtitleAlpha = if (read) ReadItemAlpha else SecondaryItemAlpha
// Increase touch slop of swipe action to reduce accidental trigger val start = getSwipeAction(
val configuration = LocalViewConfiguration.current action = chapterSwipeStartAction,
CompositionLocalProvider( read = read,
LocalViewConfiguration provides object : ViewConfiguration by configuration { bookmark = bookmark,
override val touchSlop: Float = configuration.touchSlop * 3f downloadState = downloadStateProvider(),
}, background = MaterialTheme.colorScheme.primaryContainer,
onSwipe = { onChapterSwipe(chapterSwipeStartAction) },
)
val end = getSwipeAction(
action = chapterSwipeEndAction,
read = read,
bookmark = bookmark,
downloadState = downloadStateProvider(),
background = MaterialTheme.colorScheme.primaryContainer,
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
)
SwipeableActionsBox(
modifier = Modifier.clipToBounds(),
startActions = listOfNotNull(start),
endActions = listOfNotNull(end),
swipeThreshold = swipeActionThreshold,
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
) { ) {
val start = getSwipeAction( Row(
action = chapterSwipeStartAction, modifier = modifier
read = read, .selectedBackground(selected)
bookmark = bookmark, .combinedClickable(
downloadState = downloadStateProvider(), onClick = onClick,
background = MaterialTheme.colorScheme.primaryContainer, onLongClick = onLongClick,
onSwipe = { onChapterSwipe(chapterSwipeStartAction) }, )
) .padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
val end = getSwipeAction(
action = chapterSwipeEndAction,
read = read,
bookmark = bookmark,
downloadState = downloadStateProvider(),
background = MaterialTheme.colorScheme.primaryContainer,
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
)
val swipeableActionsState = rememberSwipeableActionsState()
LaunchedEffect(Unit) {
// Haptic effect when swipe over threshold
val swipeActionThresholdPx = with(density) { swipeActionThreshold.toPx() }
snapshotFlow { swipeableActionsState.offset.value.absoluteValue > swipeActionThresholdPx }
.collect { if (it) haptic.performHapticFeedback(HapticFeedbackType.LongPress) }
}
SwipeableActionsBox(
modifier = Modifier.clipToBounds(),
state = swipeableActionsState,
startActions = listOfNotNull(start),
endActions = listOfNotNull(end),
swipeThreshold = swipeActionThreshold,
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
) { ) {
Row( Column(
modifier = modifier modifier = Modifier.weight(1f),
.selectedBackground(selected) verticalArrangement = Arrangement.spacedBy(6.dp),
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
)
.padding(start = 16.dp, top = 12.dp, end = 8.dp, bottom = 12.dp),
) { ) {
Column( Row(
modifier = Modifier.weight(1f), horizontalArrangement = Arrangement.spacedBy(2.dp),
verticalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically,
) { ) {
Row( var textHeight by remember { mutableIntStateOf(0) }
horizontalArrangement = Arrangement.spacedBy(2.dp), if (!read) {
verticalAlignment = Alignment.CenterVertically, Icon(
) { imageVector = Icons.Filled.Circle,
var textHeight by remember { mutableIntStateOf(0) } contentDescription = stringResource(MR.strings.unread),
if (!read) { modifier = Modifier
Icon( .height(8.dp)
imageVector = Icons.Filled.Circle, .padding(end = 4.dp),
contentDescription = stringResource(MR.strings.unread), tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.height(8.dp)
.padding(end = 4.dp),
tint = MaterialTheme.colorScheme.primary,
)
}
if (bookmark) {
Icon(
imageVector = Icons.Filled.Bookmark,
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
modifier = Modifier
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
tint = MaterialTheme.colorScheme.primary,
)
}
Text(
text = title,
style = MaterialTheme.typography.bodyMedium,
color = LocalContentColor.current.copy(alpha = textAlpha),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
onTextLayout = { textHeight = it.size.height },
) )
} }
if (bookmark) {
Icon(
imageVector = Icons.Filled.Bookmark,
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
modifier = Modifier
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
tint = MaterialTheme.colorScheme.primary,
)
}
Text(
text = title,
style = MaterialTheme.typography.bodyMedium,
color = LocalContentColor.current.copy(alpha = textAlpha),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
onTextLayout = { textHeight = it.size.height },
)
}
Row { Row(modifier = Modifier.alpha(textSubtitleAlpha)) {
ProvideTextStyle( ProvideTextStyle(value = MaterialTheme.typography.bodySmall) {
value = MaterialTheme.typography.bodyMedium.copy( if (date != null) {
fontSize = 12.sp, Text(
color = LocalContentColor.current.copy(alpha = textSubtitleAlpha), text = date,
), maxLines = 1,
) { overflow = TextOverflow.Ellipsis,
if (date != null) { )
Text( if (readProgress != null || scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
text = date, }
maxLines = 1, if (readProgress != null) {
overflow = TextOverflow.Ellipsis, Text(
) text = readProgress,
if ( maxLines = 1,
readProgress != null || overflow = TextOverflow.Ellipsis,
scanlator != null/* SY --> */ || color = LocalContentColor.current.copy(alpha = ReadItemAlpha),
sourceName != null/* SY <-- */ )
) { if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText()
DotSeparatorText() }
} // SY -->
} if (sourceName != null) {
if (readProgress != null) { Text(
Text( text = sourceName,
text = readProgress, maxLines = 1,
maxLines = 1, overflow = TextOverflow.Ellipsis,
overflow = TextOverflow.Ellipsis, )
color = LocalContentColor.current.copy(alpha = ReadItemAlpha), if (scanlator != null) DotSeparatorText()
) }
if (scanlator != null/* SY --> */ || sourceName != null/* SY <-- */) DotSeparatorText() // SY <--
} if (scanlator != null) {
// SY --> Text(
if (sourceName != null) { text = scanlator,
Text( maxLines = 1,
text = sourceName, overflow = TextOverflow.Ellipsis,
maxLines = 1, )
overflow = TextOverflow.Ellipsis,
)
if (scanlator != null) DotSeparatorText()
}
// SY <--
if (scanlator != null) {
Text(
text = scanlator,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
} }
} }
} }
ChapterDownloadIndicator(
enabled = downloadIndicatorEnabled,
modifier = Modifier.padding(start = 4.dp),
downloadStateProvider = downloadStateProvider,
downloadProgressProvider = downloadProgressProvider,
onClick = { onDownloadClick?.invoke(it) },
)
} }
ChapterDownloadIndicator(
enabled = downloadIndicatorEnabled,
modifier = Modifier.padding(start = 4.dp),
downloadStateProvider = downloadStateProvider,
downloadProgressProvider = downloadProgressProvider,
onClick = { onDownloadClick?.invoke(it) },
)
} }
} }
} }
@@ -11,7 +11,7 @@ import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import coil.compose.AsyncImage import coil3.compose.AsyncImage
import eu.kanade.presentation.util.rememberResourceBitmapPainter import eu.kanade.presentation.util.rememberResourceBitmapPainter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@@ -38,10 +38,10 @@ import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil.imageLoader import coil3.imageLoader
import coil.request.CachePolicy import coil3.request.CachePolicy
import coil.request.ImageRequest import coil3.request.ImageRequest
import coil.size.Size import coil3.size.Size
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.DropdownMenu import eu.kanade.presentation.components.DropdownMenu
@@ -169,7 +169,9 @@ fun MangaCoverDialog(
.data(coverDataProvider()) .data(coverDataProvider())
.size(Size.ORIGINAL) .size(Size.ORIGINAL)
.memoryCachePolicy(CachePolicy.DISABLED) .memoryCachePolicy(CachePolicy.DISABLED)
.target { drawable -> .target { image ->
val drawable = image.asDrawable(view.context.resources)
// Copy bitmap in case it came from memory cache // Copy bitmap in case it came from memory cache
// Because SSIV needs to thoroughly read the image // Because SSIV needs to thoroughly read the image
val copy = (drawable as? BitmapDrawable)?.let { val copy = (drawable as? BitmapDrawable)?.let {
@@ -73,7 +73,7 @@ import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage import coil3.compose.AsyncImage
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
@@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
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
@@ -44,7 +44,7 @@ fun MissingChapterCountListItem(
@PreviewLightDark @PreviewLightDark
@Composable @Composable
private fun Preview() { private fun Preview() {
TachiyomiTheme { TachiyomiPreviewTheme {
Surface { Surface {
MissingChapterCountListItem(count = 42) MissingChapterCountListItem(count = 42)
} }
@@ -19,12 +19,12 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.components.ChipBorder import eu.kanade.presentation.components.ChipBorder
import eu.kanade.presentation.components.SuggestionChip import eu.kanade.presentation.components.SuggestionChip
import eu.kanade.presentation.components.SuggestionChipDefaults import eu.kanade.presentation.components.SuggestionChipDefaults
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.source.online.all.EHentai
import exh.metadata.metadata.EHentaiSearchMetadata import exh.metadata.metadata.EHentaiSearchMetadata
@@ -173,10 +173,10 @@ fun TagsChip(
} }
} }
@Preview @PreviewLightDark
@Composable @Composable
fun NamespaceTagsPreview() { fun NamespaceTagsPreview() {
TachiyomiTheme { TachiyomiPreviewTheme {
Surface { Surface {
val context = LocalContext.current val context = LocalContext.current
NamespaceTags( NamespaceTags(
@@ -25,14 +25,13 @@ 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.draw.clipToBounds
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil.compose.SubcomposeAsyncImage import coil3.compose.SubcomposeAsyncImage
import coil.compose.SubcomposeAsyncImageContent import coil3.compose.SubcomposeAsyncImageContent
import eu.kanade.domain.manga.model.PagePreview import eu.kanade.domain.manga.model.PagePreview
import eu.kanade.presentation.manga.MangaScreenItem import eu.kanade.presentation.manga.MangaScreenItem
import eu.kanade.tachiyomi.ui.manga.PagePreviewState import eu.kanade.tachiyomi.ui.manga.PagePreviewState
@@ -102,6 +101,7 @@ fun PagePreviews(
pagePreviewState: PagePreviewState, pagePreviewState: PagePreviewState,
onOpenPage: (Int) -> Unit, onOpenPage: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit, onMorePreviewsClicked: () -> Unit,
rowCount: Int,
) { ) {
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
var maxWidth by remember { var maxWidth by remember {
@@ -113,7 +113,7 @@ fun PagePreviews(
} }
pagePreviewState is PagePreviewState.Success -> { pagePreviewState is PagePreviewState.Success -> {
val itemPerRowCount = (maxWidth / 120.dp).floor() val itemPerRowCount = (maxWidth / 120.dp).floor()
pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount).forEach { pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount).forEach {
PagePreviewRow( PagePreviewRow(
onOpenPage = onOpenPage, onOpenPage = onOpenPage,
items = remember(it) { it.toImmutableList() } items = remember(it) { it.toImmutableList() }
@@ -132,7 +132,8 @@ fun LazyListScope.PagePreviewItems(
onOpenPage: (Int) -> Unit, onOpenPage: (Int) -> Unit,
onMorePreviewsClicked: () -> Unit, onMorePreviewsClicked: () -> Unit,
maxWidth: Dp, maxWidth: Dp,
setMaxWidth: (Dp) -> Unit setMaxWidth: (Dp) -> Unit,
rowCount: Int,
) { ) {
when { when {
pagePreviewState is PagePreviewState.Loading || maxWidth == Dp.Hairline -> { pagePreviewState is PagePreviewState.Loading || maxWidth == Dp.Hairline -> {
@@ -148,7 +149,7 @@ fun LazyListScope.PagePreviewItems(
items( items(
key = { "${MangaScreenItem.CHAPTER_PREVIEW_ROW}-$it" }, key = { "${MangaScreenItem.CHAPTER_PREVIEW_ROW}-$it" },
contentType = { MangaScreenItem.CHAPTER_PREVIEW_ROW }, contentType = { MangaScreenItem.CHAPTER_PREVIEW_ROW },
items = pagePreviewState.pagePreviews.take(4 * itemPerRowCount).chunked(itemPerRowCount), items = pagePreviewState.pagePreviews.take(rowCount * itemPerRowCount).chunked(itemPerRowCount),
) { ) {
PagePreviewRow( PagePreviewRow(
onOpenPage = onOpenPage, onOpenPage = onOpenPage,

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