diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 61ca4b433b..1546dee1dd 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -2,13 +2,12 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"labels": ["Dependencies"],
+ "semanticCommits": "disabled",
"packageRules": [
{
- "groupName": "Compose BOM (Alpha)",
- "matchPackageNames": [
- "dev.chrisbanes.compose:compose-bom"
- ],
- "ignoreUnstable": false
+ "groupName": "GitHub Actions",
+ "matchManagers": ["github-actions"],
+ "pinDigests": true,
}
]
-}
\ No newline at end of file
+}
diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml
index 00d3391362..3d7b2aaff9 100644
--- a/.github/workflows/build_pull_request.yml
+++ b/.github/workflows/build_pull_request.yml
@@ -1,12 +1,18 @@
name: PR build check
on:
pull_request:
- paths-ignore:
- - '**.md'
- - 'i18n/src/commonMain/moko-resources/**/strings-aniyomi.xml'
- - 'i18n/src/commonMain/moko-resources/**/strings.xml'
- - 'i18n/src/commonMain/moko-resources/**/plurals-aniyomi.xml'
- - 'i18n/src/commonMain/moko-resources/**/plurals.xml'
+ paths:
+ - '**'
+ - '!**.md'
+ - '!i18n/src/commonMain/moko-resources/**/strings-aniyomi.xml'
+ - '!i18n/src/commonMain/moko-resources/**/strings.xml'
+ - '!i18n/src/commonMain/moko-resources/**/plurals-aniyomi.xml'
+ - '!i18n/src/commonMain/moko-resources/**/plurals.xml'
+ - 'i18n/src/commonMain/moko-resources/base/strings-aniyomi.xml'
+ - 'i18n/src/commonMain/moko-resources/base/strings.xml'
+ - 'i18n/src/commonMain/moko-resources/base/plurals-aniyomi.xml'
+ - 'i18n/src/commonMain/moko-resources/base/plurals.xml'
+
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -22,33 +28,34 @@ jobs:
steps:
- name: Clone repo
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Validate Gradle Wrapper
- uses: gradle/actions/wrapper-validation@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
+ uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Dependency Review
- uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
+ uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a # v4.4.0
- name: Set up JDK
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
+ uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
with:
java-version: 17
distribution: adopt
+ - name: Set up gradle
+ uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
+
- name: Build app and run unit tests
- uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
- with:
- arguments: detekt assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
+ run: ./gradlew spotlessCheck assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
- name: Upload APK
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: arm64-v8a-${{ github.sha }}
path: app/build/outputs/apk/standard/release/app-standard-arm64-v8a-release-unsigned.apk
- name: Upload mapping
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: mapping-${{ github.sha }}
- path: app/build/outputs/mapping/standardRelease
\ No newline at end of file
+ path: app/build/outputs/mapping/standardRelease
diff --git a/.github/workflows/build_push.yml b/.github/workflows/build_push.yml
index 0412a954f7..729ab2abcd 100644
--- a/.github/workflows/build_push.yml
+++ b/.github/workflows/build_push.yml
@@ -6,8 +6,7 @@ permissions:
on:
push:
branches:
- - master
- - dev
+ - '*'
tags:
- v*
@@ -22,30 +21,31 @@ jobs:
steps:
- name: Clone repo
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Validate Gradle Wrapper
- uses: gradle/actions/wrapper-validation@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
+ uses: gradle/actions/wrapper-validation@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
- name: Set up JDK
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
+ uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
with:
java-version: 17
distribution: adopt
+ - name: Set up gradle
+ uses: gradle/actions/setup-gradle@d156388eb19639ec20ade50009f3d199ce1e2808 # v4.1.0
+
- name: Build app and run unit tests
- uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3.5.0
- with:
- arguments: detekt assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
+ run: ./gradlew spotlessCheck assembleStandardRelease testReleaseUnitTest testStandardReleaseUnitTest
- name: Upload APK
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: arm64-v8a-${{ github.sha }}
path: app/build/outputs/apk/standard/release/app-standard-arm64-v8a-release-unsigned.apk
- name: Upload mapping
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: mapping-${{ github.sha }}
path: app/build/outputs/mapping/standardRelease
@@ -98,7 +98,7 @@ jobs:
- name: Create Release
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'aniyomiorg/aniyomi'
- uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0 # v2.0.6
+ uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8
with:
tag_name: ${{ env.VERSION_TAG }}
name: Aniyomi ${{ env.VERSION_TAG }}
diff --git a/.gitignore b/.gitignore
index 0c5f5664ec..42c569b7a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,16 @@
+# Build files
.gradle
.kotlin
-/local.properties
-/acra.properties
-/.idea/workspace.xml
-.DS_Store
+build
+
+# IDE files
+*.iml
.idea/*
!.idea/icon.png
-*iml
-*.iml
+/captures
-# Built files
-*/build
-/build
-*.apk
-app/**/output.json
+# Configuration files
+local.properties
-# Unnecessary file
-*.swp
\ No newline at end of file
+# macOS specific files
+.DS_Store
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000..41f5679d63
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,66 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is a modified version of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+- `Added` - for new features.
+- `Changed ` - for changes in existing functionality.
+- `Improved` - for enhancement or optimization in existing functionality.
+- `Removed` - for now removed features.
+- `Fixed` - for any bug fixes.
+- `Other` - for technical stuff.
+
+## [Unreleased]
+### Added
+
+- feat(external-players): add mpvKt ([@Secozzi](https://github.com/Secozzi)) ([#1674](https://github.com/aniyomiorg/aniyomi/pull/1674))
+- feat(player): video filters ([@abdallahmehiz](https://github.com/abdallahmehiz)) ([#1698](https://github.com/aniyomiorg/aniyomi/pull/1698))
+- feat(player): Add better auto sub select ([@Secozzi](https://github.com/Secozzi)) ([#1706](https://github.com/aniyomiorg/aniyomi/pull/1706))
+- feat(downloader): Copy the file location when using ext downloader ([@quickdesh](https://github.com/quickdesh)) ([#1758](https://github.com/aniyomiorg/aniyomi/pull/1758))
+
+### Improved
+
+- feat(entry): show "Now" instead of "0 minutes ago" ([@Secozzi](https://github.com/Secozzi)) ([#1715](https://github.com/aniyomiorg/aniyomi/pull/1715))
+
+### Fixed
+
+- Fix enhanced tracking for jellyfin ([@Secozzi](https://github.com/Secozzi)) ([#1656](https://github.com/aniyomiorg/aniyomi/pull/1656), [#1658](https://github.com/aniyomiorg/aniyomi/pull/1658))
+- fix(animescreen): Fix airing time not showing ([@Secozzi](https://github.com/Secozzi)) ([#1720](https://github.com/aniyomiorg/aniyomi/pull/1720))
+- fix hidden categories getting reset after delete/reorder ([@cuong-tran](https://github.com/cuong-tran)) ([#1780](https://github.com/aniyomiorg/aniyomi/pull/1780))
+- Fix episode progress not being saved and duplicate tracks ([@perokhe](https://github.com/perokhe)) ([#1784](https://github.com/aniyomiorg/aniyomi/pull/1784), [#1785](https://github.com/aniyomiorg/aniyomi/pull/1785))
+
+### Other
+
+- Merge from mihon until 0.16.5 ([@Secozzi](https://github.com/Secozzi)) ([#1663](https://github.com/aniyomiorg/aniyomi/pull/1663))
+ - Merge until latest mihon commits ([@Secozzi](https://github.com/Secozzi)) ([#1693](https://github.com/aniyomiorg/aniyomi/pull/1693))
+ - Merge until latest mihon commits (v0.17.0) ([@Secozzi](https://github.com/Secozzi)) ([#1804](https://github.com/aniyomiorg/aniyomi/pull/1804))
+
+## [v0.16.4.3] - 2024-07-01
+### Fixed
+
+- Fix extensions disappearing due to errors with the ClassLoader ([@jmir1](https://github.com/jmir1)) ([`959f84a`](https://github.com/aniyomiorg/aniyomi/commit/959f84ab41859f90c458c076d83d363ae086e47f))
+
+## [v0.16.4.2] - 2024-07-01
+### Fixed
+
+- Hotfix to eliminate all proguard issues causing errors and crashes ([@jmir1](https://github.com/jmir1)) ([`a8cd723`](https://github.com/aniyomiorg/aniyomi/commit/a8cd7233dfdf26c98ff86b1871a7ac5774379b5e), [`a7644c2`](https://github.com/aniyomiorg/aniyomi/commit/a7644c268153fc0b9f10c27202591f960c6f6384), [`5045fa1`](https://github.com/aniyomiorg/aniyomi/commit/5045fa18ce5a1faa2130f1a33609e43d8453f078))
+
+## [v0.16.4.1] - 2024-07-01
+### Fixed
+
+- Hotfix release to address errors with extensions ([@jmir1](https://github.com/jmir1)) ([`98d2528`](https://github.com/aniyomiorg/aniyomi/commit/98d252866e17beba7d9a4d094797e23c05ead6c1))
+
+## [v0.16.4.0] - 2024-07-01
+### Fixed
+
+- fix(pip): pip not broadcasting intent in A14+ ([@quickdesh](https://github.com/quickdesh)) ([#1603](https://github.com/aniyomiorg/aniyomi/pull/1603))
+- fix: advanced player settings crash in android ≤ 10 ([@perokhe](https://github.com/perokhe)) ([#1627](https://github.com/aniyomiorg/aniyomi/pull/1627))
+
+### Improved
+
+- feat: hide the skip intro button if the skipped amount == 0 ([@abdallahmehiz](https://github.com/abdallahmehiz)) ([#1598](https://github.com/aniyomiorg/aniyomi/pull/1598))
+
+### Other
+
+- Merge from mihon until mihon 0.16.2 ([@Secozzi](https://github.com/Secozzi)) ([#1578](https://github.com/aniyomiorg/aniyomi/pull/1578))
+ - Merge from mihon until 0.16.4 ([@Secozzi](https://github.com/Secozzi)) ([#1601](https://github.com/aniyomiorg/aniyomi/pull/1601))
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8cca4def05..6a687ebdca 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -24,10 +24,6 @@ Before you start, please note that the ability to use following technologies is
- [Android Studio](https://developer.android.com/studio)
- Emulator or phone with developer options enabled to test changes.
-## Linting
-
-To auto-fix some linting errors, run the `ktlintFormat` Gradle task.
-
## Getting help
- Join [the Discord server](https://discord.gg/F32UjdJZrR) for online help and to ask questions while developing.
@@ -39,16 +35,16 @@ Translations are done externally via Weblate. See [our website](https://aniyomi.
# Forks
-Forks are allowed so long as they abide by [the project's LICENSE](https://github.com/tachiyomiorg/tachiyomi/blob/master/LICENSE).
+Forks are allowed so long as they abide by [the project's LICENSE](https://github.com/aniyomiorg/aniyomi/blob/main/LICENSE).
When creating a fork, remember to:
- To avoid confusion with the main app:
- Change the app name
- Change the app icon
- - Change or disable the [app update checker](https://github.com/aniyomiorg/aniyomi/blob/master/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt)
+ - Change or disable the [app update checker](https://github.com/aniyomiorg/aniyomi/blob/main/app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt)
- To avoid installation conflicts:
- - Change the `applicationId` in [`build.gradle.kts`](https://github.com/aniyomiorg/aniyomi/blob/master/app/build.gradle.kts)
+ - Change the `applicationId` in [`build.gradle.kts`](https://github.com/aniyomiorg/aniyomi/blob/main/app/build.gradle.kts)
- To avoid having your data polluting the main app's analytics and crash report services:
- - If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/aniyomiorg/aniyomi/blob/master/app/src/standard/google-services.json) with your own
- - If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/aniyomiorg/aniyomi/blob/master/app/build.gradle.kts) with your own
+ - If you want to use Firebase analytics, replace [`google-services.json`](https://github.com/aniyomiorg/aniyomi/blob/main/app/src/standard/google-services.json) with your own
+ - If you want to use ACRA crash reporting, replace the `ACRA_URI` endpoint in [`build.gradle.kts`](https://github.com/aniyomiorg/aniyomi/blob/main/app/build.gradle.kts) with your own
diff --git a/README.md b/README.md
index ab36a21f99..bbd46ceca9 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ Discover and watch anime, cartoons, series, and more – easier than ever on you
* Local reading and watching of content.
* A configurable reader with multiple viewers, reading directions and other settings.
* A configurable player built on mpv-android with multiple options and settings.
-* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.io/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), [Simkl](https://simkl.com/), and [Bangumi](https://bgm.tv/) support.
+* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.app/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), [Simkl](https://simkl.com/), and [Bangumi](https://bgm.tv/) support.
* Categories to organize your library.
* Light and dark themes.
* Schedule updating your library for new chapters/episodes.
diff --git a/app/.gitignore b/app/.gitignore
deleted file mode 100644
index 90c0dd56f7..0000000000
--- a/app/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/build
-*iml
-*.iml
\ No newline at end of file
diff --git a/app/.idea/discord.xml b/app/.idea/discord.xml
index d8e9561668..e016cd84e7 100644
--- a/app/.idea/discord.xml
+++ b/app/.idea/discord.xml
@@ -4,4 +4,4 @@
-
\ No newline at end of file
+
diff --git a/app/.idea/gradle.xml b/app/.idea/gradle.xml
index 7c7594018d..ba4483fbd9 100644
--- a/app/.idea/gradle.xml
+++ b/app/.idea/gradle.xml
@@ -15,4 +15,4 @@
-
\ No newline at end of file
+
diff --git a/app/.idea/misc.xml b/app/.idea/misc.xml
index 6dc906734c..3fca0de45e 100644
--- a/app/.idea/misc.xml
+++ b/app/.idea/misc.xml
@@ -1,3 +1,3 @@
-
\ No newline at end of file
+
diff --git a/app/.idea/vcs.xml b/app/.idea/vcs.xml
index 6c0b863585..54e4b961ee 100644
--- a/app/.idea/vcs.xml
+++ b/app/.idea/vcs.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index ce29ee60b7..f2a5719294 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -2,19 +2,18 @@ import mihon.buildlogic.getBuildTime
import mihon.buildlogic.getCommitCount
import mihon.buildlogic.getGitSha
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import java.io.FileInputStream
-import java.util.Properties
plugins {
id("mihon.android.application")
id("mihon.android.application.compose")
- id("com.mikepenz.aboutlibraries.plugin")
id("com.github.zellius.shortcut-helper")
kotlin("plugin.serialization")
+ alias(libs.plugins.aboutLibraries)
}
shortcutHelper.setFilePath("./shortcuts.xml")
+@Suppress("PropertyName")
val SUPPORTED_ABIS = setOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
android {
@@ -23,7 +22,7 @@ android {
defaultConfig {
applicationId = "xyz.jmir.tachiyomi.mi"
- versionCode = 125
+ versionCode = 128
versionName = "0.16.4.3"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
@@ -115,13 +114,16 @@ android {
packaging {
resources.excludes.addAll(
listOf(
+ "kotlin-tooling-metadata.json",
"META-INF/DEPENDENCIES",
"LICENSE.txt",
"META-INF/LICENSE",
- "META-INF/LICENSE.txt",
+ "META-INF/**/LICENSE.txt",
+ "META-INF/*.properties",
+ "META-INF/**/*.properties",
"META-INF/README.md",
"META-INF/NOTICE",
- "META-INF/*.kotlin_module",
+ "META-INF/*.version",
),
)
}
@@ -148,6 +150,7 @@ android {
dependencies {
implementation(projects.i18n)
+ implementation(projects.core.archive)
implementation(projects.core.common)
implementation(projects.coreMetadata)
implementation(projects.sourceApi)
@@ -167,7 +170,6 @@ dependencies {
debugImplementation(compose.ui.tooling)
implementation(compose.ui.tooling.preview)
implementation(compose.ui.util)
- implementation(compose.accompanist.systemuicontroller)
implementation(androidx.interpolator)
@@ -187,6 +189,7 @@ dependencies {
implementation(androidx.appcompat)
implementation(androidx.biometricktx)
implementation(androidx.constraintlayout)
+ implementation(androidx.compose.constraintlayout)
implementation(androidx.corektx)
implementation(androidx.splashscreen)
implementation(androidx.recyclerview)
@@ -247,7 +250,6 @@ dependencies {
implementation(libs.compose.webview)
implementation(libs.compose.grid)
-
// Logging
implementation(libs.logcat)
diff --git a/app/src/debug/res/mipmap/ic_launcher.xml b/app/src/debug/res/mipmap/ic_launcher.xml
index dcbbdf1218..4f4ecc0d2e 100644
--- a/app/src/debug/res/mipmap/ic_launcher.xml
+++ b/app/src/debug/res/mipmap/ic_launcher.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/debug/res/mipmap/ic_launcher_round.xml b/app/src/debug/res/mipmap/ic_launcher_round.xml
index dcbbdf1218..4f4ecc0d2e 100644
--- a/app/src/debug/res/mipmap/ic_launcher_round.xml
+++ b/app/src/debug/res/mipmap/ic_launcher_round.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9458212ceb..64579fd7a4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -193,13 +193,13 @@
+ android:supportsPictureInPicture="true"
+ android:theme="@style/Theme.Tachiyomi">
diff --git a/app/src/main/assets/aniyomi.lua b/app/src/main/assets/aniyomi.lua
new file mode 100644
index 0000000000..4654e2eac1
--- /dev/null
+++ b/app/src/main/assets/aniyomi.lua
@@ -0,0 +1,90 @@
+aniyomi = {}
+-- UI
+function aniyomi.show_text(text)
+ mp.set_property("user-data/aniyomi/show_text", text)
+end
+function aniyomi.hide_ui()
+ mp.set_property("user-data/aniyomi/toggle_ui", "hide")
+end
+function aniyomi.show_ui()
+ mp.set_property("user-data/aniyomi/toggle_ui", "show")
+end
+function aniyomi.toggle_ui()
+ mp.set_property("user-data/aniyomi/toggle_ui", "toggle")
+end
+function aniyomi.show_subtitle_settings()
+ mp.set_property("user-data/aniyomi/show_panel", "subtitle_settings")
+end
+function aniyomi.show_subtitle_delay()
+ mp.set_property("user-data/aniyomi/show_panel", "subtitle_delay")
+end
+function aniyomi.show_audio_delay()
+ mp.set_property("user-data/aniyomi/show_panel", "audio_delay")
+end
+function aniyomi.show_video_filters()
+ mp.set_property("user-data/aniyomi/show_panel", "video_filters")
+end
+function aniyomi.show_software_keyboard()
+ mp.set_property("user-data/aniyomi/software_keyboard", "show")
+end
+function aniyomi.hide_software_keyboard()
+ mp.set_property("user-data/aniyomi/software_keyboard", "hide")
+end
+function aniyomi.toggle_software_keyboard()
+ mp.set_property("user-data/aniyomi/software_keyboard", "toggle")
+end
+-- Custom buttons
+function aniyomi.set_button_title(text)
+ mp.set_property("user-data/aniyomi/set_button_title", text)
+end
+function aniyomi.reset_button_title()
+ mp.set_property("user-data/aniyomi/reset_button_title", "unused")
+end
+function aniyomi.hide_button()
+ mp.set_property("user-data/aniyomi/toggle_button", "hide")
+end
+function aniyomi.show_button()
+ mp.set_property("user-data/aniyomi/toggle_button", "show")
+end
+function aniyomi.toggle_button()
+ mp.set_property("user-data/aniyomi/toggle_button", "toggle")
+end
+-- Controls
+function aniyomi.previous_episode()
+ mp.set_property("user-data/aniyomi/switch_episode", "p")
+end
+function aniyomi.next_episode()
+ mp.set_property("user-data/aniyomi/switch_episode", "n")
+end
+function aniyomi.pause()
+ mp.set_property("user-data/aniyomi/pause", "pause")
+end
+function aniyomi.unpause()
+ mp.set_property("user-data/aniyomi/pause", "unpause")
+end
+function aniyomi.pauseunpause()
+ mp.set_property("user-data/aniyomi/pause", "pauseunpause")
+end
+function aniyomi.seek_by(value)
+ mp.set_property("user-data/aniyomi/seek_by", value)
+end
+function aniyomi.seek_to(value)
+ mp.set_property("user-data/aniyomi/seek_to", value)
+end
+function aniyomi.seek_by_with_text(value, text)
+ mp.set_property("user-data/aniyomi/seek_by_with_text", value .. "|" .. text)
+end
+function aniyomi.seek_to_with_text(value, text)
+ mp.set_property("user-data/aniyomi/seek_to_with_text", value .. "|" .. text)
+end
+function aniyomi.int_picker(title, name_format, start, stop, step, property)
+ mp.set_property("user-data/aniyomi/launch_int_picker", title .. "|" .. name_format .. "|" .. start .. "|" .. stop .. "|" .. step .. "|" .. property)
+end
+-- Legacy
+function aniyomi.left_seek_by(value)
+ aniyomi.seek_by(-value)
+end
+function aniyomi.right_seek_by(value)
+ aniyomi.seek_by(value)
+end
+return aniyomi
diff --git a/app/src/main/java/aniyomi/util/DataSaver.kt b/app/src/main/java/aniyomi/util/DataSaver.kt
index 7aa0860fae..dd8a1fbfbc 100644
--- a/app/src/main/java/aniyomi/util/DataSaver.kt
+++ b/app/src/main/java/aniyomi/util/DataSaver.kt
@@ -112,7 +112,8 @@ private class WsrvNlDataSaver(preferences: SourcePreferences) : DataSaver {
private fun getUrl(imageUrl: String): String {
// Network Request sent to wsrv
- return "https://wsrv.nl/?url=$imageUrl" + if (imageUrl.contains(".webp", true) || imageUrl.contains(
+ return "https://wsrv.nl/?url=$imageUrl" + if (imageUrl.contains(".webp", true) ||
+ imageUrl.contains(
".gif",
true,
)
diff --git a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt
index 8dab8a054c..baf369e393 100644
--- a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt
+++ b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt
@@ -5,7 +5,7 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
fun List.insertSeparators(
- generator: (T?, T?) -> R?,
+ generator: (before: T?, after: T?) -> R?,
): List {
if (isEmpty()) return emptyList()
val newList = mutableListOf()
@@ -19,6 +19,24 @@ fun List.insertSeparators(
return newList
}
+/**
+ * Similar to [eu.kanade.core.util.insertSeparators] but iterates from last to first element
+ */
+fun List.insertSeparatorsReversed(
+ generator: (before: T?, after: T?) -> R?,
+): List {
+ if (isEmpty()) return emptyList()
+ val newList = mutableListOf()
+ for (i in size downTo 0) {
+ val after = getOrNull(i)
+ after?.let(newList::add)
+ val before = getOrNull(i - 1)
+ val separator = generator.invoke(before, after)
+ separator?.let(newList::add)
+ }
+ return newList.asReversed()
+}
+
fun HashSet.addOrRemove(value: E, shouldAdd: Boolean) {
if (shouldAdd) {
add(value)
diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt
index c54db27683..f4bf0b2e6d 100644
--- a/app/src/main/java/eu/kanade/domain/DomainModule.kt
+++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt
@@ -41,6 +41,7 @@ import eu.kanade.domain.track.manga.interactor.AddMangaTracks
import eu.kanade.domain.track.manga.interactor.RefreshMangaTracks
import eu.kanade.domain.track.manga.interactor.SyncChapterProgressWithTrack
import eu.kanade.domain.track.manga.interactor.TrackChapter
+import eu.kanade.tachiyomi.ui.player.utils.TrackSelect
import mihon.data.repository.anime.AnimeExtensionRepoRepositoryImpl
import mihon.data.repository.manga.MangaExtensionRepoRepositoryImpl
import mihon.domain.extensionrepo.anime.interactor.CreateAnimeExtensionRepo
@@ -58,10 +59,13 @@ import mihon.domain.extensionrepo.manga.interactor.ReplaceMangaExtensionRepo
import mihon.domain.extensionrepo.manga.interactor.UpdateMangaExtensionRepo
import mihon.domain.extensionrepo.manga.repository.MangaExtensionRepoRepository
import mihon.domain.extensionrepo.service.ExtensionRepoService
+import mihon.domain.items.chapter.interactor.FilterChaptersForDownload
+import mihon.domain.items.episode.interactor.FilterEpisodesForDownload
import mihon.domain.upcoming.anime.interactor.GetUpcomingAnime
import mihon.domain.upcoming.manga.interactor.GetUpcomingManga
import tachiyomi.data.category.anime.AnimeCategoryRepositoryImpl
import tachiyomi.data.category.manga.MangaCategoryRepositoryImpl
+import tachiyomi.data.custombutton.CustomButtonRepositoryImpl
import tachiyomi.data.entries.anime.AnimeRepositoryImpl
import tachiyomi.data.entries.manga.MangaRepositoryImpl
import tachiyomi.data.history.anime.AnimeHistoryRepositoryImpl
@@ -103,6 +107,13 @@ import tachiyomi.domain.category.manga.interactor.SetMangaDisplayMode
import tachiyomi.domain.category.manga.interactor.SetSortModeForMangaCategory
import tachiyomi.domain.category.manga.interactor.UpdateMangaCategory
import tachiyomi.domain.category.manga.repository.MangaCategoryRepository
+import tachiyomi.domain.custombuttons.interactor.CreateCustomButton
+import tachiyomi.domain.custombuttons.interactor.DeleteCustomButton
+import tachiyomi.domain.custombuttons.interactor.GetCustomButtons
+import tachiyomi.domain.custombuttons.interactor.ReorderCustomButton
+import tachiyomi.domain.custombuttons.interactor.ToggleFavoriteCustomButton
+import tachiyomi.domain.custombuttons.interactor.UpdateCustomButton
+import tachiyomi.domain.custombuttons.repository.CustomButtonRepository
import tachiyomi.domain.entries.anime.interactor.AnimeFetchInterval
import tachiyomi.domain.entries.anime.interactor.GetAnime
import tachiyomi.domain.entries.anime.interactor.GetAnimeByUrlAndSourceId
@@ -284,6 +295,7 @@ class DomainModule : InjektModule {
addFactory { SetSeenStatus(get(), get(), get(), get()) }
addFactory { ShouldUpdateDbEpisode() }
addFactory { SyncEpisodesWithSource(get(), get(), get(), get(), get(), get(), get()) }
+ addFactory { FilterEpisodesForDownload(get(), get(), get()) }
addSingletonFactory { ChapterRepositoryImpl(get()) }
addFactory { GetChapter(get()) }
@@ -294,6 +306,7 @@ class DomainModule : InjektModule {
addFactory { ShouldUpdateDbChapter() }
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) }
addFactory { GetAvailableScanlators(get()) }
+ addFactory { FilterChaptersForDownload(get(), get(), get()) }
addSingletonFactory { AnimeHistoryRepositoryImpl(get()) }
addFactory { GetAnimeHistory(get()) }
@@ -365,5 +378,15 @@ class DomainModule : InjektModule {
addFactory { DeleteMangaExtensionRepo(get()) }
addFactory { ReplaceMangaExtensionRepo(get()) }
addFactory { UpdateMangaExtensionRepo(get(), get()) }
+
+ addSingletonFactory { CustomButtonRepositoryImpl(get()) }
+ addFactory { CreateCustomButton(get()) }
+ addFactory { DeleteCustomButton(get()) }
+ addFactory { GetCustomButtons(get()) }
+ addFactory { UpdateCustomButton(get()) }
+ addFactory { ReorderCustomButton(get()) }
+ addFactory { ToggleFavoriteCustomButton(get()) }
+
+ addFactory { TrackSelect(get(), get()) }
}
}
diff --git a/app/src/main/java/eu/kanade/domain/entries/anime/interactor/SetAnimeViewerFlags.kt b/app/src/main/java/eu/kanade/domain/entries/anime/interactor/SetAnimeViewerFlags.kt
index 2937f867a9..a4edc9f965 100644
--- a/app/src/main/java/eu/kanade/domain/entries/anime/interactor/SetAnimeViewerFlags.kt
+++ b/app/src/main/java/eu/kanade/domain/entries/anime/interactor/SetAnimeViewerFlags.kt
@@ -1,5 +1,6 @@
package eu.kanade.domain.entries.anime.interactor
+import tachiyomi.core.common.util.lang.toLong
import tachiyomi.domain.entries.anime.model.Anime
import tachiyomi.domain.entries.anime.model.AnimeUpdate
import tachiyomi.domain.entries.anime.repository.AnimeRepository
@@ -14,7 +15,10 @@ class SetAnimeViewerFlags(
animeRepository.updateAnime(
AnimeUpdate(
id = id,
- viewerFlags = anime.viewerFlags.setFlag(flag, Anime.ANIME_INTRO_MASK),
+ viewerFlags = anime.viewerFlags
+ .setFlag(flag, Anime.ANIME_INTRO_MASK)
+ // Disable skip intro button if length is set to 0
+ .setFlag((flag == 0L).toLong().addHexZeros(14), Anime.ANIME_INTRO_DISABLE_MASK),
),
)
}
diff --git a/app/src/main/java/eu/kanade/domain/track/anime/interactor/AddAnimeTracks.kt b/app/src/main/java/eu/kanade/domain/track/anime/interactor/AddAnimeTracks.kt
index 91dd332a09..e401de5b74 100644
--- a/app/src/main/java/eu/kanade/domain/track/anime/interactor/AddAnimeTracks.kt
+++ b/app/src/main/java/eu/kanade/domain/track/anime/interactor/AddAnimeTracks.kt
@@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.database.models.anime.AnimeTrack
import eu.kanade.tachiyomi.data.track.AnimeTracker
import eu.kanade.tachiyomi.data.track.EnhancedAnimeTracker
import eu.kanade.tachiyomi.data.track.Tracker
+import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import logcat.LogPriority
import tachiyomi.core.common.util.lang.withIOContext
@@ -15,17 +16,16 @@ import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.entries.anime.model.Anime
import tachiyomi.domain.history.anime.interactor.GetAnimeHistory
import tachiyomi.domain.items.episode.interactor.GetEpisodesByAnimeId
-import tachiyomi.domain.track.anime.interactor.GetAnimeTracks
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.time.ZoneOffset
class AddAnimeTracks(
- private val getTracks: GetAnimeTracks,
private val insertTrack: InsertAnimeTrack,
private val syncChapterProgressWithTrack: SyncEpisodeProgressWithTrack,
private val getEpisodesByAnimeId: GetEpisodesByAnimeId,
+ private val trackerManager: TrackerManager,
) {
// TODO: update all trackers based on common data
@@ -80,7 +80,7 @@ class AddAnimeTracks(
suspend fun bindEnhancedTrackers(anime: Anime, source: AnimeSource) = withNonCancellableContext {
withIOContext {
- getTracks.await(anime.id)
+ trackerManager.loggedInTrackers()
.filterIsInstance()
.filter { it.accept(source) }
.forEach { service ->
@@ -88,11 +88,11 @@ class AddAnimeTracks(
service.match(anime)?.let { track ->
track.anime_id = anime.id
(service as Tracker).animeService.bind(track)
- insertTrack.await(track.toDomainTrack()!!)
+ insertTrack.await(track.toDomainTrack(idRequired = false)!!)
syncChapterProgressWithTrack.await(
anime.id,
- track.toDomainTrack()!!,
+ track.toDomainTrack(idRequired = false)!!,
service.animeService,
)
}
diff --git a/app/src/main/java/eu/kanade/domain/track/anime/interactor/SyncEpisodeProgressWithTrack.kt b/app/src/main/java/eu/kanade/domain/track/anime/interactor/SyncEpisodeProgressWithTrack.kt
index cf2c56aeee..f30832bdb1 100644
--- a/app/src/main/java/eu/kanade/domain/track/anime/interactor/SyncEpisodeProgressWithTrack.kt
+++ b/app/src/main/java/eu/kanade/domain/track/anime/interactor/SyncEpisodeProgressWithTrack.kt
@@ -10,6 +10,7 @@ import tachiyomi.domain.items.episode.interactor.UpdateEpisode
import tachiyomi.domain.items.episode.model.toEpisodeUpdate
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
import tachiyomi.domain.track.anime.model.AnimeTrack
+import kotlin.math.max
class SyncEpisodeProgressWithTrack(
private val updateEpisode: UpdateEpisode,
@@ -36,7 +37,8 @@ class SyncEpisodeProgressWithTrack(
// only take into account continuous watching
val localLastSeen = sortedEpisodes.takeWhile { it.seen }.lastOrNull()?.episodeNumber ?: 0F
- val updatedTrack = remoteTrack.copy(lastEpisodeSeen = localLastSeen.toDouble())
+ val lastSeen = max(remoteTrack.lastEpisodeSeen, localLastSeen.toDouble())
+ val updatedTrack = remoteTrack.copy(lastEpisodeSeen = lastSeen)
try {
service.update(updatedTrack.toDbTrack())
diff --git a/app/src/main/java/eu/kanade/domain/track/manga/interactor/AddMangaTracks.kt b/app/src/main/java/eu/kanade/domain/track/manga/interactor/AddMangaTracks.kt
index fdcd7fba36..aa28f4b70e 100644
--- a/app/src/main/java/eu/kanade/domain/track/manga/interactor/AddMangaTracks.kt
+++ b/app/src/main/java/eu/kanade/domain/track/manga/interactor/AddMangaTracks.kt
@@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.data.database.models.manga.MangaTrack
import eu.kanade.tachiyomi.data.track.EnhancedMangaTracker
import eu.kanade.tachiyomi.data.track.MangaTracker
import eu.kanade.tachiyomi.data.track.Tracker
+import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.source.MangaSource
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import logcat.LogPriority
@@ -15,17 +16,16 @@ import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.entries.manga.model.Manga
import tachiyomi.domain.history.manga.interactor.GetMangaHistory
import tachiyomi.domain.items.chapter.interactor.GetChaptersByMangaId
-import tachiyomi.domain.track.manga.interactor.GetMangaTracks
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.time.ZoneOffset
class AddMangaTracks(
- private val getTracks: GetMangaTracks,
private val insertTrack: InsertMangaTrack,
private val syncChapterProgressWithTrack: SyncChapterProgressWithTrack,
private val getChaptersByMangaId: GetChaptersByMangaId,
+ private val trackerManager: TrackerManager,
) {
// TODO: update all trackers based on common data
@@ -80,7 +80,7 @@ class AddMangaTracks(
suspend fun bindEnhancedTrackers(manga: Manga, source: MangaSource) = withNonCancellableContext {
withIOContext {
- getTracks.await(manga.id)
+ trackerManager.loggedInTrackers()
.filterIsInstance()
.filter { it.accept(source) }
.forEach { service ->
@@ -88,11 +88,11 @@ class AddMangaTracks(
service.match(manga)?.let { track ->
track.manga_id = manga.id
(service as Tracker).mangaService.bind(track)
- insertTrack.await(track.toDomainTrack()!!)
+ insertTrack.await(track.toDomainTrack(idRequired = false)!!)
syncChapterProgressWithTrack.await(
manga.id,
- track.toDomainTrack()!!,
+ track.toDomainTrack(idRequired = false)!!,
service.mangaService,
)
}
diff --git a/app/src/main/java/eu/kanade/domain/track/manga/interactor/SyncChapterProgressWithTrack.kt b/app/src/main/java/eu/kanade/domain/track/manga/interactor/SyncChapterProgressWithTrack.kt
index ab36ce46f0..2ce23160d1 100644
--- a/app/src/main/java/eu/kanade/domain/track/manga/interactor/SyncChapterProgressWithTrack.kt
+++ b/app/src/main/java/eu/kanade/domain/track/manga/interactor/SyncChapterProgressWithTrack.kt
@@ -10,6 +10,7 @@ import tachiyomi.domain.items.chapter.interactor.UpdateChapter
import tachiyomi.domain.items.chapter.model.toChapterUpdate
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
import tachiyomi.domain.track.manga.model.MangaTrack
+import kotlin.math.max
class SyncChapterProgressWithTrack(
private val updateChapter: UpdateChapter,
@@ -36,7 +37,8 @@ class SyncChapterProgressWithTrack(
// only take into account continuous reading
val localLastRead = sortedChapters.takeWhile { it.read }.lastOrNull()?.chapterNumber ?: 0F
- val updatedTrack = remoteTrack.copy(lastChapterRead = localLastRead.toDouble())
+ val lastRead = max(remoteTrack.lastChapterRead, localLastRead.toDouble())
+ val updatedTrack = remoteTrack.copy(lastChapterRead = lastRead)
try {
tracker.update(updatedTrack.toDbTrack())
diff --git a/app/src/main/java/eu/kanade/domain/track/model/AutoTrackState.kt b/app/src/main/java/eu/kanade/domain/track/model/AutoTrackState.kt
new file mode 100644
index 0000000000..987999b749
--- /dev/null
+++ b/app/src/main/java/eu/kanade/domain/track/model/AutoTrackState.kt
@@ -0,0 +1,10 @@
+package eu.kanade.domain.track.model
+
+import dev.icerock.moko.resources.StringResource
+import tachiyomi.i18n.MR
+
+enum class AutoTrackState(val titleRes: StringResource) {
+ ALWAYS(MR.strings.lock_always),
+ ASK(MR.strings.default_category_summary),
+ NEVER(MR.strings.lock_never),
+}
diff --git a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt
index 81b3f01d1d..f6222d1dc6 100644
--- a/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt
+++ b/app/src/main/java/eu/kanade/domain/track/service/TrackPreferences.kt
@@ -1,9 +1,11 @@
package eu.kanade.domain.track.service
+import eu.kanade.domain.track.model.AutoTrackState
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.anilist.Anilist
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
+import tachiyomi.core.common.preference.getEnum
class TrackPreferences(
private val preferenceStore: PreferenceStore,
@@ -42,4 +44,9 @@ class TrackPreferences(
"show_next_episode_airing_time",
true,
)
+
+ fun autoUpdateTrackOnMarkRead() = preferenceStore.getEnum(
+ "pref_auto_update_manga_on_mark_read",
+ AutoTrackState.ALWAYS,
+ )
}
diff --git a/app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt b/app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt
index e54886b456..7496cf6e88 100644
--- a/app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt
+++ b/app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt
@@ -21,7 +21,11 @@ class UiPreferences(
fun appTheme() = preferenceStore.getEnum(
"pref_app_theme",
- if (DeviceUtil.isDynamicColorAvailable) { AppTheme.MONET } else { AppTheme.DEFAULT },
+ if (DeviceUtil.isDynamicColorAvailable) {
+ AppTheme.MONET
+ } else {
+ AppTheme.DEFAULT
+ },
)
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
diff --git a/app/src/main/java/eu/kanade/domain/ui/model/NavStyle.kt b/app/src/main/java/eu/kanade/domain/ui/model/NavStyle.kt
index ef4558922c..6ba53e65a7 100644
--- a/app/src/main/java/eu/kanade/domain/ui/model/NavStyle.kt
+++ b/app/src/main/java/eu/kanade/domain/ui/model/NavStyle.kt
@@ -25,7 +25,7 @@ enum class NavStyle(
MOVE_MANGA_TO_MORE(titleRes = MR.strings.pref_bottom_nav_no_manga, moreTab = MangaLibraryTab),
MOVE_UPDATES_TO_MORE(titleRes = MR.strings.pref_bottom_nav_no_updates, moreTab = UpdatesTab),
MOVE_HISTORY_TO_MORE(titleRes = MR.strings.pref_bottom_nav_no_history, moreTab = HistoriesTab),
- MOVE_BROWSE_TO_MORE(titleRes = MR.strings.pref_bottom_nav_no_browse, moreTab = BrowseTab()),
+ MOVE_BROWSE_TO_MORE(titleRes = MR.strings.pref_bottom_nav_no_browse, moreTab = BrowseTab),
;
val moreIcon: ImageVector
@@ -44,7 +44,7 @@ enum class NavStyle(
MangaLibraryTab,
UpdatesTab,
HistoriesTab,
- BrowseTab(),
+ BrowseTab,
MoreTab,
).apply { remove(this@NavStyle.moreTab) }
}
diff --git a/app/src/main/java/eu/kanade/domain/ui/model/StartScreen.kt b/app/src/main/java/eu/kanade/domain/ui/model/StartScreen.kt
index a41ead2bc1..c5e16fddad 100644
--- a/app/src/main/java/eu/kanade/domain/ui/model/StartScreen.kt
+++ b/app/src/main/java/eu/kanade/domain/ui/model/StartScreen.kt
@@ -14,5 +14,5 @@ enum class StartScreen(val titleRes: StringResource, val tab: Tab) {
MANGA(MR.strings.manga, MangaLibraryTab),
UPDATES(MR.strings.label_recent_updates, UpdatesTab),
HISTORY(MR.strings.label_recent_manga, HistoriesTab),
- BROWSE(MR.strings.browse, BrowseTab()),
+ BROWSE(MR.strings.browse, BrowseTab),
}
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionDetailsScreen.kt
index 0ed3010298..b8d9f181d2 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionDetailsScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionDetailsScreen.kt
@@ -241,7 +241,7 @@ private fun DetailsHeader(
Update available: ${extension.hasUpdate}
Obsolete: ${extension.isObsolete}
Shared: ${extension.isShared}
- Repository: ${extension.repoUrl}
+ Repository: ${extension.repoUrl}
""".trimIndent(),
)
}
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt
index bc0ae578dd..68c61d0870 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeExtensionsScreen.kt
@@ -47,6 +47,7 @@ import eu.kanade.presentation.browse.manga.ExtensionTrustDialog
import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.entries.components.DotSeparatorNoSpaceText
import eu.kanade.presentation.more.settings.screen.browse.AnimeExtensionReposScreen
+import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
@@ -185,14 +186,14 @@ private fun AnimeExtensionContent(
}
ExtensionHeader(
textRes = header.textRes,
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
action = action,
)
}
is AnimeExtensionUiModel.Header.Text -> {
ExtensionHeader(
text = header.text,
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
)
}
}
@@ -211,12 +212,14 @@ private fun AnimeExtensionContent(
) { item ->
AnimeExtensionItem(
item = item,
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
onClickItem = {
when (it) {
is AnimeExtension.Available -> onInstallExtension(it)
is AnimeExtension.Installed -> onOpenExtension(it)
- is AnimeExtension.Untrusted -> { trustState = it }
+ is AnimeExtension.Untrusted -> {
+ trustState = it
+ }
}
},
onLongClickItem = onLongClickItem,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesFilterScreen.kt
index 8aafc1a4e2..538979c401 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesFilterScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesFilterScreen.kt
@@ -10,6 +10,7 @@ import androidx.compose.ui.platform.LocalContext
import eu.kanade.presentation.browse.anime.components.BaseAnimeSourceItem
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
+import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.tachiyomi.ui.browse.anime.source.AnimeSourcesFilterScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.domain.source.anime.model.AnimeSource
@@ -68,7 +69,7 @@ private fun AnimeSourcesFilterContent(
contentType = "source-filter-header",
) {
AnimeSourcesFilterHeader(
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
language = language,
enabled = enabled,
onClickItem = onClickLanguage,
@@ -81,7 +82,7 @@ private fun AnimeSourcesFilterContent(
contentType = { "source-filter-item" },
) { source ->
AnimeSourcesFilterItem(
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
source = source,
isEnabled = "${source.id}" !in state.disabledSources,
onClickItem = onClickSource,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesScreen.kt
index d2ce30aa4f..4ce0bd5558 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/AnimeSourcesScreen.kt
@@ -28,7 +28,7 @@ import tachiyomi.domain.source.anime.model.AnimeSource
import tachiyomi.domain.source.anime.model.Pin
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
-import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
+import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
import tachiyomi.presentation.core.i18n.stringResource
@@ -151,7 +151,7 @@ private fun AnimeSourcePinButton(
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onBackground.copy(
- alpha = SecondaryItemAlpha,
+ alpha = SECONDARY_ALPHA,
)
}
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/BrowseAnimeSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/BrowseAnimeSourceScreen.kt
index 5e66204b66..1273d0f77a 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/BrowseAnimeSourceScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/BrowseAnimeSourceScreen.kt
@@ -41,6 +41,8 @@ fun BrowseAnimeSourceContent(
source: AnimeSource?,
animeList: LazyPagingItems>,
columns: GridCells,
+ entries: Int = 0,
+ topBarHeight: Int = 0,
displayMode: LibraryDisplayMode,
snackbarHostState: SnackbarHostState,
contentPadding: PaddingValues,
@@ -129,6 +131,8 @@ fun BrowseAnimeSourceContent(
LibraryDisplayMode.List -> {
BrowseAnimeSourceList(
animeList = animeList,
+ entries = entries,
+ topBarHeight = topBarHeight,
contentPadding = contentPadding,
onAnimeClick = onAnimeClick,
onAnimeLongClick = onAnimeLongClick,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeIcons.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeIcons.kt
index 4304ba0af8..62e903a622 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeIcons.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeIcons.kt
@@ -130,7 +130,7 @@ private fun AnimeExtension.getIcon(density: Int = DisplayMetrics.DENSITY_DEFAULT
val appInfo = AnimeExtensionLoader.getAnimeExtensionPackageInfoFromPkgName(
context,
pkgName,
- )!!.applicationInfo
+ )!!.applicationInfo!!
val appResources = context.packageManager.getResourcesForApplication(appInfo)
Result.Success(
appResources.getDrawableForDensity(appInfo.icon, density, null)!!
diff --git a/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeSourceList.kt b/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeSourceList.kt
index c9a215f187..011fd6047e 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeSourceList.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/anime/components/BrowseAnimeSourceList.kt
@@ -5,6 +5,11 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
@@ -20,12 +25,19 @@ import tachiyomi.presentation.core.util.plus
@Composable
fun BrowseAnimeSourceList(
animeList: LazyPagingItems>,
+ entries: Int,
+ topBarHeight: Int,
contentPadding: PaddingValues,
onAnimeClick: (Anime) -> Unit,
onAnimeLongClick: (Anime) -> Unit,
) {
+ var containerHeight by remember { mutableIntStateOf(0) }
LazyColumn(
contentPadding = contentPadding + PaddingValues(vertical = 8.dp),
+ modifier = Modifier
+ .onGloballyPositioned { layoutCoordinates ->
+ containerHeight = layoutCoordinates.size.height - topBarHeight
+ },
) {
item {
if (animeList.loadState.prepend is LoadState.Loading) {
@@ -39,6 +51,8 @@ fun BrowseAnimeSourceList(
anime = anime,
onClick = { onAnimeClick(anime) },
onLongClick = { onAnimeLongClick(anime) },
+ entries = entries,
+ containerHeight = containerHeight,
)
}
@@ -55,6 +69,8 @@ private fun BrowseAnimeSourceListItem(
anime: Anime,
onClick: () -> Unit = {},
onLongClick: () -> Unit = onClick,
+ entries: Int,
+ containerHeight: Int,
) {
EntryListItem(
title = anime.title,
@@ -71,5 +87,7 @@ private fun BrowseAnimeSourceListItem(
},
onLongClick = onLongClick,
onClick = onClick,
+ entries = entries,
+ containerHeight = containerHeight,
)
}
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/BrowseMangaSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/BrowseMangaSourceScreen.kt
index 694f926612..030351287f 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/BrowseMangaSourceScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/BrowseMangaSourceScreen.kt
@@ -41,6 +41,8 @@ fun BrowseSourceContent(
source: MangaSource?,
mangaList: LazyPagingItems>,
columns: GridCells,
+ entries: Int = 0,
+ topBarHeight: Int = 0,
displayMode: LibraryDisplayMode,
snackbarHostState: SnackbarHostState,
contentPadding: PaddingValues,
@@ -129,6 +131,8 @@ fun BrowseSourceContent(
LibraryDisplayMode.List -> {
BrowseMangaSourceList(
mangaList = mangaList,
+ entries = entries,
+ topBarHeight = topBarHeight,
contentPadding = contentPadding,
onMangaClick = onMangaClick,
onMangaLongClick = onMangaLongClick,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionDetailsScreen.kt
index 92423923c6..d0c3557612 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionDetailsScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionDetailsScreen.kt
@@ -242,7 +242,7 @@ private fun DetailsHeader(
Update available: ${extension.hasUpdate}
Obsolete: ${extension.isObsolete}
Shared: ${extension.isShared}
- Repository: ${extension.repoUrl}
+ Repository: ${extension.repoUrl}
""".trimIndent(),
)
}
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt
index f3862c14c6..55584f526f 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaExtensionsScreen.kt
@@ -48,6 +48,7 @@ import eu.kanade.presentation.browse.manga.components.MangaExtensionIcon
import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.entries.components.DotSeparatorNoSpaceText
import eu.kanade.presentation.more.settings.screen.browse.MangaExtensionReposScreen
+import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.presentation.util.rememberRequestPackageInstallsPermissionState
import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
@@ -187,14 +188,14 @@ private fun ExtensionContent(
}
ExtensionHeader(
textRes = header.textRes,
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
action = action,
)
}
is MangaExtensionUiModel.Header.Text -> {
ExtensionHeader(
text = header.text,
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
)
}
}
@@ -212,13 +213,15 @@ private fun ExtensionContent(
},
) { item ->
ExtensionItem(
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
item = item,
onClickItem = {
when (it) {
is MangaExtension.Available -> onInstallExtension(it)
is MangaExtension.Installed -> onOpenExtension(it)
- is MangaExtension.Untrusted -> { trustState = it }
+ is MangaExtension.Untrusted -> {
+ trustState = it
+ }
}
},
onLongClickItem = onLongClickItem,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesFilterScreen.kt
index b61f9c4106..4d860ed2b4 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesFilterScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesFilterScreen.kt
@@ -10,6 +10,7 @@ import androidx.compose.ui.platform.LocalContext
import eu.kanade.presentation.browse.manga.components.BaseMangaSourceItem
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
+import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.tachiyomi.ui.browse.manga.source.MangaSourcesFilterScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.domain.source.manga.model.Source
@@ -68,7 +69,7 @@ private fun SourcesFilterContent(
contentType = "source-filter-header",
) {
SourcesFilterHeader(
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
language = language,
enabled = enabled,
onClickItem = onClickLanguage,
@@ -81,7 +82,7 @@ private fun SourcesFilterContent(
contentType = { "source-filter-item" },
) { source ->
SourcesFilterItem(
- modifier = Modifier.animateItem(),
+ modifier = Modifier.animateItemFastScroll(),
source = source,
enabled = "${source.id}" !in state.disabledSources,
onClickItem = onClickSource,
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesScreen.kt
index 8640bf6bc8..978fcf2441 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/MangaSourcesScreen.kt
@@ -28,7 +28,7 @@ import tachiyomi.domain.source.manga.model.Pin
import tachiyomi.domain.source.manga.model.Source
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
-import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
+import tachiyomi.presentation.core.components.material.SECONDARY_ALPHA
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
import tachiyomi.presentation.core.i18n.stringResource
@@ -151,7 +151,7 @@ private fun SourcePinButton(
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onBackground.copy(
- alpha = SecondaryItemAlpha,
+ alpha = SECONDARY_ALPHA,
)
}
val description = if (isPinned) MR.strings.action_unpin else MR.strings.action_pin
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaIcons.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaIcons.kt
index 8dfc933f46..954a4d430d 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaIcons.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaIcons.kt
@@ -130,7 +130,7 @@ private fun MangaExtension.getIcon(density: Int = DisplayMetrics.DENSITY_DEFAULT
val appInfo = MangaExtensionLoader.getMangaExtensionPackageInfoFromPkgName(
context,
pkgName,
- )!!.applicationInfo
+ )!!.applicationInfo!!
val appResources = context.packageManager.getResourcesForApplication(appInfo)
Result.Success(
appResources.getDrawableForDensity(appInfo.icon, density, null)!!
diff --git a/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaSourceList.kt b/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaSourceList.kt
index 0cbaa55824..6d75143e3b 100644
--- a/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaSourceList.kt
+++ b/app/src/main/java/eu/kanade/presentation/browse/manga/components/BrowseMangaSourceList.kt
@@ -5,6 +5,11 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
@@ -19,12 +24,19 @@ import tachiyomi.presentation.core.util.plus
@Composable
fun BrowseMangaSourceList(
mangaList: LazyPagingItems>,
+ entries: Int,
+ topBarHeight: Int,
contentPadding: PaddingValues,
onMangaClick: (Manga) -> Unit,
onMangaLongClick: (Manga) -> Unit,
) {
+ var containerHeight by remember { mutableIntStateOf(0) }
LazyColumn(
contentPadding = contentPadding + PaddingValues(vertical = 8.dp),
+ modifier = Modifier
+ .onGloballyPositioned { layoutCoordinates ->
+ containerHeight = layoutCoordinates.size.height - topBarHeight
+ },
) {
item {
if (mangaList.loadState.prepend is LoadState.Loading) {
@@ -38,6 +50,8 @@ fun BrowseMangaSourceList(
manga = manga,
onClick = { onMangaClick(manga) },
onLongClick = { onMangaLongClick(manga) },
+ entries = entries,
+ containerHeight = containerHeight,
)
}
@@ -54,6 +68,8 @@ private fun BrowseMangaSourceListItem(
manga: Manga,
onClick: () -> Unit = {},
onLongClick: () -> Unit = onClick,
+ entries: Int,
+ containerHeight: Int,
) {
EntryListItem(
title = manga.title,
@@ -70,5 +86,7 @@ private fun BrowseMangaSourceListItem(
},
onLongClick = onLongClick,
onClick = onClick,
+ entries = entries,
+ containerHeight = containerHeight,
)
}
diff --git a/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt b/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt
index 30ae43a43d..15d05a6ec6 100644
--- a/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt
+++ b/app/src/main/java/eu/kanade/presentation/components/AdaptiveSheet.kt
@@ -9,12 +9,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
-import androidx.core.view.WindowInsetsControllerCompat
import cafe.adriel.voyager.core.annotation.InternalVoyagerApi
import cafe.adriel.voyager.core.lifecycle.DisposableEffectIgnoringConfiguration
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator
-import com.google.accompanist.systemuicontroller.rememberSystemUiController
import eu.kanade.presentation.util.ScreenTransition
import eu.kanade.presentation.util.isTabletUi
import tachiyomi.presentation.core.components.AdaptiveSheet as AdaptiveSheetImpl
@@ -71,7 +69,6 @@ fun NavigatorAdaptiveSheet(
fun AdaptiveSheet(
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
- hideSystemBars: Boolean = false,
enableSwipeDismiss: Boolean = true,
content: @Composable () -> Unit,
) {
@@ -81,12 +78,6 @@ fun AdaptiveSheet(
onDismissRequest = onDismissRequest,
properties = dialogProperties,
) {
- if (hideSystemBars) {
- rememberSystemUiController().apply {
- isSystemBarsVisible = false
- systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
- }
- }
AdaptiveSheetImpl(
modifier = modifier,
isTabletUi = isTabletUi,
diff --git a/app/src/main/java/eu/kanade/presentation/components/DateText.kt b/app/src/main/java/eu/kanade/presentation/components/DateText.kt
index 17f95bbd89..030708f3c3 100644
--- a/app/src/main/java/eu/kanade/presentation/components/DateText.kt
+++ b/app/src/main/java/eu/kanade/presentation/components/DateText.kt
@@ -27,6 +27,7 @@ fun relativeDateText(
)
}
+// For use in chapter/episode release time
@Composable
fun relativeDateTimeText(
dateEpochMillis: Long,
@@ -58,6 +59,7 @@ fun relativeDateText(
?: stringResource(MR.strings.not_applicable)
}
+// For use in chapter/episode release time
@Composable
fun relativeDateTimeText(
localDateTime: LocalDateTime?,
diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt
index b9f7f0e204..b86057a67a 100644
--- a/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt
+++ b/app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt
@@ -47,12 +47,10 @@ fun TabbedDialog(
tabOverflowMenuContent: (@Composable ColumnScope.(() -> Unit) -> Unit)? = null,
onOverflowMenuClicked: (() -> Unit)? = null,
overflowIcon: ImageVector? = null,
- hideSystemBars: Boolean = false,
pagerState: PagerState = rememberPagerState { tabTitles.size },
content: @Composable (Int) -> Unit,
) {
AdaptiveSheet(
- hideSystemBars = hideSystemBars,
modifier = modifier,
onDismissRequest = onDismissRequest,
) {
diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt
index ace5dbda7f..36113687cd 100644
--- a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
+import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
@@ -15,7 +16,6 @@ import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Tab
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
@@ -36,7 +36,7 @@ fun TabbedScreen(
titleRes: StringResource?,
tabs: ImmutableList,
modifier: Modifier = Modifier,
- startIndex: Int? = null,
+ state: PagerState = rememberPagerState { tabs.size },
mangaSearchQuery: String? = null,
onChangeMangaSearchQuery: (String?) -> Unit = {},
scrollable: Boolean = false,
@@ -45,15 +45,8 @@ fun TabbedScreen(
) {
val scope = rememberCoroutineScope()
- val state = rememberPagerState { tabs.size }
val snackbarHostState = remember { SnackbarHostState() }
- LaunchedEffect(startIndex) {
- if (startIndex != null) {
- state.scrollToPage(startIndex)
- }
- }
-
Scaffold(
topBar = {
if (titleRes != null) {
diff --git a/app/src/main/java/eu/kanade/presentation/entries/anime/AnimeScreen.kt b/app/src/main/java/eu/kanade/presentation/entries/anime/AnimeScreen.kt
index 48f6929d44..4e913aa7d0 100644
--- a/app/src/main/java/eu/kanade/presentation/entries/anime/AnimeScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/entries/anime/AnimeScreen.kt
@@ -427,13 +427,9 @@ private fun AnimeScreenSmallImpl(
AnimeInfoBox(
isTabletUi = false,
appBarPadding = topPadding,
- title = state.anime.title,
- author = state.anime.author,
- artist = state.anime.artist,
+ anime = state.anime,
sourceName = remember { state.source.getNameForAnimeInfo() },
isStubSource = remember { state.source is StubAnimeSource },
- coverDataProvider = { state.anime },
- status = state.anime.status,
onCoverClick = onCoverClicked,
doSearch = onSearch,
)
@@ -499,7 +495,8 @@ private fun AnimeScreenSmallImpl(
timer -= 1000L
}
}
- if (timer > 0L && showNextEpisodeAirTime &&
+ if (timer > 0L &&
+ showNextEpisodeAirTime &&
state.anime.status.toInt() != SAnime.COMPLETED
) {
NextEpisodeAiringListItem(
@@ -708,13 +705,9 @@ fun AnimeScreenLargeImpl(
AnimeInfoBox(
isTabletUi = true,
appBarPadding = contentPadding.calculateTopPadding(),
- title = state.anime.title,
- author = state.anime.author,
- artist = state.anime.artist,
+ anime = state.anime,
sourceName = remember { state.source.getNameForAnimeInfo() },
isStubSource = remember { state.source is StubAnimeSource },
- coverDataProvider = { state.anime },
- status = state.anime.status,
onCoverClick = onCoverClicked,
doSearch = onSearch,
)
@@ -781,7 +774,8 @@ fun AnimeScreenLargeImpl(
timer -= 1000L
}
}
- if (timer > 0L && showNextEpisodeAirTime &&
+ if (timer > 0L &&
+ showNextEpisodeAirTime &&
state.anime.status.toInt() != SAnime.COMPLETED
) {
NextEpisodeAiringListItem(
diff --git a/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt b/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt
index f671671c5b..edc53f62cf 100644
--- a/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt
+++ b/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt
@@ -6,11 +6,13 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
@@ -29,13 +31,9 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
@@ -46,19 +44,31 @@ import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
-import cafe.adriel.voyager.core.model.StateScreenModel
+import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import cafe.adriel.voyager.core.screen.Screen
import eu.kanade.presentation.components.TabbedDialogPaddings
+import eu.kanade.tachiyomi.animesource.AnimeSource
+import eu.kanade.tachiyomi.animesource.model.Hoster
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager
import eu.kanade.tachiyomi.ui.main.MainActivity
+import eu.kanade.tachiyomi.ui.player.controls.components.sheets.HosterState
+import eu.kanade.tachiyomi.ui.player.controls.components.sheets.QualitySheetHosterContent
+import eu.kanade.tachiyomi.ui.player.controls.components.sheets.QualitySheetVideoContent
+import eu.kanade.tachiyomi.ui.player.controls.components.sheets.getChangedAt
import eu.kanade.tachiyomi.ui.player.loader.EpisodeLoader
+import eu.kanade.tachiyomi.ui.player.loader.HosterLoader
import eu.kanade.tachiyomi.util.system.toast
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import logcat.LogPriority
+import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchUI
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.logcat
@@ -73,6 +83,8 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
+import java.util.concurrent.atomic.AtomicBoolean
+import kotlin.coroutines.cancellation.CancellationException
class EpisodeOptionsDialogScreen(
private val useExternalDownloader: Boolean,
@@ -91,14 +103,29 @@ class EpisodeOptionsDialogScreen(
sourceId = sourceId,
)
}
- val state by sm.state.collectAsState()
+
+ val episode by sm.episode.collectAsState()
+ val anime by sm.anime.collectAsState()
+ val hosterState by sm.hosterState.collectAsState()
+ val hosterExpandedList by sm.hosterExpandedList.collectAsState()
+ val selectedHosterVideoIndex by sm.selectedHosterVideoIndex.collectAsState()
+ val currentVideo by sm.currentVideo.collectAsState()
+ val showAllQualities by sm.showAllQualities.collectAsState()
EpisodeOptionsDialog(
useExternalDownloader = useExternalDownloader,
episodeTitle = episodeTitle,
- episode = state.episode,
- anime = state.anime,
- resultList = state.resultList,
+ episode = episode,
+ anime = anime,
+ showAllQualities = showAllQualities,
+ resultList = hosterState,
+ expandedList = hosterExpandedList,
+ currentVideo = currentVideo,
+ selectedHosterVideoIndex = selectedHosterVideoIndex,
+ onShowAllQualities = sm::onShowAllQualities,
+ onClickHoster = sm::onClickHoster,
+ onClickVideo = sm::onClickVideo,
+ getHosterList = sm::getHosterList,
)
}
@@ -111,38 +138,256 @@ class EpisodeOptionsDialogScreenModel(
episodeId: Long,
animeId: Long,
sourceId: Long,
-) : StateScreenModel(State()) {
+) : ScreenModel {
private val sourceManager: AnimeSourceManager = Injekt.get()
+ private val _hosterState = MutableStateFlow>?>(null)
+ val hosterState = _hosterState.asStateFlow()
+ private val _hosterExpandedList = MutableStateFlow>(emptyList())
+ val hosterExpandedList = _hosterExpandedList.asStateFlow()
+ private val _selectedHosterVideoIndex = MutableStateFlow(Pair(-1, -1))
+ val selectedHosterVideoIndex = _selectedHosterVideoIndex.asStateFlow()
+ private val _currentVideo = MutableStateFlow