1
0
mirror of https://github.com/mihonapp/mihon.git synced 2025-08-02 21:01:32 +02:00

Compare commits

...

48 Commits

Author SHA1 Message Date
AntsyLich
a4f5dfab1a Release v0.16.4 2024-02-26 22:19:23 +06:00
AntsyLich
085147b15b Fix detekt issue 2024-02-26 22:19:23 +06:00
AntsyLich
085ad8d446 Don't add custom User Agent for MAL
Closes 
2024-02-26 22:08:11 +06:00
AntsyLich
139663acfc Release v0.16.3 2024-01-30 02:31:45 +06:00
AntsyLich
1581b876cf Remove old ISSUE_TEMPLATE.md 2024-01-30 02:31:45 +06:00
AntsyLich
0f4de03d7a Don't throw MALTokenExpired whenever we fail to refresh MAL token
Also cleanup
2024-01-30 02:31:45 +06:00
AntsyLich
ddbe8efbc5 [skip ci] Increase size of the message indicating which apk to download 2024-01-30 02:31:44 +06:00
Weblate (bot)
63146e717b Translations update from Hosted Weblate ()
* 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
AntsyLich
b2d22f86c6 Lint 2024-01-29 23:09:09 +06:00
AwkwardPeak7
79f46b25f6 Fix new extension install not registering in app. ()
* 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
AntsyLich
aa498360db Move :core to :core:common 2024-01-29 15:20:21 +06:00
AntsyLich
f03f998b21 [skip ci] Delete ic_launcher-web.png 2024-01-29 14:31:48 +06:00
AntsyLich
4811cf07cd Address build warning in :i18n
And small cleanup
2024-01-29 14:29:04 +06:00
MajorTanya
b71c793fad Add click-to-copy extension debug info ()
* 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 .

* 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
AntsyLich
47e5421527 Upgrade combose-bom to latest 2024-01-29 13:25:01 +06:00
Theodoro Loureiro mota
5dc6501688 Fix - Scroll crashing ()
Updating compose bom.
2024-01-29 12:56:29 +06:00
Theodoro Loureiro mota
cc09230e26 Adding Detekt in the project ()
* 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
AntsyLich
9c4d2b087f [skip ci] Update issue templates 2024-01-29 02:03:00 +06:00
renovate[bot]
4bcba0503a Update dependency com.android.tools.build:gradle to v8.2.2 ()
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-28 20:39:37 +06:00
Jishnu M
cf33f250cc Change extension update error file name () 2024-01-28 20:32:23 +06:00
Theodoro Loureiro mota
915a967151 Fixing bottom sheet UI bug in non-tablet devices ()
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Setting decorFitsSystemWindows = true to fix ui bug on Android 11
2024-01-28 20:31:59 +06:00
Soitora
9cc0c4e035 Hide display cutout setting if fullscreen is off ()
- 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
AntsyLich
222e111806 Release v0.16.2 2024-01-28 00:28:28 +06:00
Weblate (bot)
8489b0dd8b [skip ci] Translations update from Hosted Weblate ()
* Translated using Weblate (Nepali)

Currently translated at 94.1% (747 of 793 strings)

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

* Translated using Weblate (Italian)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Japanese)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 98.3% (780 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Polish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Turkish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Swedish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (German)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Swedish)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Finnish)

Currently translated at 80.9% (642 of 793 strings)

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

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Nepali)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Arabic)

Currently translated at 100.0% (793 of 793 strings)

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

* Translated using Weblate (Persian)

Currently translated at 82.7% (656 of 793 strings)

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

* Translated using Weblate (Finnish)

Currently translated at 80.9% (642 of 793 strings)

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

* Translated using Weblate (Arabic)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Chuvash)

Currently translated at 88.2% (15 of 17 strings)

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

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (17 of 17 strings)

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

---------

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

* `tracker_id` to Long

* `last_chapter_read` to Double

* `total_chapters` to Long

* `status` to Long
2024-01-27 23:17:09 +06:00
MajorTanya
65bfa083f2 Replace "tachiyomi" with "mihon" in crash log name ()
Closes .
2024-01-26 01:00:23 +06:00
CodeSpoof
b8a9998bbd [skip ci] Remove official extensions check from issue templates ()
* Update report_issue.yml

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

* Update request_feature.yml

No more official extensions
2024-01-25 23:27:23 +06:00
Weblate (bot)
d736bec003 Translations update from Hosted Weblate ()
* Translated using Weblate (Swedish)

Currently translated at 100.0% (17 of 17 strings)

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

* Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (17 of 17 strings)

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

---------

Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Lzmxya <lzmxya@gmail.com>
2024-01-24 19:23:39 +06:00
Secozzi
348b23a9fd Fix refreshing from enhanced tracker ()
fix refreshing from enhanced tracker
2024-01-24 19:16:28 +06:00
Theodoro Loureiro mota
121b2ec829 [skip ci] Removing extensions from config issues () 2024-01-24 19:05:40 +06:00
Theodoro Loureiro mota
1dd130df9e Fix : Inconsistent button height with some languages in "Data and storage" ()
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Fixing bug in the MultiChoiceSegmentedButtonRow

* Rollback file
2024-01-23 18:47:05 +06:00
Theodoro Loureiro mota
e17d87f357 Adding Type-safe project accessors ()
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding

* Enabling TYPESAFE_PROJECT_ACCESSORS

* Adding typesafe project accessors in the app module

* Adding typesafe project accessors in the core module

* Adding typesafe project accessors in the core-metadata module

* Adding typesafe project accessors in the data module

* Adding typesafe project accessors in the domain module

* Adding typesafe project accessors in the presentation-core module

* Adding typesafe project accessors in the presentation-widget module

* Adding typesafe project accessors in the source-local module

* Adding typesafe project accessors in the source-api module

* Rolling back

* Changing TYPESAFE_PROJECT_ACCESSORS line

* Removing extra spaces
2024-01-23 18:35:58 +06:00
Soitora
de75561402 Change README to Markdown ()
* Change README to Markdown

Also fix license and add disclaimer

* Change some links to markdown as well
2024-01-23 14:14:05 +06:00
AntsyLich
58085336a5 Lint 2024-01-22 20:20:11 +06:00
Soitora
89ea0a271b Add translation widget () 2024-01-22 20:12:39 +06:00
AntsyLich
e3f33e24f5 Use own client for trackers + custom user agents
Closes 
Closes 

Co-authored-by: Med <45147847+kitsumed@users.noreply.github.com>
2024-01-22 16:18:30 +06:00
AntsyLich
9fd1419142 Translations ()
* Small fix on french translation. ()

Update fr/strings.xml

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

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

* Updated Turkish suffixes ()

Update strings.xml

* Fix zh-rTW Translation ()

fix zh-tw translate

* Update Filipino Plurals ()

Updated some Filipino Plurals to make sense grammatically

* Update Filipino Strings ()

Changed/updated a few grammatical strings for the Filipino Translation

---------

Co-authored-by: Med <45147847+kitsumed@users.noreply.github.com>
Co-authored-by: NukeSource <123626751+NukeSource@users.noreply.github.com>
Co-authored-by: ɴᴇᴋᴏ <111511925+NeKoOuO@users.noreply.github.com>
Co-authored-by: InfinityDouki56 <31158494+infyProductions@users.noreply.github.com>
2024-01-22 15:45:37 +06:00
AntsyLich
cb06898430 Fix issues when updating extensions 2024-01-22 02:27:45 +06:00
AntsyLich
39407407f2 Remove usage of .not() where possible 2024-01-21 19:40:42 +06:00
AntsyLich
a024218410 Fix faulty MangaUpdates score in db
Closes 
2024-01-21 12:21:30 +06:00
AntsyLich
26815c7356 Tweak app icon scaling 2024-01-21 11:55:25 +06:00
jobobby04
e0deeb8008 Backup and Restore Excluded scanlators ()
* Backup and Restore Excluded scanlators

* Improve performance

* This looks better
2024-01-21 11:38:36 +06:00
AntsyLich
38d6ab80ce Fix "Flash on page change" gives black screen on page change
Fixes 
2024-01-20 16:33:50 +06:00
Federico Pierantoni
78e66fd8d3 Tweak README ()
* update README.md

* Update README.md

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2024-01-20 15:59:18 +06:00
Soitora
26aa126ecb Modernize README ()
* Prepare new Readme

* Modernize README

* Tweak wording
2024-01-20 01:33:42 +06:00
KaiserBh
e4a65656e7 refactor: db changes for syncing. ()
fix: sync marking chapter unread when we do library update before syncing.

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

Signed-off-by: KaiserBh <kaiserbh@proton.me>
2024-01-18 10:37:41 +06:00
352 changed files with 2866 additions and 1093 deletions
.github
README.md
app
build.gradle.kts
src
debug
main
ic_launcher-web.png
java
eu
kanade
core
domain
presentation
tachiyomi
App.ktAppInfo.ktMigrations.kt
crash
data
di
extension
ui
util
test
res
build.gradle.kts
buildSrc
config/detekt
core-metadata
core/common
data
domain
gradle
i18n
presentation-core
build.gradle.kts
src
main
java
tachiyomi
presentation-widget
settings.gradle.kts
source-api
build.gradle.kts
src
androidMain
kotlin
eu
kanade
tachiyomi
commonMain
kotlin
eu
kanade
tachiyomi
source-local
build.gradle.kts
src
androidMain
kotlin
tachiyomi
commonMain
kotlin
tachiyomi
source

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

@@ -1,11 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: ⚠️ Extension/source issue
url: https://github.com/tachiyomiorg/extensions/issues/new/choose
about: Issues and requests for official extensions and sources should be opened in the extensions repository instead
- name: 📦 Mihon extensions
url: https://mihon.app/extensions/
about: List of all available extensions with download links
- name: 🖥️ Mihon website
url: https://mihon.app/
about: Guides, troubleshooting, and answers to common questions

@@ -53,7 +53,7 @@ body:
label: Mihon version
description: You can find your Mihon version in **More → About**.
placeholder: |
Example: "0.16.1"
Example: "0.16.4"
validations:
required: true
@@ -94,11 +94,9 @@ body:
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
required: true
- label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https://mihon.app/docs/guides/troubleshooting/).
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.4](https://github.com/mihonapp/mihon/releases/latest)**.
required: true
- label: I have updated all installed extensions.
required: true

@@ -31,9 +31,7 @@ body:
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with an official extension, I should be opening an issue in the [extensions repository](https://github.com/tachiyomiorg/extensions/issues/new/choose).
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.4](https://github.com/mihonapp/mihon/releases/latest)**.
required: true
- label: I will fill out all of the requested information in this form.
required: true

BIN
.github/assets/logo.png vendored Normal file

Binary file not shown.

After

(image error) Size: 7.5 KiB

Binary file not shown.

Before

(image error) Size: 736 B

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

@@ -35,7 +35,7 @@ jobs:
- name: Build app and run unit tests
uses: gradle/gradle-command-action@v2
with:
arguments: ktlintCheck assembleStandardRelease testReleaseUnitTest
arguments: detekt assembleStandardRelease testReleaseUnitTest
# Sign APK and create release for tags
@@ -99,7 +99,7 @@ jobs:
| x86 | ${{ env.APK_X86_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: |
mihon-${{ env.VERSION_TAG }}.apk
mihon-arm64-v8a-${{ env.VERSION_TAG }}.apk

136
README.md

@@ -1,89 +1,113 @@
| Build | Stable | Weekly Beta | Support Server |
|-------|--------|-------------|----------------|
| [![CI](https://github.com/mihonapp/mihon/actions/workflows/build_push.yml/badge.svg)](https://github.com/mihonapp/mihon/actions/workflows/build_push.yml) | [![stable release](https://img.shields.io/github/release/mihonapp/mihon.svg?maxAge=3600&label=download)](https://github.com/mihonapp/mihon/releases) | [![latest beta build](https://img.shields.io/github/v/release/mihonapp/mihon-preview.svg?maxAge=3600&label=download)](https://github.com/mihonapp/mihon-preview/releases) | [![Discord](https://img.shields.io/discord/1195734228319617024.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/mihon) |
<div align="center">
# ![app icon](./.github/readme-images/app-icon.png)Mihon
Mihon is a free and open source manga reader for Android 8.0 and above.
<a href="https://mihon.app">
<img src="./.github/assets/logo.png" alt="Mihon logo" title="Mihon logo" width="80"/>
</a>
# Mihon [App](#)
### Full-featured reader
Discover and read manga, webtoons, comics, and more easier than ever on your Android device.
[![Discord server](https://img.shields.io/discord/1195734228319617024.svg?label=&labelColor=6A7EC2&color=7389D8&logo=discord&logoColor=FFFFFF)](https://discord.gg/mihon)
[![GitHub downloads](https://img.shields.io/github/downloads/mihonapp/mihon/total?label=downloads&labelColor=27303D&color=0D1117&logo=github&logoColor=FFFFFF&style=flat)](https://github.com/mihonapp/mihon/releases)
[![CI](https://img.shields.io/github/actions/workflow/status/mihonapp/mihon/build_push.yml?labelColor=27303D)](https://github.com/mihonapp/mihon/actions/workflows/build_push.yml)
[![License: Apache-2.0](https://img.shields.io/github/license/mihonapp/mihon?labelColor=27303D&color=0877d2)](/LICENSE)
[![Translation status](https://img.shields.io/weblate/progress/mihon?labelColor=27303D&color=946300)](https://hosted.weblate.org/engage/mihon/)
## Download
[![Mihon Stable](https://img.shields.io/github/release/mihonapp/mihon.svg?maxAge=3600&label=Stable&labelColor=06599d&color=043b69)](https://github.com/mihonapp/mihon/releases)
[![Mihon Beta](https://img.shields.io/github/v/release/mihonapp/mihon-preview.svg?maxAge=3600&label=Beta&labelColor=2c2c47&color=1c1c39)](https://github.com/mihonapp/mihon-preview/releases)
*Requires Android 8.0 or higher.*
## Features
Features include:
* Online reading from a variety of sources
* Local reading of downloaded content
<div align="left">
* Local reading of content.
* A configurable reader with multiple viewers, reading directions and other settings.
* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.io/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), and [Bangumi](https://bgm.tv/) support
* Categories to organize your library
* Light and dark themes
* Schedule updating your library for new chapters
* Create backups locally to read offline or to your desired cloud service
* Tracker support: [MyAnimeList](https://myanimelist.net/), [AniList](https://anilist.co/), [Kitsu](https://kitsu.io/), [MangaUpdates](https://mangaupdates.com), [Shikimori](https://shikimori.one), and [Bangumi](https://bgm.tv/) support.
* Categories to organize your library.
* Light and dark themes.
* Schedule updating your library for new chapters.
* Create backups locally to read offline or to your desired cloud service.
* Plus much more...
## Download
Get the app from our [releases page](https://github.com/mihonapp/mihon/releases).
</div>
If you want to try new features before they get to the stable release, you can download the beta version [here](https://github.com/mihonapp/mihon-preview/releases).
## Contributing
## Issues, Feature Requests and Contributing
[Code of conduct](./CODE_OF_CONDUCT.md) · [Contributing guide](./CONTRIBUTING.md)
Please make sure to read the full guidelines. Your issue may be closed without warning if you do not.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
<details><summary>Issues</summary>
If you got any questions, [join our Discord server](https://discord.gg/mihon).
1. **Before reporting a new issue, take a look at the [FAQ](https://mihon.app/docs/faq/general), the [changelog](https://mihon.app/changelogs/) and the already opened [issues](https://github.com/mihonapp/mihon/issues).**
2. If you are unsure, ask here: [![Discord](https://img.shields.io/discord/1195734228319617024.svg)](https://discord.gg/mihon)
<details align="center"><summary>Issues</summary><div align="left">
</details>
Before reporting a new issue, take a look at the [FAQ](https://mihon.app/docs/faq/general), the [changelog](https://mihon.app/changelogs/) and the already opened [issues](https://github.com/mihonapp/mihon/issues).
<details><summary>Bugs</summary>
</div></details>
* Include version (More → About → Version)
* If not latest, try updating, it may have already been solved
* Beta version is equal to the number of commits as seen on the main page
* Include steps to reproduce (if not obvious from description)
* Include screenshot (if needed)
* If it could be device-dependent, try reproducing on another device (if possible)
<details align="center"><summary>Bugs</summary><div align="left">
* Include version (**More → About → Version**).
* If not latest, try updating, it may have already been solved.
* Beta version is equal to the number of commits as seen on the main page.
* Include steps to reproduce (if not obvious from description).
* Include screenshot (if needed).
* If it could be device-dependent, try reproducing on another device (if possible).
* Don't group unrelated requests into one issue
- **DO:** [#24](https://git.mihon.dev/tachiyomi/tachiyomi/issues/24), [#71](https://git.mihon.dev/tachiyomi/tachiyomi/issues/71)
- **DON'T:** [#75](https://git.mihon.dev/tachiyomi/tachiyomi/issues/75)
</details>
</div></details>
<details><summary>Feature Requests</summary>
<details align="center"><summary>Feature requests</summary><div align="left">
* Write a detailed issue, explaining what it should do or how. Avoid writing just "like X app does"
* Write a detailed issue, explaining what it should do or how.
* Avoid writing just "like X app does";
* Include screenshot (if needed)
* Source requests are not accepted.
Source requests are not accepted.
</details>
</div></details>
<details><summary>Contributing</summary>
### Repositories
See [CONTRIBUTING.md](./CONTRIBUTING.md).
</details>
[![mihonapp/website - GitHub](https://github-readme-stats.vercel.app/api/pin/?username=mihonapp&repo=website&bg_color=161B22&text_color=c9d1d9&title_color=0877d2&icon_color=0877d2&border_radius=8&hide_border=true)](https://github.com/mihonapp/website/)
<details><summary>Code of Conduct</summary>
### Credits
See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
</details>
Thank you to all the people who have contributed!
## FAQ
<a href="https://github.com/mihonapp/mihon/graphs/contributors">
<img src="https://contrib.rocks/image?repo=mihonapp/mihon" alt="Mihon app contributors" title="Mihon app contributors" width="800"/>
</a>
[See our website.](https://mihon.app/)
You can also reach out to us on [Discord](https://discord.gg/mihon).
### Disclaimer
## License
The developer(s) of this application does not have any affiliation with the content providers available, and this application hosts zero content.
Copyright 2015 Javier Tomás
### License
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
```
Copyright © 2015 Javier Tomás
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## Disclaimer
Modifications Copyright © 2024 The Mihon Open Source Project
```
The developer of this application does not have any affiliation with the content providers available.
</div>

@@ -22,8 +22,8 @@ android {
defaultConfig {
applicationId = "app.mihon"
versionCode = 2
versionName = "0.16.1"
versionCode = 5
versionName = "0.16.4"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
@@ -139,15 +139,15 @@ android {
}
dependencies {
implementation(project(":i18n"))
implementation(project(":core"))
implementation(project(":core-metadata"))
implementation(project(":source-api"))
implementation(project(":source-local"))
implementation(project(":data"))
implementation(project(":domain"))
implementation(project(":presentation-core"))
implementation(project(":presentation-widget"))
implementation(projects.i18n)
implementation(projects.core.common)
implementation(projects.coreMetadata)
implementation(projects.sourceApi)
implementation(projects.sourceLocal)
implementation(projects.data)
implementation(projects.domain)
implementation(projects.presentationCore)
implementation(projects.presentationWidget)
// Compose
implementation(platform(compose.bom))
@@ -163,7 +163,6 @@ dependencies {
implementation(compose.ui.util)
implementation(compose.accompanist.webview)
implementation(compose.accompanist.systemuicontroller)
lintChecks(compose.lintchecks)
implementation(androidx.paging.runtime)
implementation(androidx.paging.compose)

@@ -12,5 +12,12 @@
<path
android:pathData="M0,0h432v432h-432z"
android:fillColor="#2E3943"/>
<path
android:pathData="M322.13,215.5C322.13,272.66 274.64,319 216.07,319C157.49,319 110,272.66 110,215.5C110,158.34 157.49,112 216.07,112C274.64,112 322.13,158.34 322.13,215.5Z"
android:fillColor="#F2FAFF"/>
<path
android:pathData="M216.07,299.59C263.66,299.59 302.24,261.94 302.24,215.5C302.24,169.06 263.66,131.41 216.07,131.41C168.47,131.41 129.89,169.06 129.89,215.5C129.89,261.94 168.47,299.59 216.07,299.59ZM216.07,319C274.64,319 322.13,272.66 322.13,215.5C322.13,158.34 274.64,112 216.07,112C157.49,112 110,158.34 110,215.5C110,272.66 157.49,319 216.07,319Z"
android:fillColor="#7EBBED"
android:fillType="evenOdd"/>
</group>
</vector>

@@ -4,13 +4,6 @@
android:viewportWidth="432"
android:viewportHeight="432">
<path
android:pathData="M337,216C337,282.83 282.83,337 216,337C149.17,337 95,282.83 95,216C95,149.17 149.17,95 216,95C282.83,95 337,149.17 337,216Z"
android:fillColor="#F2FAFF"/>
<path
android:pathData="M216,314.31C270.3,314.31 314.31,270.3 314.31,216C314.31,161.7 270.3,117.69 216,117.69C161.7,117.69 117.69,161.7 117.69,216C117.69,270.3 161.7,314.31 216,314.31ZM216,337C282.83,337 337,282.83 337,216C337,149.17 282.83,95 216,95C149.17,95 95,149.17 95,216C95,282.83 149.17,337 216,337Z"
android:fillColor="#7EBBED"
android:fillType="evenOdd"/>
<path
android:pathData="M163.71,174.79L162.66,150.56C165.82,151.16 169.58,151.31 178.16,151.31C188.55,151.31 202.24,150.71 209.32,149.81C212.32,149.51 213.53,149.05 215.49,148L231.74,161.85C230.23,163.95 229.78,164.86 228.13,169.07C226.77,172.38 220.6,191.49 218.2,199.62C229.33,201.88 235.5,203.53 243.93,206.99C244.98,199.62 245.13,195.71 245.13,182.31C245.13,178.85 244.98,176.9 244.53,173.74L270.72,174.64C269.96,178.25 269.82,179.76 269.66,185.62C269.06,199.77 268.46,206.54 266.95,216.78C277.34,222.04 277.34,222.04 282.61,224.9C285.32,226.41 285.92,226.71 287.72,227.31L278.99,255.45C274.78,251.69 268.91,247.63 260.33,242.81C252.81,260.72 240.32,273.82 221.35,284.2C215.03,275.77 210.22,270.65 202.54,264.63C213.68,259.37 218.8,256.06 224.67,250.49C230.38,244.92 234.15,239.5 237.76,231.38C228.13,227.01 221.96,225.05 211.27,222.8C205.1,241.16 200.13,252.9 195.77,259.97C189.9,269.45 181.93,274.42 172.74,274.42C165.67,274.42 158.45,271.26 153.18,265.84C147.16,259.67 144,251.09 144,241.16C144,226.41 151.07,213.62 163.41,205.64C171.39,200.52 179.82,198.27 193.21,197.51C195.92,188.63 198.18,180.96 200.29,172.38C193.66,172.98 185.39,173.43 175.3,173.88C169.88,174.04 168.08,174.19 163.71,174.79ZM186.59,220.54C179.52,221.74 175.3,224 171.54,228.82C168.68,232.13 167.33,236.04 167.33,240.25C167.33,244.92 169.58,248.38 172.44,248.38C175.9,248.38 179.82,240.55 186.59,220.54Z"
android:pathData="M182.03,188.7L181.33,172.69C183.42,173.09 185.91,173.19 191.57,173.19C198.44,173.19 207.49,172.79 212.16,172.19C214.15,171.99 214.95,171.7 216.24,171L226.98,180.15C225.98,181.54 225.68,182.14 224.59,184.92C223.7,187.11 219.62,199.74 218.03,205.11C225.39,206.6 229.46,207.7 235.03,209.98C235.73,205.11 235.83,202.52 235.83,193.67C235.83,191.39 235.73,190.09 235.43,188.01L252.74,188.6C252.24,190.99 252.14,191.98 252.04,195.86C251.64,205.21 251.24,209.68 250.25,216.45C257.11,219.93 257.11,219.93 260.59,221.82C262.38,222.81 262.78,223.01 263.97,223.41L258.2,242.01C255.42,239.52 251.54,236.83 245.87,233.65C240.9,245.49 232.65,254.14 220.12,261C215.94,255.43 212.76,252.05 207.68,248.07C215.04,244.59 218.43,242.4 222.3,238.72C226.08,235.04 228.57,231.46 230.96,226.09C224.59,223.21 220.51,221.92 213.45,220.43C209.38,232.56 206.09,240.32 203.21,244.99C199.33,251.25 194.06,254.54 187.99,254.54C183.32,254.54 178.55,252.45 175.07,248.87C171.09,244.79 169,239.12 169,232.56C169,222.81 173.67,214.36 181.83,209.09C187.1,205.71 192.67,204.21 201.52,203.72C203.31,197.85 204.8,192.78 206.19,187.11C201.82,187.51 196.35,187.81 189.68,188.1C186.1,188.2 184.91,188.3 182.03,188.7ZM197.14,218.93C192.47,219.73 189.68,221.22 187.2,224.4C185.31,226.59 184.41,229.18 184.41,231.96C184.41,235.04 185.91,237.33 187.8,237.33C190.08,237.33 192.67,232.16 197.14,218.93Z"
android:fillColor="#031019"/>
</vector>

Binary file not shown.

Before

(image error) Size: 22 KiB

@@ -1,7 +1,7 @@
package eu.kanade.core.preference
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) {
is CheckboxState.TriState.Exclude -> ToggleableState.Indeterminate

@@ -5,7 +5,7 @@ import androidx.compose.runtime.mutableStateOf
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import tachiyomi.core.preference.Preference
import tachiyomi.core.common.preference.Preference
class PreferenceMutableState<T>(
private val preference: Preference<T>,

@@ -2,8 +2,8 @@ package eu.kanade.domain.base
import android.content.Context
import dev.icerock.moko.resources.StringResource
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.i18n.MR
class BasePreferences(

@@ -5,9 +5,9 @@ import eu.kanade.domain.base.BasePreferences.ExtensionInstaller
import eu.kanade.tachiyomi.util.system.hasMiuiPackageInstaller
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
import kotlinx.coroutines.CoroutineScope
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.getEnum
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.getEnum
class ExtensionInstallerPreference(
private val context: Context,

@@ -2,8 +2,8 @@ package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.download.interactor.DeleteDownload
import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.model.ChapterUpdate
import tachiyomi.domain.chapter.repository.ChapterRepository

@@ -163,7 +163,7 @@ class SyncChaptersWithSource(
var updatedToAdd = newChapters.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--)
if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
if (!chapter.isRecognizedNumber || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
chapter = chapter.copy(
read = chapter.chapterNumber in deletedReadChapterNumbers,

@@ -1,7 +1,7 @@
package eu.kanade.domain.download.interactor
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.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager

@@ -1,7 +1,7 @@
package eu.kanade.domain.extension.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.plusAssign
import tachiyomi.core.common.preference.plusAssign
class CreateExtensionRepo(private val preferences: SourcePreferences) {

@@ -1,7 +1,7 @@
package eu.kanade.domain.extension.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.minusAssign
import tachiyomi.core.common.preference.minusAssign
class DeleteExtensionRepo(private val preferences: SourcePreferences) {

@@ -23,7 +23,7 @@ class GetExtensionSources(
ExtensionSourceItem(
source = source,
enabled = source.isEnabled(),
labelAsName = isMultiSource && isMultiLangSingleSource.not(),
labelAsName = isMultiSource && !isMultiLangSingleSource,
)
}
}

@@ -22,9 +22,9 @@ class GetExtensionsByType(
extensionManager.availableExtensionsFlow,
) { _activeLanguages, _installed, _untrusted, _available ->
val (updates, installed) = _installed
.filter { (showNsfwSources || it.isNsfw.not()) }
.filter { (showNsfwSources || !it.isNsfw) }
.sortedWith(
compareBy<Extension.Installed> { it.isObsolete.not() }
compareBy<Extension.Installed> { !it.isObsolete }
.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name },
)
.partition { it.hasUpdate }
@@ -36,7 +36,7 @@ class GetExtensionsByType(
.filter { extension ->
_installed.none { it.pkgName == extension.pkgName } &&
_untrusted.none { it.pkgName == extension.pkgName } &&
(showNsfwSources || extension.isNsfw.not())
(showNsfwSources || !extension.isNsfw)
}
.flatMap { ext ->
if (ext.sources.isEmpty()) {

@@ -3,7 +3,7 @@ package eu.kanade.domain.extension.interactor
import android.content.pm.PackageInfo
import androidx.core.content.pm.PackageInfoCompat
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.common.preference.getAndSet
class TrustExtension(
private val preferences: SourcePreferences,

@@ -5,9 +5,9 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
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.ComicInfoPublishingStatus
import tachiyomi.core.preference.TriState
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.Injekt

@@ -3,7 +3,7 @@ package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.coroutines.flow.Flow
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.repository.SourceRepository
import tachiyomi.source.local.isLocal
@@ -34,15 +34,15 @@ class GetSourcesWithFavoriteCount(
when (sorting) {
SetMigrateSorting.Mode.ALPHABETICAL -> {
when {
a.first.isStub && b.first.isStub.not() -> -1
b.first.isStub && a.first.isStub.not() -> 1
a.first.isStub && !b.first.isStub -> -1
b.first.isStub && !a.first.isStub -> 1
else -> a.first.name.lowercase().compareToWithCollator(b.first.name.lowercase())
}
}
SetMigrateSorting.Mode.TOTAL -> {
when {
a.first.isStub && b.first.isStub.not() -> -1
b.first.isStub && a.first.isStub.not() -> 1
a.first.isStub && !b.first.isStub -> -1
b.first.isStub && !a.first.isStub -> 1
else -> a.second.compareTo(b.second)
}
}

@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.common.preference.getAndSet
class ToggleLanguage(
val preferences: SourcePreferences,

@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source
class ToggleSource(

@@ -1,7 +1,7 @@
package eu.kanade.domain.source.interactor
import eu.kanade.domain.source.service.SourcePreferences
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.common.preference.getAndSet
import tachiyomi.domain.source.model.Source
class ToggleSourcePin(

@@ -2,9 +2,9 @@ package eu.kanade.domain.source.service
import eu.kanade.domain.source.interactor.SetMigrateSorting
import eu.kanade.tachiyomi.util.system.LocaleHelper
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.getEnum
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.getEnum
import tachiyomi.domain.library.model.LibraryDisplayMode
class SourcePreferences(

@@ -8,9 +8,9 @@ import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.model.Manga

@@ -30,9 +30,9 @@ class RefreshTracks(
.map { (track, service) ->
async {
return@async try {
val updatedTrack = service!!.refresh(track.toDbTrack())
insertTrack.await(updatedTrack.toDomainTrack()!!)
syncChapterProgressWithTrack.await(mangaId, track, service)
val updatedTrack = service!!.refresh(track.toDbTrack()).toDomainTrack()!!
insertTrack.await(updatedTrack)
syncChapterProgressWithTrack.await(mangaId, updatedTrack, service)
null
} catch (e: Throwable) {
service to e

@@ -4,7 +4,7 @@ import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.tachiyomi.data.track.EnhancedTracker
import eu.kanade.tachiyomi.data.track.Tracker
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.UpdateChapter
import tachiyomi.domain.chapter.model.toChapterUpdate

@@ -9,8 +9,8 @@ import eu.kanade.tachiyomi.data.track.TrackerManager
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import logcat.LogPriority
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withNonCancellableContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack

@@ -19,30 +19,28 @@ fun Track.toDbTrack(): DbTrack = DbTrack.create(trackerId).also {
it.remote_id = remoteId
it.library_id = libraryId
it.title = title
it.last_chapter_read = lastChapterRead.toFloat()
it.total_chapters = totalChapters.toInt()
it.status = status.toInt()
it.score = score.toFloat()
it.last_chapter_read = lastChapterRead
it.total_chapters = totalChapters
it.status = status
it.score = score
it.tracking_url = remoteUrl
it.started_reading_date = startDate
it.finished_reading_date = finishDate
}
fun DbTrack.toDomainTrack(idRequired: Boolean = true): Track? {
val trackId = id ?: if (idRequired.not()) -1 else return null
val trackId = id ?: if (!idRequired) -1 else return null
return Track(
id = trackId,
mangaId = manga_id,
trackerId = tracker_id.toLong(),
trackerId = tracker_id,
remoteId = remote_id,
libraryId = library_id,
title = title,
lastChapterRead = last_chapter_read.toDouble(),
totalChapters = total_chapters.toLong(),
status = status.toLong(),
// Jank workaround due to precision issues while converting
// See https://github.com/tachiyomiorg/tachiyomi/issues/10343
score = score.toString().toDouble(),
lastChapterRead = last_chapter_read,
totalChapters = total_chapters,
status = status,
score = score,
remoteUrl = tracking_url,
startDate = started_reading_date,
finishDate = finished_reading_date,

@@ -12,8 +12,8 @@ import eu.kanade.domain.track.interactor.TrackChapter
import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.track.interactor.GetTracks
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

@@ -2,8 +2,8 @@ package eu.kanade.domain.track.service
import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.anilist.Anilist
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
class TrackPreferences(
private val preferenceStore: PreferenceStore,
@@ -19,9 +19,15 @@ class TrackPreferences(
"",
)
fun trackAuthExpired(tracker: Tracker) = preferenceStore.getBoolean(
Preference.privateKey("pref_tracker_auth_expired_${tracker.id}"),
false,
)
fun setCredentials(tracker: Tracker, username: String, password: String) {
trackUsername(tracker).set(username)
trackPassword(tracker).set(password)
trackAuthExpired(tracker).set(false)
}
fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")

@@ -3,7 +3,7 @@ package eu.kanade.domain.track.store
import android.content.Context
import androidx.core.content.edit
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.system.logcat
class DelayedTrackingStore(context: Context) {

@@ -5,8 +5,8 @@ import eu.kanade.domain.ui.model.TabletUiMode
import eu.kanade.domain.ui.model.ThemeMode
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.getEnum
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.getEnum
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Locale

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

@@ -53,6 +53,7 @@ import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR
@@ -224,7 +225,31 @@ private fun DetailsHeader(
end = MaterialTheme.padding.medium,
top = MaterialTheme.padding.medium,
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,
) {
ExtensionIcon(

@@ -203,7 +203,13 @@ private fun ExtensionContent(
items(
items = items,
contentType = { "item" },
key = { "extension-${it.hashCode()}" },
key = { item ->
when (item.extension) {
is Extension.Untrusted -> "extension-untrusted-${item.hashCode()}"
is Extension.Installed -> "extension-installed-${item.hashCode()}"
is Extension.Available -> "extension-available-${item.hashCode()}"
}
},
) { item ->
ExtensionItem(
modifier = Modifier.animateItemPlacement(),

@@ -31,7 +31,7 @@ import eu.kanade.presentation.util.rememberResourceBitmapPainter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension
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.source.local.isLocal

@@ -2,7 +2,7 @@ package eu.kanade.presentation.category
import android.content.Context
import androidx.compose.runtime.Composable
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.domain.category.model.Category
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource

@@ -30,7 +30,7 @@ import eu.kanade.presentation.category.visualName
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay
import tachiyomi.core.preference.CheckboxState
import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.domain.category.model.Category
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding

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

@@ -10,7 +10,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import dev.icerock.moko.resources.StringResource
import tachiyomi.core.preference.CheckboxState
import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LabeledCheckbox
import tachiyomi.presentation.core.i18n.stringResource

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

@@ -31,7 +31,7 @@ import eu.kanade.domain.manga.model.forceDownloaded
import eu.kanade.presentation.components.TabbedDialog
import eu.kanade.presentation.components.TabbedDialogPaddings
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.core.preference.TriState
import tachiyomi.core.common.preference.TriState
import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LabeledCheckbox

@@ -10,7 +10,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.outlined.ArrowDownward
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.DropdownMenuItem
import androidx.compose.material3.Icon
@@ -256,7 +256,7 @@ private fun Modifier.commonClickable(
onClick = onClick,
role = Role.Button,
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(
indication = ripple(
bounded = false,
radius = IconButtonTokens.StateLayerSize / 2,
),

@@ -30,7 +30,7 @@ import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.Download
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.MaterialTheme
import androidx.compose.material3.Surface
@@ -192,7 +192,7 @@ private fun RowScope.Button(
.weight(animatedWeight)
.combinedClickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
indication = ripple(bounded = false),
onLongClick = onLongClick,
onClick = onClick,
),

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

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

@@ -57,9 +57,9 @@ import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.launch
import logcat.LogPriority
import okhttp3.Headers
import tachiyomi.core.util.lang.launchNonCancellable
import tachiyomi.core.util.lang.withUIContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.manga.interactor.ResetViewerFlags
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource

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

@@ -7,8 +7,11 @@ import android.net.Uri
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
@@ -47,11 +50,11 @@ import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import logcat.LogPriority
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.storage.displayablePath
import tachiyomi.core.util.lang.launchNonCancellable
import tachiyomi.core.util.lang.withUIContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.storage.displayablePath
import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.storage.service.StoragePreferences
@@ -97,7 +100,7 @@ object SettingsDataScreen : SearchableSettings {
@Composable
fun storageLocationPicker(
storageDirPref: tachiyomi.core.preference.Preference<String>,
storageDirPref: tachiyomi.core.common.preference.Preference<String>,
): ManagedActivityResultLauncher<Uri?, Uri?> {
val context = LocalContext.current
@@ -119,7 +122,7 @@ object SettingsDataScreen : SearchableSettings {
@Composable
fun storageLocationText(
storageDirPref: tachiyomi.core.preference.Preference<String>,
storageDirPref: tachiyomi.core.common.preference.Preference<String>,
): String {
val context = LocalContext.current
val storageDir by storageDirPref.collectAsState()
@@ -189,9 +192,11 @@ object SettingsDataScreen : SearchableSettings {
MultiChoiceSegmentedButtonRow(
modifier = Modifier
.fillMaxWidth()
.height(intrinsicSize = IntrinsicSize.Min)
.padding(horizontal = PrefsHorizontalPadding),
) {
SegmentedButton(
modifier = Modifier.fillMaxHeight(),
checked = false,
onCheckedChange = { navigator.push(CreateBackupScreen()) },
shape = SegmentedButtonDefaults.itemShape(0, 2),
@@ -199,6 +204,7 @@ object SettingsDataScreen : SearchableSettings {
Text(stringResource(MR.strings.pref_create_backup))
}
SegmentedButton(
modifier = Modifier.fillMaxHeight(),
checked = false,
onCheckedChange = {
if (!BackupRestoreJob.isRunning(context)) {

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

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

@@ -38,9 +38,9 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.launch
import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.lang.withUIContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.release.interactor.GetApplicationRelease
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.LinkIcon

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

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

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

@@ -48,7 +48,7 @@ import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
import tachiyomi.core.preference.InMemoryPreferenceStore
import tachiyomi.core.common.preference.InMemoryPreferenceStore
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource

@@ -11,6 +11,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import kotlinx.coroutines.delay
import kotlin.time.Duration.Companion.seconds
@Stable
class DisplayRefreshHost {
@@ -30,15 +31,15 @@ fun DisplayRefreshHost(
val currentDisplayRefresh = hostState.currentDisplayRefresh
LaunchedEffect(currentDisplayRefresh) {
if (currentDisplayRefresh) {
delay(1500)
delay(1.5.seconds)
hostState.currentDisplayRefresh = false
}
}
if (currentDisplayRefresh) {
Canvas(
modifier = modifier.fillMaxSize(),
) {
Canvas(
modifier = modifier.fillMaxSize(),
) {
if (currentDisplayRefresh) {
drawRect(Color.Black)
}
}

@@ -11,7 +11,7 @@ import androidx.core.graphics.green
import androidx.core.graphics.red
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.ColorFilterMode
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.presentation.core.components.CheckboxItem
import tachiyomi.presentation.core.components.SettingsChipRow

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

@@ -88,7 +88,7 @@ fun TrackInfoDialogHome(
TrackInfoItem(
title = item.track.title,
tracker = item.tracker,
status = item.tracker.getStatus(item.track.status.toInt()),
status = item.tracker.getStatus(item.track.status),
onStatusClick = { onStatusClick(item) },
chapters = "${item.track.lastChapterRead.toInt()}".let {
val totalChapters = item.track.totalChapters

@@ -48,9 +48,9 @@ import tachiyomi.presentation.core.util.isScrolledToStart
@Composable
fun TrackStatusSelector(
selection: Int,
onSelectionChange: (Int) -> Unit,
selections: Map<Int, StringResource?>,
selection: Long,
onSelectionChange: (Long) -> Unit,
selections: Map<Long, StringResource?>,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
@@ -236,12 +236,12 @@ private fun TrackStatusSelectorPreviews() {
onSelectionChange = {},
selections = persistentMapOf(
// Anilist values
1 to MR.strings.reading,
2 to MR.strings.plan_to_read,
3 to MR.strings.completed,
4 to MR.strings.on_hold,
5 to MR.strings.dropped,
6 to MR.strings.repeating,
1L to MR.strings.reading,
2L to MR.strings.plan_to_read,
3L to MR.strings.completed,
4L to MR.strings.on_hold,
5L to MR.strings.dropped,
6L to MR.strings.repeating,
),
onConfirm = {},
onDismissRequest = {},

@@ -301,7 +301,7 @@ private fun SearchResultItem(
text = status,
)
}
if (trackSearch.score != -1f) {
if (trackSearch.score != -1.0) {
SearchResultItemDetails(
title = stringResource(MR.strings.score),
text = trackSearch.score.toString(),

@@ -62,14 +62,14 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
private fun randTrackSearch() = TrackSearch().let {
it.id = Random.nextLong()
it.manga_id = Random.nextLong()
it.tracker_id = Random.nextInt()
it.tracker_id = Random.nextLong()
it.remote_id = Random.nextLong()
it.library_id = Random.nextLong()
it.title = lorem((1..10).random()).joinToString()
it.last_chapter_read = (0..100).random().toFloat()
it.total_chapters = (100..1000).random()
it.score = (0..10).random().toFloat()
it.status = Random.nextInt()
it.last_chapter_read = (0..100).random().toDouble()
it.total_chapters = (100L..1000L).random()
it.score = (0..10).random().toDouble()
it.status = Random.nextLong()
it.started_reading_date = 0L
it.finished_reading_date = 0L
it.tracking_url = "https://example.com/tracker-example"

@@ -4,7 +4,7 @@ import android.content.Context
import eu.kanade.tachiyomi.network.HttpException
import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException
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.domain.source.model.SourceNotInstalledException
import tachiyomi.i18n.MR

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

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

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

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

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

@@ -12,9 +12,9 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.i18n.pluralStringResource
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.storage.displayablePath
import tachiyomi.core.common.i18n.pluralStringResource
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.storage.displayablePath
import tachiyomi.i18n.MR
import uy.kohesive.injekt.injectLazy
import java.io.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.workManager
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.storage.service.StorageManager
import uy.kohesive.injekt.Injekt

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

@@ -30,6 +30,10 @@ class MangaBackupCreator(
// Entry for this manga
val mangaObject = manga.toBackupManga()
mangaObject.excludedScanlators = handler.awaitList {
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(manga.id)
}
if (options.chapters) {
// Backup all the chapters
handler.awaitList {

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

@@ -38,6 +38,7 @@ data class BackupManga(
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
@ProtoNumber(106) var lastModifiedAt: Long = 0,
@ProtoNumber(107) var favoriteModifiedAt: Long? = null,
@ProtoNumber(108) var excludedScanlators: List<String> = emptyList(),
) {
fun getMangaImpl(): Manga {
return Manga.create().copy(

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

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

@@ -73,6 +73,7 @@ class MangaRestorer(
backupCategories = backupCategories,
history = backupManga.history + backupManga.brokenHistory.map { it.toBackupHistory() },
tracks = backupManga.tracking,
excludedScanlators = backupManga.excludedScanlators,
)
}
}
@@ -264,11 +265,13 @@ class MangaRestorer(
backupCategories: List<BackupCategory>,
history: List<BackupHistory>,
tracks: List<BackupTracking>,
excludedScanlators: List<String>,
): Manga {
restoreCategories(manga, categories, backupCategories)
restoreChapters(manga, chapters)
restoreTracking(manga, tracks)
restoreHistory(history)
restoreExcludedScanlators(manga, excludedScanlators)
updateManga.awaitUpdateFetchInterval(manga, now, currentFetchWindow)
return manga
}
@@ -401,4 +404,25 @@ class MangaRestorer(
}
private fun Track.forComparison() = this.copy(id = 0L, mangaId = 0L)
/**
* Restores the excluded scanlators for the manga.
*
* @param manga the manga whose excluded scanlators have to be restored.
* @param excludedScanlators the excluded scanlators to restore.
*/
private suspend fun restoreExcludedScanlators(manga: Manga, excludedScanlators: List<String>) {
if (excludedScanlators.isEmpty()) return
val existingExcludedScanlators = handler.awaitList {
excluded_scanlatorsQueries.getExcludedScanlatorsByMangaId(manga.id)
}
val toInsert = excludedScanlators.filter { it !in existingExcludedScanlators }
if (toInsert.isNotEmpty()) {
handler.await {
toInsert.forEach {
excluded_scanlatorsQueries.insert(manga.id, it)
}
}
}
}
}

@@ -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.library.LibraryUpdateJob
import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.AndroidPreferenceStore
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.common.preference.AndroidPreferenceStore
import tachiyomi.core.common.preference.PreferenceStore
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

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

@@ -27,7 +27,7 @@ import okio.Source
import okio.buffer
import okio.sink
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.MangaCover
import tachiyomi.domain.source.service.SourceManager

@@ -9,7 +9,7 @@ import coil.decode.ImageSource
import coil.fetch.SourceResult
import coil.request.Options
import okio.BufferedSource
import tachiyomi.core.util.system.ImageUtil
import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.decoder.ImageDecoder
/**

@@ -8,7 +8,7 @@ interface Track : Serializable {
var manga_id: Long
var tracker_id: Int
var tracker_id: Long
var remote_id: Long
@@ -16,13 +16,13 @@ interface Track : Serializable {
var title: String
var last_chapter_read: Float
var last_chapter_read: Double
var total_chapters: Int
var total_chapters: Long
var score: Float
var score: Double
var status: Int
var status: Long
var started_reading_date: Long
@@ -40,7 +40,7 @@ interface Track : Serializable {
companion object {
fun create(serviceId: Long): Track = TrackImpl().apply {
tracker_id = serviceId.toInt()
tracker_id = serviceId
}
}
}

@@ -6,7 +6,7 @@ class TrackImpl : Track {
override var manga_id: Long = 0
override var tracker_id: Int = 0
override var tracker_id: Long = 0
override var remote_id: Long = 0
@@ -14,13 +14,13 @@ class TrackImpl : Track {
override lateinit var title: String
override var last_chapter_read: Float = 0F
override var last_chapter_read: Double = 0.0
override var total_chapters: Int = 0
override var total_chapters: Long = 0
override var score: Float = 0f
override var score: Double = 0.0
override var status: Int = 0
override var status: Long = 0
override var started_reading_date: Long = 0

@@ -39,11 +39,11 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority
import tachiyomi.core.storage.extension
import tachiyomi.core.storage.nameWithoutExtension
import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.lang.launchNonCancellable
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.storage.extension
import tachiyomi.core.common.storage.nameWithoutExtension
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchNonCancellable
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager

@@ -14,10 +14,10 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.runBlocking
import logcat.LogPriority
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.storage.extension
import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.storage.extension
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.download.service.DownloadPreferences
@@ -315,13 +315,13 @@ class DownloadManager(
val capitalizationChanged = oldFolder.name.equals(newName, ignoreCase = true)
if (capitalizationChanged) {
val tempName = newName + Downloader.TMP_DIR_SUFFIX
if (oldFolder.renameTo(tempName).not()) {
if (!oldFolder.renameTo(tempName)) {
logcat(LogPriority.ERROR) { "Failed to rename source download folder: ${oldFolder.name}" }
return
}
}
if (oldFolder.renameTo(newName).not()) {
if (!oldFolder.renameTo(newName)) {
logcat(LogPriority.ERROR) { "Failed to rename source download folder: ${oldFolder.name}" }
}
}

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

@@ -5,9 +5,9 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.util.storage.DiskUtil
import logcat.LogPriority
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.storage.displayablePath
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.storage.displayablePath
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.storage.service.StorageManager
@@ -130,7 +130,7 @@ class DownloadProvider(
val newChapterName = sanitizeChapterName(chapterName)
return DiskUtil.buildValidFilename(
when {
chapterScanlator.isNullOrBlank().not() -> "${chapterScanlator}_$newChapterName"
!chapterScanlator.isNullOrBlank() -> "${chapterScanlator}_$newChapterName"
else -> newChapterName
},
)

@@ -40,15 +40,15 @@ import kotlinx.coroutines.supervisorScope
import logcat.LogPriority
import nl.adaptivity.xmlutil.serialization.XML
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.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.chapter.model.Chapter
import tachiyomi.domain.download.service.DownloadPreferences

@@ -39,10 +39,10 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.preference.getAndSet
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.getAndSet
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
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 {
try {
if (errors.isNotEmpty()) {
val file = context.createFileInCacheDir("tachiyomi_update_errors.txt")
val file = context.createFileInCacheDir("mihon_update_errors.txt")
file.bufferedWriter().use { out ->
out.write(context.stringResource(MR.strings.library_errors_help, ERROR_LOG_HELP_URL) + "\n\n")
// Error file format:

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

@@ -27,8 +27,8 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.manga.interactor.GetLibraryManga
import tachiyomi.domain.manga.model.Manga

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