Compare commits

...

38 Commits

Author SHA1 Message Date
2a01a2ac6b Release v0.16.5 2024-04-09 14:17:04 +06:00
9a6559b013 Remove unused imports 2024-04-09 14:17:04 +06:00
a7509b3a3c Fix build time zone in about screen
And slight cleanup
2024-04-09 14:17:04 +06:00
2755d1f35e chore(deps): update dependency gradle to v8.7 (#567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-09 14:17:04 +06:00
6a8a9c6bbf Address detekt issues 2024-04-09 14:17:04 +06:00
w
7862088b94 Update image-decoder, color management (#523)
* Update image-decoder, color management

* move display profile pref

* remove true color pref

* Move Display Profile settings to a new section

* Partially revert "remove true color pref"

This partially reverts commit e1a7581695.

* Tweak label

---------

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

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

* Removed parentheses to make detekt happy

* Updated relative date display for dates in the future

* Small cleanup for header creation logic

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

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

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

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

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

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

* Rename isRetry parameter to setupJobOnFailure

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

* Update History Screen to use new localdate based relative times

* Update Updates Screen to use new localdate based relative times

* Cleaned up date util classes

* Updated build time display

* Code cleanup

* Fixed crash in settings

* Updated Preferences item

* Worker Info works

* Fixed Tracker date display

* Code changes to pass detekt
2024-04-09 13:23:42 +06:00
a4f5dfab1a Release v0.16.4 2024-02-26 22:19:23 +06:00
085147b15b Fix detekt issue 2024-02-26 22:19:23 +06:00
085ad8d446 Don't add custom User Agent for MAL
Closes #298
2024-02-26 22:08:11 +06:00
139663acfc Release v0.16.3 2024-01-30 02:31:45 +06:00
1581b876cf Remove old ISSUE_TEMPLATE.md 2024-01-30 02:31:45 +06:00
0f4de03d7a Don't throw MALTokenExpired whenever we fail to refresh MAL token
Also cleanup
2024-01-30 02:31:45 +06:00
ddbe8efbc5 [skip ci] Increase size of the message indicating which apk to download 2024-01-30 02:31:44 +06:00
63146e717b 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>
2024-01-30 02:31:16 +06:00
b2d22f86c6 Lint 2024-01-29 23:09:09 +06:00
79f46b25f6 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
2024-01-29 23:08:28 +06:00
aa498360db Move :core to :core:common 2024-01-29 15:20:21 +06:00
f03f998b21 [skip ci] Delete ic_launcher-web.png 2024-01-29 14:31:48 +06:00
4811cf07cd Address build warning in :i18n
And small cleanup
2024-01-29 14:29:04 +06:00
b71c793fad 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>
2024-01-29 13:57:23 +06:00
47e5421527 Upgrade combose-bom to latest 2024-01-29 13:25:01 +06:00
5dc6501688 Fix #197 - Scroll crashing (#272)
Updating compose bom.
2024-01-29 12:56:29 +06:00
cc09230e26 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>
2024-01-29 03:29:55 +06:00
9c4d2b087f [skip ci] Update issue templates 2024-01-29 02:03:00 +06:00
4bcba0503a Update dependency com.android.tools.build:gradle to v8.2.2 (#256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-28 20:39:37 +06:00
cf33f250cc Change extension update error file name (#253) 2024-01-28 20:32:23 +06:00
915a967151 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
2024-01-28 20:31:59 +06:00
9cc0c4e035 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>
2024-01-28 16:13:18 +06:00
297 changed files with 2181 additions and 729 deletions

View File

@ -1,34 +0,0 @@
**PLEASE READ THIS**
I acknowledge that:
- I have updated:
- To the latest version of the app (stable is v0.15.3)
- All extensions
- I have gone through the FAQ (https://mihon.app/docs/faq/general) and troubleshooting guide (https://mihon.app/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.

View File

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

View File

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

View File

@ -37,4 +37,4 @@ jobs:
- name: Build app and run unit tests - name: Build app and run unit tests
uses: gradle/gradle-command-action@v2 uses: gradle/gradle-command-action@v2
with: with:
arguments: ktlintCheck assembleStandardRelease testReleaseUnitTest arguments: detekt assembleStandardRelease testReleaseUnitTest

View File

@ -35,7 +35,7 @@ jobs:
- name: Build app and run unit tests - name: Build app and run unit tests
uses: gradle/gradle-command-action@v2 uses: gradle/gradle-command-action@v2
with: with:
arguments: ktlintCheck assembleStandardRelease testReleaseUnitTest arguments: detekt assembleStandardRelease testReleaseUnitTest
# Sign APK and create release for tags # Sign APK and create release for tags
@ -99,7 +99,7 @@ jobs:
| 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 mihon-${{ env.VERSION_TAG }}.apk ## If you are unsure which version to choose then go with mihon-${{ env.VERSION_TAG }}.apk
files: | files: |
mihon-${{ env.VERSION_TAG }}.apk mihon-${{ env.VERSION_TAG }}.apk
mihon-arm64-v8a-${{ env.VERSION_TAG }}.apk mihon-arm64-v8a-${{ env.VERSION_TAG }}.apk

View File

@ -22,8 +22,8 @@ android {
defaultConfig { defaultConfig {
applicationId = "app.mihon" applicationId = "app.mihon"
versionCode = 3 versionCode = 6
versionName = "0.16.2" versionName = "0.16.5"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"") buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
@ -140,7 +140,7 @@ android {
dependencies { dependencies {
implementation(projects.i18n) implementation(projects.i18n)
implementation(projects.core) implementation(projects.core.common)
implementation(projects.coreMetadata) implementation(projects.coreMetadata)
implementation(projects.sourceApi) implementation(projects.sourceApi)
implementation(projects.sourceLocal) implementation(projects.sourceLocal)
@ -163,7 +163,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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

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

View File

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

View File

@ -2,8 +2,8 @@ package eu.kanade.domain.base
import android.content.Context import android.content.Context
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import 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(
@ -28,4 +28,6 @@ class BasePreferences(
SHIZUKU(MR.strings.ext_installer_shizuku, false), SHIZUKU(MR.strings.ext_installer_shizuku, false),
PRIVATE(MR.strings.ext_installer_private, false), PRIVATE(MR.strings.ext_installer_private, false),
} }
fun displayProfile() = preferenceStore.getString("pref_display_profile_key", "")
} }

View File

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

View File

@ -2,8 +2,8 @@ package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.download.interactor.DeleteDownload import eu.kanade.domain.download.interactor.DeleteDownload
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.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.model.ChapterUpdate import tachiyomi.domain.chapter.model.ChapterUpdate
import tachiyomi.domain.chapter.repository.ChapterRepository import tachiyomi.domain.chapter.repository.ChapterRepository

View File

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

View File

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

View File

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

View File

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

View File

@ -5,9 +5,9 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.source.model.SManga 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 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,8 +9,8 @@ import eu.kanade.tachiyomi.data.track.TrackerManager
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
@ -21,7 +21,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
@ -43,7 +43,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
} }
} }

View File

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

View File

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

View File

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

View File

@ -5,10 +5,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(
@ -31,9 +31,9 @@ class UiPreferences(
fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", TabletUiMode.AUTOMATIC) fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", TabletUiMode.AUTOMATIC)
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())
} }
} }
} }

View File

@ -24,7 +24,7 @@ import eu.kanade.presentation.util.formattedMessage
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
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

View File

@ -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
@ -224,7 +225,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(

View File

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

View File

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

View File

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

View File

@ -97,5 +97,5 @@ fun AdaptiveSheet(
private val dialogProperties = DialogProperties( private val dialogProperties = DialogProperties(
usePlatformDefaultWidth = false, usePlatformDefaultWidth = false,
decorFitsSystemWindows = false, decorFitsSystemWindows = true,
) )

View File

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

View File

@ -28,7 +28,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(
@ -133,7 +133,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
} }

View File

@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
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
@ -71,10 +72,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

View File

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

View File

@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel
import eu.kanade.tachiyomi.util.system.isDevFlavor import eu.kanade.tachiyomi.util.system.isDevFlavor
import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
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.LibrarySort import tachiyomi.domain.library.model.LibrarySort

View File

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

View File

@ -10,7 +10,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
@ -256,7 +256,7 @@ private fun Modifier.commonClickable(
onClick = onClick, onClick = onClick,
role = Role.Button, role = Role.Button,
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple( indication = ripple(
bounded = false, bounded = false,
radius = IconButtonTokens.StateLayerSize / 2, radius = IconButtonTokens.StateLayerSize / 2,
), ),

View File

@ -30,7 +30,7 @@ import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.DoneAll import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.RemoveDone import androidx.compose.material.icons.outlined.RemoveDone
import androidx.compose.material.ripple.rememberRipple import androidx.compose.material.ripple
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@ -192,7 +192,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,
), ),

View File

@ -26,7 +26,7 @@ import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.more.DownloadQueueState import eu.kanade.tachiyomi.ui.more.DownloadQueueState
import tachiyomi.core.Constants import tachiyomi.core.common.Constants
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold

View File

@ -8,7 +8,7 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.core.preference.Preference as PreferenceData import tachiyomi.core.common.preference.Preference as PreferenceData
sealed class Preference { sealed class Preference {
abstract val title: String abstract val title: String

View File

@ -6,6 +6,8 @@ import android.content.Intent
import android.provider.Settings import android.provider.Settings
import android.webkit.WebStorage import android.webkit.WebStorage
import android.webkit.WebView import android.webkit.WebView
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
@ -57,9 +59,9 @@ import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import okhttp3.Headers import okhttp3.Headers
import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.manga.interactor.ResetViewerFlags import tachiyomi.domain.manga.interactor.ResetViewerFlags
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
@ -123,6 +125,7 @@ object SettingsAdvancedScreen : SearchableSettings {
getDataGroup(), getDataGroup(),
getNetworkGroup(networkPreferences = networkPreferences), getNetworkGroup(networkPreferences = networkPreferences),
getLibraryGroup(), getLibraryGroup(),
getReaderGroup(basePreferences = basePreferences),
getExtensionsGroup(basePreferences = basePreferences), getExtensionsGroup(basePreferences = basePreferences),
) )
} }
@ -313,6 +316,34 @@ object SettingsAdvancedScreen : SearchableSettings {
) )
} }
@Composable
private fun getReaderGroup(
basePreferences: BasePreferences,
): Preference.PreferenceGroup {
val context = LocalContext.current
val chooseColorProfile = rememberLauncherForActivityResult(
contract = ActivityResultContracts.OpenDocument(),
) { uri ->
uri?.let {
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flags)
basePreferences.displayProfile().set(uri.toString())
}
}
return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_reader),
preferenceItems = persistentListOf(
Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_display_profile),
subtitle = basePreferences.displayProfile().get(),
onClick = {
chooseColorProfile.launch(arrayOf("*/*"))
},
),
)
)
}
@Composable @Composable
private fun getExtensionsGroup( private fun getExtensionsGroup(
basePreferences: BasePreferences, basePreferences: BasePreferences,

View File

@ -26,7 +26,7 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.time.Instant import java.time.LocalDate
object SettingsAppearanceScreen : SearchableSettings { object SettingsAppearanceScreen : SearchableSettings {
@ -101,7 +101,7 @@ object SettingsAppearanceScreen : SearchableSettings {
val context = LocalContext.current val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val now = remember { Instant.now().toEpochMilli() } val now = remember { LocalDate.now() }
val dateFormat by uiPreferences.dateFormat().collectAsState() val dateFormat by uiPreferences.dateFormat().collectAsState()
val formattedNow = remember(dateFormat) { val formattedNow = remember(dateFormat) {

View File

@ -13,7 +13,7 @@ import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen import eu.kanade.presentation.more.settings.screen.browse.ExtensionReposScreen
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.pluralStringResource import tachiyomi.presentation.core.i18n.pluralStringResource
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource

View File

@ -50,11 +50,11 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.storage.displayablePath import tachiyomi.core.common.storage.displayablePath
import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.storage.service.StoragePreferences import tachiyomi.domain.storage.service.StoragePreferences
@ -100,7 +100,7 @@ object SettingsDataScreen : SearchableSettings {
@Composable @Composable
fun storageLocationPicker( fun storageLocationPicker(
storageDirPref: tachiyomi.core.preference.Preference<String>, storageDirPref: tachiyomi.core.common.preference.Preference<String>,
): ManagedActivityResultLauncher<Uri?, Uri?> { ): ManagedActivityResultLauncher<Uri?, Uri?> {
val context = LocalContext.current val context = LocalContext.current
@ -122,7 +122,7 @@ object SettingsDataScreen : SearchableSettings {
@Composable @Composable
fun storageLocationText( fun storageLocationText(
storageDirPref: tachiyomi.core.preference.Preference<String>, storageDirPref: tachiyomi.core.common.preference.Preference<String>,
): String { ): String {
val context = LocalContext.current val context = LocalContext.current
val storageDir by storageDirPref.collectAsState() val storageDir by storageDirPref.collectAsState()

View File

@ -29,6 +29,7 @@ object SettingsReaderScreen : SearchableSettings {
@Composable @Composable
override fun getPreferences(): List<Preference> { override fun getPreferences(): List<Preference> {
val readerPref = remember { Injekt.get<ReaderPreferences>() } val readerPref = remember { Injekt.get<ReaderPreferences>() }
return listOf( return listOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
pref = readerPref.defaultReadingMode(), pref = readerPref.defaultReadingMode(),
@ -56,11 +57,6 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_show_navigation_mode), title = stringResource(MR.strings.pref_show_navigation_mode),
subtitle = stringResource(MR.strings.pref_show_navigation_mode_summary), subtitle = stringResource(MR.strings.pref_show_navigation_mode_summary),
), ),
Preference.PreferenceItem.SwitchPreference(
pref = readerPref.trueColor(),
title = stringResource(MR.strings.pref_true_color),
subtitle = stringResource(MR.strings.pref_true_color_summary),
),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPref.pageTransitions(), pref = readerPref.pageTransitions(),
title = stringResource(MR.strings.pref_page_transitions), title = stringResource(MR.strings.pref_page_transitions),

View File

@ -12,7 +12,7 @@ import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableMap import kotlinx.collections.immutable.toImmutableMap
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.pluralStringResource import tachiyomi.presentation.core.i18n.pluralStringResource
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource

View File

@ -53,8 +53,8 @@ import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding

View File

@ -38,9 +38,9 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.release.interactor.GetApplicationRelease import tachiyomi.domain.release.interactor.GetApplicationRelease
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LinkIcon import tachiyomi.presentation.core.components.LinkIcon
@ -55,10 +55,9 @@ import tachiyomi.presentation.core.icons.Reddit
import tachiyomi.presentation.core.icons.X import tachiyomi.presentation.core.icons.X
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.text.DateFormat import java.time.Instant
import java.text.SimpleDateFormat import java.time.LocalDateTime
import java.util.Locale import java.time.ZoneId
import java.util.TimeZone
object AboutScreen : Screen() { object AboutScreen : Screen() {
@ -269,18 +268,15 @@ object AboutScreen : Screen() {
internal fun getFormattedBuildTime(): String { internal fun getFormattedBuildTime(): String {
return try { return try {
val inputDf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US) LocalDateTime.ofInstant(
inputDf.timeZone = TimeZone.getTimeZone("UTC") Instant.parse(BuildConfig.BUILD_TIME),
val buildTime = inputDf.parse(BuildConfig.BUILD_TIME) ZoneId.systemDefault(),
val outputDf = DateFormat.getDateTimeInstance(
DateFormat.MEDIUM,
DateFormat.SHORT,
Locale.getDefault(),
) )
outputDf.timeZone = TimeZone.getDefault() .toDateTimestampString(
UiPreferences.dateFormat(
buildTime!!.toDateTimestampString(UiPreferences.dateFormat(Injekt.get<UiPreferences>().dateFormat().get())) Injekt.get<UiPreferences>().dateFormat().get(),
),
)
} catch (e: Exception) { } catch (e: Exception) {
BuildConfig.BUILD_TIME BuildConfig.BUILD_TIME
} }

View File

@ -37,9 +37,9 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.util.lang.launchUI import tachiyomi.core.common.util.lang.launchUI
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.data.Database import tachiyomi.data.Database
import tachiyomi.domain.source.interactor.GetSourcesWithNonLibraryManga import tachiyomi.domain.source.interactor.GetSourcesWithNonLibraryManga
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source

View File

@ -30,7 +30,7 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource

View File

@ -13,7 +13,7 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -42,7 +42,9 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.plus import tachiyomi.presentation.core.util.plus
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.LocalDateTime
import java.time.ZoneId
class WorkerInfoScreen : Screen() { class WorkerInfoScreen : Screen() {
@ -149,11 +151,17 @@ class WorkerInfoScreen : Screen() {
appendLine("State: ${workInfo.state}") appendLine("State: ${workInfo.state}")
if (workInfo.state == WorkInfo.State.ENQUEUED) { if (workInfo.state == WorkInfo.State.ENQUEUED) {
appendLine( appendLine(
"Next scheduled run: ${Date(workInfo.nextScheduleTimeMillis).toDateTimestampString( "Next scheduled run: ${
UiPreferences.dateFormat( LocalDateTime.ofInstant(
Injekt.get<UiPreferences>().dateFormat().get(), Instant.ofEpochMilli(workInfo.nextScheduleTimeMillis),
), ZoneId.systemDefault(),
)}", )
.toDateTimestampString(
UiPreferences.dateFormat(
Injekt.get<UiPreferences>().dateFormat().get(),
),
)
}",
) )
appendLine("Attempt #${workInfo.runAttemptCount + 1}") appendLine("Attempt #${workInfo.runAttemptCount + 1}")
} }

View File

@ -48,7 +48,7 @@ import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiTheme
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.InMemoryPreferenceStore import tachiyomi.core.common.preference.InMemoryPreferenceStore
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource

View File

@ -11,7 +11,7 @@ import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.ColorFilterMode import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.ColorFilterMode
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.CheckboxItem
import tachiyomi.presentation.core.components.SettingsChipRow import tachiyomi.presentation.core.components.SettingsChipRow

View File

@ -42,7 +42,7 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
pref = screenModel.preferences.fullscreen(), pref = screenModel.preferences.fullscreen(),
) )
if (screenModel.hasDisplayCutout) { if (screenModel.hasDisplayCutout && screenModel.preferences.fullscreen().get()) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_cutout_short), label = stringResource(MR.strings.pref_cutout_short),
pref = screenModel.preferences.cutoutShort(), pref = screenModel.preferences.cutoutShort(),

View File

@ -52,17 +52,18 @@ import eu.kanade.presentation.theme.TachiyomiPreviewTheme
import eu.kanade.presentation.track.components.TrackLogoIcon import eu.kanade.presentation.track.components.TrackLogoIcon
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.lang.toLocalDate
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import java.text.DateFormat import java.time.format.DateTimeFormatter
private const val UnsetStatusTextAlpha = 0.5F private const val UnsetStatusTextAlpha = 0.5F
@Composable @Composable
fun TrackInfoDialogHome( fun TrackInfoDialogHome(
trackItems: List<TrackItem>, trackItems: List<TrackItem>,
dateFormat: DateFormat, dateFormat: DateTimeFormatter,
onStatusClick: (TrackItem) -> Unit, onStatusClick: (TrackItem) -> Unit,
onChapterClick: (TrackItem) -> Unit, onChapterClick: (TrackItem) -> Unit,
onScoreClick: (TrackItem) -> Unit, onScoreClick: (TrackItem) -> Unit,
@ -104,11 +105,11 @@ fun TrackInfoDialogHome(
.takeIf { supportsScoring && item.track.score != 0.0 }, .takeIf { supportsScoring && item.track.score != 0.0 },
onScoreClick = { onScoreClick(item) } onScoreClick = { onScoreClick(item) }
.takeIf { supportsScoring }, .takeIf { supportsScoring },
startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) } startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate.toLocalDate()) }
.takeIf { supportsReadingDates && item.track.startDate != 0L }, .takeIf { supportsReadingDates && item.track.startDate != 0L },
onStartDateClick = { onStartDateEdit(item) } // TODO onStartDateClick = { onStartDateEdit(item) } // TODO
.takeIf { supportsReadingDates }, .takeIf { supportsReadingDates },
endDate = dateFormat.format(item.track.finishDate) endDate = dateFormat.format(item.track.finishDate.toLocalDate())
.takeIf { supportsReadingDates && item.track.finishDate != 0L }, .takeIf { supportsReadingDates && item.track.finishDate != 0L },
onEndDateClick = { onEndDateEdit(item) } onEndDateClick = { onEndDateEdit(item) }
.takeIf { supportsReadingDates }, .takeIf { supportsReadingDates },

View File

@ -5,7 +5,8 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.test.DummyTracker import eu.kanade.test.DummyTracker
import tachiyomi.domain.track.model.Track import tachiyomi.domain.track.model.Track
import java.text.DateFormat import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
internal class TrackInfoDialogHomePreviewProvider : internal class TrackInfoDialogHomePreviewProvider :
PreviewParameterProvider<@Composable () -> Unit> { PreviewParameterProvider<@Composable () -> Unit> {
@ -46,7 +47,7 @@ internal class TrackInfoDialogHomePreviewProvider :
trackItemWithoutTrack, trackItemWithoutTrack,
trackItemWithTrack, trackItemWithTrack,
), ),
dateFormat = DateFormat.getDateInstance(), dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM),
onStatusClick = {}, onStatusClick = {},
onChapterClick = {}, onChapterClick = {},
onScoreClick = {}, onScoreClick = {},
@ -61,7 +62,7 @@ internal class TrackInfoDialogHomePreviewProvider :
private val noTrackers = @Composable { private val noTrackers = @Composable {
TrackInfoDialogHome( TrackInfoDialogHome(
trackItems = listOf(), trackItems = listOf(),
dateFormat = DateFormat.getDateInstance(), dateFormat = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM),
onStatusClick = {}, onStatusClick = {},
onChapterClick = {}, onChapterClick = {},
onScoreClick = {}, onScoreClick = {},

View File

@ -36,7 +36,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
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@Composable @Composable
@ -206,6 +206,6 @@ private fun UpdatesBottomBar(
} }
sealed interface UpdatesUiModel { sealed interface UpdatesUiModel {
data class Header(val date: Date) : UpdatesUiModel data class Header(val date: LocalDate) : UpdatesUiModel
data class Item(val item: UpdatesItem) : UpdatesUiModel data class Item(val item: UpdatesItem) : UpdatesUiModel
} }

View File

@ -4,7 +4,7 @@ import android.content.Context
import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.network.HttpException
import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException
import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.isOnline
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.data.source.NoResultsException import tachiyomi.data.source.NoResultsException
import tachiyomi.domain.source.model.SourceNotInstalledException import tachiyomi.domain.source.model.SourceNotInstalledException
import tachiyomi.i18n.MR import tachiyomi.i18n.MR

View File

@ -4,7 +4,7 @@ import android.content.Context
import android.text.format.DateUtils import android.text.format.DateUtils
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import java.time.Instant import java.time.Instant

View File

@ -49,8 +49,8 @@ import logcat.AndroidLogcatLogger
import logcat.LogPriority import logcat.LogPriority
import logcat.LogcatLogger import logcat.LogcatLogger
import org.conscrypt.Conscrypt import org.conscrypt.Conscrypt
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.widget.WidgetManager import tachiyomi.presentation.widget.WidgetManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt

View File

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi package eu.kanade.tachiyomi
import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.common.util.system.ImageUtil
/** /**
* Used by extensions. * Used by extensions.

View File

@ -3,8 +3,8 @@ package eu.kanade.tachiyomi
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
object Migrations { object Migrations {

View File

@ -10,7 +10,7 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import kotlin.system.exitProcess import kotlin.system.exitProcess
class GlobalExceptionHandler private constructor( class GlobalExceptionHandler private constructor(

View File

@ -12,9 +12,9 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notify import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.i18n.pluralStringResource import tachiyomi.core.common.i18n.pluralStringResource
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.storage.displayablePath import tachiyomi.core.common.storage.displayablePath
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File

View File

@ -24,7 +24,7 @@ import eu.kanade.tachiyomi.util.system.isRunning
import eu.kanade.tachiyomi.util.system.setForegroundSafely import eu.kanade.tachiyomi.util.system.setForegroundSafely
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.storage.service.StorageManager import tachiyomi.domain.storage.service.StorageManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt

View File

@ -21,8 +21,8 @@ import logcat.LogPriority
import okio.buffer import okio.buffer
import okio.gzip import okio.gzip
import okio.sink import okio.sink
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.manga.interactor.GetFavorites import tachiyomi.domain.manga.interactor.GetFavorites
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga

View File

@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.preferenceKey import eu.kanade.tachiyomi.source.preferenceKey
import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.Preference import tachiyomi.core.common.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -19,8 +19,8 @@ import eu.kanade.tachiyomi.util.system.setForegroundSafely
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) : class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) :

View File

@ -16,7 +16,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat

View File

@ -12,8 +12,8 @@ import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.AndroidPreferenceStore import tachiyomi.core.common.preference.AndroidPreferenceStore
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -12,7 +12,7 @@ import logcat.LogPriority
import okhttp3.Response import okhttp3.Response
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException

View File

@ -27,7 +27,7 @@ import okio.Source
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import okio.source import okio.source
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.MangaCover
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager

View File

@ -9,7 +9,7 @@ import coil.decode.ImageSource
import coil.fetch.SourceResult import coil.fetch.SourceResult
import coil.request.Options import coil.request.Options
import okio.BufferedSource import okio.BufferedSource
import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.decoder.ImageDecoder import tachiyomi.decoder.ImageDecoder
/** /**
@ -24,7 +24,7 @@ class TachiyomiImageDecoder(private val resources: ImageSource, private val opti
check(decoder != null && decoder.width > 0 && decoder.height > 0) { "Failed to initialize decoder" } check(decoder != null && decoder.width > 0 && decoder.height > 0) { "Failed to initialize decoder" }
val bitmap = decoder.decode(rgb565 = options.allowRgb565) val bitmap = decoder.decode()
decoder.recycle() decoder.recycle()
check(bitmap != null) { "Failed to decode image" } check(bitmap != null) { "Failed to decode image" }

View File

@ -39,11 +39,11 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.storage.extension import tachiyomi.core.common.storage.extension
import tachiyomi.core.storage.nameWithoutExtension import tachiyomi.core.common.storage.nameWithoutExtension
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
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

View File

@ -14,10 +14,10 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.storage.extension import tachiyomi.core.common.storage.extension
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.download.service.DownloadPreferences

View File

@ -14,7 +14,7 @@ import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.cancelNotification import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notify import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.regex.Pattern import java.util.regex.Pattern

View File

@ -5,9 +5,9 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.storage.displayablePath import tachiyomi.core.common.storage.displayablePath
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
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.storage.service.StorageManager import tachiyomi.domain.storage.service.StorageManager

View File

@ -40,15 +40,15 @@ import kotlinx.coroutines.supervisorScope
import logcat.LogPriority import logcat.LogPriority
import nl.adaptivity.xmlutil.serialization.XML import nl.adaptivity.xmlutil.serialization.XML
import okhttp3.Response import okhttp3.Response
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.storage.extension
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchNow
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.core.common.util.system.logcat
import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE
import tachiyomi.core.metadata.comicinfo.ComicInfo import tachiyomi.core.metadata.comicinfo.ComicInfo
import tachiyomi.core.storage.extension
import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.lang.launchNow
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.ImageUtil
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.download.service.DownloadPreferences

View File

@ -39,10 +39,10 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.preference.getAndSet import tachiyomi.core.common.preference.getAndSet
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.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
@ -384,7 +384,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private fun writeErrorFile(errors: List<Pair<Manga, String?>>): File { private fun writeErrorFile(errors: List<Pair<Manga, String?>>): File {
try { try {
if (errors.isNotEmpty()) { if (errors.isNotEmpty()) {
val file = context.createFileInCacheDir("tachiyomi_update_errors.txt") val file = context.createFileInCacheDir("mihon_update_errors.txt")
file.bufferedWriter().use { out -> file.bufferedWriter().use { out ->
out.write(context.stringResource(MR.strings.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n") out.write(context.stringResource(MR.strings.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n")
// Error file format: // Error file format:

View File

@ -26,10 +26,10 @@ import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.getBitmapOrNull import eu.kanade.tachiyomi.util.system.getBitmapOrNull
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notify import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.Constants import tachiyomi.core.common.Constants
import tachiyomi.core.i18n.pluralStringResource import tachiyomi.core.common.i18n.pluralStringResource
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.util.lang.launchUI import tachiyomi.core.common.util.lang.launchUI
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.library.model.LibraryManga import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga

View File

@ -27,8 +27,8 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
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.library.model.LibraryManga import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.interactor.GetLibraryManga import tachiyomi.domain.manga.interactor.GetLibraryManga
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga

View File

@ -7,7 +7,7 @@ import android.net.Uri
import androidx.core.net.toUri import androidx.core.net.toUri
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import tachiyomi.core.Constants import tachiyomi.core.common.Constants
/** /**
* Class that manages [PendingIntent] of activity's * Class that manages [PendingIntent] of activity's

View File

@ -18,8 +18,8 @@ import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import tachiyomi.core.Constants import tachiyomi.core.common.Constants
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.domain.chapter.interactor.GetChapter import tachiyomi.domain.chapter.interactor.GetChapter
import tachiyomi.domain.chapter.interactor.UpdateChapter import tachiyomi.domain.chapter.interactor.UpdateChapter
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter

View File

@ -7,7 +7,7 @@ import androidx.core.app.NotificationManagerCompat.IMPORTANCE_HIGH
import androidx.core.app.NotificationManagerCompat.IMPORTANCE_LOW import androidx.core.app.NotificationManagerCompat.IMPORTANCE_LOW
import eu.kanade.tachiyomi.util.system.buildNotificationChannel import eu.kanade.tachiyomi.util.system.buildNotificationChannel
import eu.kanade.tachiyomi.util.system.buildNotificationChannelGroup import eu.kanade.tachiyomi.util.system.buildNotificationChannelGroup
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
/** /**

View File

@ -15,9 +15,9 @@ import eu.kanade.tachiyomi.util.storage.cacheImageDir
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import logcat.LogPriority import logcat.LogPriority
import okio.IOException import okio.IOException
import tachiyomi.core.i18n.stringResource import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@ -79,7 +79,7 @@ class ImageSaver(
MediaStore.Images.Media.RELATIVE_PATH to relativePath, MediaStore.Images.Media.RELATIVE_PATH to relativePath,
MediaStore.Images.Media.DISPLAY_NAME to image.name, MediaStore.Images.Media.DISPLAY_NAME to image.name,
MediaStore.Images.Media.MIME_TYPE to type.mime, MediaStore.Images.Media.MIME_TYPE to type.mime,
MediaStore.Images.Media.DATE_MODIFIED to Instant.now().toEpochMilli(), MediaStore.Images.Media.DATE_MODIFIED to Instant.now().epochSecond,
) )
val picture = findUriOrDefault(relativePath, filename) { val picture = findUriOrDefault(relativePath, filename) {

View File

@ -10,9 +10,9 @@ import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import logcat.LogPriority import logcat.LogPriority
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.track.interactor.InsertTrack import tachiyomi.domain.track.interactor.InsertTrack
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -25,7 +25,7 @@ import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject import kotlinx.serialization.json.putJsonObject
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.time.Instant import java.time.Instant
import java.time.LocalDate import java.time.LocalDate

View File

@ -21,7 +21,7 @@ import okhttp3.CacheControl
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder import java.net.URLEncoder
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets

View File

@ -12,8 +12,8 @@ import okhttp3.Dns
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
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 uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.IOException import java.io.IOException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException

View File

@ -25,7 +25,7 @@ import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder import java.net.URLEncoder
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets

View File

@ -14,8 +14,8 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
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 uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
private const val READLIST_API = "/api/v1/readlists" private const val READLIST_API = "/api/v1/readlists"

View File

@ -28,7 +28,7 @@ import logcat.LogPriority
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.system.logcat import tachiyomi.core.common.util.system.logcat
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import tachiyomi.domain.track.model.Track as DomainTrack import tachiyomi.domain.track.model.Track as DomainTrack

View File

@ -28,7 +28,7 @@ import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.common.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.track.myanimelist package eu.kanade.tachiyomi.data.track.myanimelist
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Interceptor import okhttp3.Interceptor
@ -21,9 +20,8 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
} }
val originalRequest = chain.request() val originalRequest = chain.request()
// Refresh access token if expired if (oauth?.isExpired() == true) {
if (oauth != null && oauth!!.isExpired()) { refreshToken(chain)
setAuth(refreshToken(chain))
} }
if (oauth == null) { if (oauth == null) {
@ -33,30 +31,11 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
// Add the authorization header to the original request // Add the authorization header to the original request
val authRequest = originalRequest.newBuilder() val authRequest = originalRequest.newBuilder()
.addHeader("Authorization", "Bearer ${oauth!!.access_token}") .addHeader("Authorization", "Bearer ${oauth!!.access_token}")
.header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})") // TODO(antsy): Add back custom user agent when they stop blocking us for no apparent reason
// .header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})")
.build() .build()
val response = chain.proceed(authRequest) return chain.proceed(authRequest)
val tokenIsExpired = response.headers["www-authenticate"]
?.contains("The access token expired") ?: false
// Retry the request once with a new token in case it was not already refreshed
// by the is expired check before.
if (response.code == 401 && tokenIsExpired) {
response.close()
val newToken = refreshToken(chain)
setAuth(newToken)
val newRequest = originalRequest.newBuilder()
.addHeader("Authorization", "Bearer ${newToken.access_token}")
.header("User-Agent", "Mihon v${BuildConfig.VERSION_NAME} (${BuildConfig.APPLICATION_ID})")
.build()
return chain.proceed(newRequest)
}
return response
} }
/** /**
@ -68,22 +47,37 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor
myanimelist.saveOAuth(oauth) myanimelist.saveOAuth(oauth)
} }
private fun refreshToken(chain: Interceptor.Chain): OAuth { private fun refreshToken(chain: Interceptor.Chain): OAuth = synchronized(this) {
if (tokenExpired) throw MALTokenExpired()
oauth?.takeUnless { it.isExpired() }?.let { return@synchronized it }
val response = try {
chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!))
} catch (_: Throwable) {
throw MALTokenRefreshFailed()
}
if (response.code == 401) {
myanimelist.setAuthExpired()
throw MALTokenExpired()
}
return runCatching { return runCatching {
val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!)) if (response.isSuccessful) {
if (oauthResponse.code == 401) { with(json) { response.parseAs<OAuth>() }
myanimelist.setAuthExpired()
}
if (oauthResponse.isSuccessful) {
with(json) { oauthResponse.parseAs<OAuth>() }
} else { } else {
oauthResponse.close() response.close()
null null
} }
} }
.getOrNull() .getOrNull()
?: throw MALTokenExpired() ?.also {
this.oauth = it
myanimelist.saveOAuth(it)
}
?: throw MALTokenRefreshFailed()
} }
} }
class MALTokenRefreshFailed : IOException("MAL: Failed to refresh account token")
class MALTokenExpired : IOException("MAL: Login has expired") class MALTokenExpired : IOException("MAL: Login has expired")

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