Compare commits

...

67 Commits
v6.6 ... v6.6.6

Author SHA1 Message Date
Koitharu
4252ebd24d Bump versionCode 2024-01-24 12:40:18 +02:00
Koitharu
cd0575a524 Update parsers 2024-01-24 12:28:50 +02:00
Koitharu
6eb2608f88 Disable autofill for protect password fields #702
(cherry picked from commit e7c9d1943d)
2024-01-24 12:16:18 +02:00
Koitharu
39e21ff93c Last read order in favorites #705
(cherry picked from commit b1240e7efa)
2024-01-24 12:16:12 +02:00
Koitharu
5ec2eab6b8 Fix webtoon scroll dispatching
(cherry picked from commit a0a72b1192)
2024-01-24 12:15:41 +02:00
Koitharu
850f6c2f3e Fix pages numbers
(cherry picked from commit 83cb35fe6e)
2024-01-24 12:09:11 +02:00
Koitharu
ec53eb9c70 Incognito mode indicator in reader
(cherry picked from commit db1ddf539c)
2024-01-24 12:08:52 +02:00
Koitharu
cdd76f723f Fix favorites counters
(cherry picked from commit d56fc674ab)
2024-01-24 12:08:17 +02:00
Koitharu
a37e8825b0 All favorites item change payload 2024-01-20 09:31:17 +02:00
Koitharu
2450544454 Update parsers
(cherry picked from commit da2ad40adf)
2024-01-20 09:22:28 +02:00
Koitharu
f6a510653e Fix import dialog injection
(cherry picked from commit af5716a8ce)
2024-01-20 09:21:43 +02:00
Koitharu
5990da587c Update supported links domains
(cherry picked from commit a98202e15e)
2024-01-20 09:21:40 +02:00
Koitharu
91e3d2f5db Skip unsupported sources in global search
(cherry picked from commit d6887e2d75)
2024-01-20 09:21:35 +02:00
Koitharu
971c683746 Show all favorites on categories screen
(cherry picked from commit 2a5300a634)
2024-01-20 09:21:27 +02:00
Koitharu
15e9aaab26 Fix pages list scrolling
(cherry picked from commit a1120ea709)
2024-01-20 09:21:18 +02:00
Koitharu
12047a85c7 Update parsers 2024-01-17 13:33:55 +02:00
Koitharu
48808f8a7d Improve scrobbling selection 2024-01-17 11:41:03 +02:00
Koitharu
18e573b6b8 Merge remote-tracking branch 'weblate/devel' into devel 2024-01-16 15:37:40 +02:00
Koitharu
c80dc08d6c Fix details activity tabs 2024-01-16 15:30:56 +02:00
Koitharu
61b5b8aa73 Fixes 2024-01-16 15:30:55 +02:00
Koitharu
5e79809326 Support reverse alphabetic order in history and favorties 2024-01-16 15:30:55 +02:00
Koitharu
dcbd7c2117 Fix history sorting 2024-01-16 15:30:55 +02:00
Koitharu
1e134b109a Fix favorites sort order 2024-01-16 15:30:55 +02:00
Koitharu
7f9b6a67af Reduce workers retry frequency 2024-01-16 15:30:55 +02:00
Koitharu
79448bb01d Workaround for ViewPager2 bug 2024-01-16 15:30:54 +02:00
Koitharu
b94f9e4b01 Fix primary navigation restore state 2024-01-16 15:30:54 +02:00
Koitharu
ae8b48d733 Migrate favorites to ViewPager2 2024-01-16 15:30:53 +02:00
Koitharu
313013dccd Mark as completed in history 2024-01-16 15:24:58 +02:00
NA0341
c36d23ec06 Update CONTRIBUTING.md
Improved readability & fixed spelling.
2024-01-16 15:24:41 +02:00
Paramjot singj
ebe71476d1 Translated using Weblate (Punjabi)
Currently translated at 4.1% (23 of 556 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pa/
2024-01-15 19:06:18 +01:00
Paramjot singj
ca2ae9bc83 Translated using Weblate (Hindi)
Currently translated at 22.8% (127 of 556 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/hi/
2024-01-15 19:06:18 +01:00
Alex Georgiou
f2898aba85 Translated using Weblate (Greek)
Currently translated at 99.8% (555 of 556 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
2024-01-15 19:06:18 +01:00
Dimas oppo
1b73f19ae1 Translated using Weblate (Indonesian)
Currently translated at 96.2% (535 of 556 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/
2024-01-15 19:06:18 +01:00
Paramjot singj
4b4aea0410 Translated using Weblate (Italian)
Currently translated at 100.0% (7 of 7 strings)

Translation: Kotatsu/plurals
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
2024-01-15 19:06:17 +01:00
Çınar
b9f8e3978a Translated using Weblate (Turkish)
Currently translated at 100.0% (556 of 556 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
2024-01-15 19:06:17 +01:00
Weblate (bot)
89eed10508 Translations update from Hosted Weblate (#652)
* Translated using Weblate (Greek)

Currently translated at 99.8% (555 of 556 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Translated using Weblate (Greek)

Currently translated at 45.8% (255 of 556 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (7 of 7 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Alex Georgiou <alexandrosgeorgiou35@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/el/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals

* Translated using Weblate (German)

Currently translated at 99.6% (554 of 556 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Bela K <na0341-dev@posteo.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translation: Kotatsu/Strings

* Translated using Weblate (Spanish)

Currently translated at 100.0% (556 of 556 strings)

Translated using Weblate (Spanish)

Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings

* Translated using Weblate (French)

Currently translated at 100.0% (7 of 7 strings)

Translated using Weblate (French)

Currently translated at 96.2% (535 of 556 strings)

Co-authored-by: Quentin VERDIER <quent1.verdier@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: Deivinni Silva <deivinnimds3656@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings

* Translated using Weblate (Serbian)

Currently translated at 99.1% (551 of 556 strings)

Co-authored-by: Anon <anonymousprivate76@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sr/
Translation: Kotatsu/Strings

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings

* Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: Judith Smith <i@razuritta.me>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings

* Translated using Weblate (Malay)

Currently translated at 56.1% (312 of 556 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (7 of 7 strings)

Added translation using Weblate (Malay)

Added translation using Weblate (Malay)

Co-authored-by: Megat Al Zhahir Daniel <megatalzhahir@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/ms/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ms/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings

* Translated using Weblate (Arabic)

Currently translated at 51.0% (284 of 556 strings)

Co-authored-by: Khaled <ashen.cv@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ar/
Translation: Kotatsu/Strings

* Translated using Weblate (Greek)

Currently translated at 99.8% (555 of 556 strings)

Co-authored-by: Theodore Visvikis <theodoros.visvikis@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translation: Kotatsu/Strings

* Translated using Weblate (Italian)

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Paramjot singj <paramjotsingh2852@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings

* Translated using Weblate (Italian)

Currently translated at 100.0% (7 of 7 strings)

Co-authored-by: Paper Jack <paperjack@tutanota.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translation: Kotatsu/plurals

* Added translation using Weblate (Punjabi (Pakistan))

Added translation using Weblate (Punjabi)

Translated using Weblate (Italian)

Currently translated at 100.0% (7 of 7 strings)

Co-authored-by: Paramjot singj <paramjotsingh2852@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translation: Kotatsu/plurals

* Translated using Weblate (Greek)

Currently translated at 99.8% (555 of 556 strings)

Co-authored-by: Alex Georgiou <alexandrosgeorgiou35@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translation: Kotatsu/Strings

---------

Co-authored-by: Alex Georgiou <alexandrosgeorgiou35@gmail.com>
Co-authored-by: Bela K <na0341-dev@posteo.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: Quentin VERDIER <quent1.verdier@gmail.com>
Co-authored-by: Deivinni Silva <deivinnimds3656@gmail.com>
Co-authored-by: Anon <anonymousprivate76@gmail.com>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: Judith Smith <i@razuritta.me>
Co-authored-by: Megat Al Zhahir Daniel <megatalzhahir@gmail.com>
Co-authored-by: Khaled <ashen.cv@gmail.com>
Co-authored-by: Theodore Visvikis <theodoros.visvikis@gmail.com>
Co-authored-by: Paramjot singj <paramjotsingh2852@gmail.com>
Co-authored-by: Paper Jack <paperjack@tutanota.com>
2024-01-15 13:47:21 +03:00
Alex Georgiou
799c0910ea Translated using Weblate (Greek)
Currently translated at 99.8% (555 of 556 strings)

Co-authored-by: Alex Georgiou <alexandrosgeorgiou35@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translation: Kotatsu/Strings
2024-01-14 18:18:56 +01:00
Paramjot singj
ed6802344a Added translation using Weblate (Punjabi (Pakistan))
Added translation using Weblate (Punjabi)

Translated using Weblate (Italian)

Currently translated at 100.0% (7 of 7 strings)

Co-authored-by: Paramjot singj <paramjotsingh2852@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translation: Kotatsu/plurals
2024-01-14 18:18:56 +01:00
Paper Jack
2d94688742 Translated using Weblate (Italian)
Currently translated at 100.0% (7 of 7 strings)

Co-authored-by: Paper Jack <paperjack@tutanota.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translation: Kotatsu/plurals
2024-01-14 18:18:56 +01:00
Paramjot singj
d0b44050f5 Translated using Weblate (Italian)
Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Paramjot singj <paramjotsingh2852@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2024-01-14 18:18:56 +01:00
Theodore Visvikis
486ae12d41 Translated using Weblate (Greek)
Currently translated at 99.8% (555 of 556 strings)

Co-authored-by: Theodore Visvikis <theodoros.visvikis@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translation: Kotatsu/Strings
2024-01-14 18:18:56 +01:00
Khaled
cb36f085d7 Translated using Weblate (Arabic)
Currently translated at 51.0% (284 of 556 strings)

Co-authored-by: Khaled <ashen.cv@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ar/
Translation: Kotatsu/Strings
2024-01-14 18:18:56 +01:00
大王叫我来巡山
5af42e5b6b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings
2024-01-14 18:18:56 +01:00
Megat Al Zhahir Daniel
160fa2c001 Translated using Weblate (Malay)
Currently translated at 56.1% (312 of 556 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (7 of 7 strings)

Added translation using Weblate (Malay)

Added translation using Weblate (Malay)

Co-authored-by: Megat Al Zhahir Daniel <megatalzhahir@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/ms/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ms/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2024-01-14 18:18:55 +01:00
Judith Smith
f9ba87b8cf Translated using Weblate (Chinese (Simplified))
Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: Judith Smith <i@razuritta.me>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
大王叫我来巡山
ee3cf08545 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
Anon
e0497b357b Translated using Weblate (Serbian)
Currently translated at 99.1% (551 of 556 strings)

Co-authored-by: Anon <anonymousprivate76@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sr/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
Deivinni Silva
6de08cd4fe Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: Deivinni Silva <deivinnimds3656@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
Quentin VERDIER
4760f1ea35 Translated using Weblate (French)
Currently translated at 100.0% (7 of 7 strings)

Translated using Weblate (French)

Currently translated at 96.2% (535 of 556 strings)

Co-authored-by: Quentin VERDIER <quent1.verdier@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2024-01-14 18:18:55 +01:00
gallegonovato
c64c4643bf Translated using Weblate (Spanish)
Currently translated at 100.0% (556 of 556 strings)

Translated using Weblate (Spanish)

Currently translated at 99.6% (554 of 556 strings)

Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
Bela K
7bfcdb387c Translated using Weblate (German)
Currently translated at 99.6% (554 of 556 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Bela K <na0341-dev@posteo.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translation: Kotatsu/Strings
2024-01-14 18:18:55 +01:00
Alex Georgiou
503fcf65fb Translated using Weblate (Greek)
Currently translated at 99.8% (555 of 556 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Translated using Weblate (Greek)

Currently translated at 45.8% (255 of 556 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (7 of 7 strings)

Translated using Weblate (English)

Currently translated at 100.0% (556 of 556 strings)

Co-authored-by: Alex Georgiou <alexandrosgeorgiou35@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/el/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/el/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2024-01-14 18:18:55 +01:00
Koitharu
54fb79dc98 Fix crash on start app update download 2024-01-12 18:18:04 +02:00
Koitharu
ea4c048029 Update parsers 2024-01-12 18:16:32 +02:00
Koitharu
badc826cd3 Hide search on unsupported sources 2024-01-12 18:15:00 +02:00
CakesTwix
f5ece8124e Translated using Weblate (Ukrainian)
Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: CakesTwix <cakestwix1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
Zero O
accdc41d6c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: Zero O <godarms2010@live.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
PacoteB2
819730984e Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: PacoteB2 <gop88662@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
Anton Prevrhal
01c404f9e5 Translated using Weblate (German)
Currently translated at 88.6% (491 of 554 strings)

Co-authored-by: Anton Prevrhal <anton.prevrhal@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
Anon
1fad686733 Translated using Weblate (Serbian)
Currently translated at 99.4% (551 of 554 strings)

Co-authored-by: Anon <anonymousprivate76@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sr/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
Сергій
396be6008d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: Сергій <sergiy.goncharuk.1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
ssantos
42f7846167 Translated using Weblate (Portuguese)
Currently translated at 100.0% (7 of 7 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: ssantos <ssantos@web.de>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/pt/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2024-01-11 19:26:30 +02:00
Макар Разин
dca56a43ee Translated using Weblate (Russian)
Currently translated at 100.0% (554 of 554 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (554 of 554 strings)

Co-authored-by: Макар Разин <makarrazin14@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
Translation: Kotatsu/Strings
2024-01-11 19:26:30 +02:00
Koitharu
cc91e56e1b Update parsers 2024-01-11 19:08:15 +02:00
Koitharu
627cf73d72 Action to mark manga as completed 2024-01-11 18:53:45 +02:00
Koitharu
514870f71c Filter exceptions reporting via ACRA 2024-01-07 15:51:16 +02:00
Koitharu
adffa800e8 Update parsers 2024-01-07 12:08:04 +02:00
103 changed files with 3414 additions and 1278 deletions

View File

@@ -1,11 +1,12 @@
## Kotatsu contribution guidelines
- If you want to fix bug or implement a new feature, that already mention in the [issues](https://github.com/KotatsuApp/Kotatsu/issues), please, assign this issue to you and/or comment about it.
- Whether you have to implement new feature, please, open an issue or discussion regarding it to ensure it will be accepted.
- Translations have to be managed using the [Weblate](https://hosted.weblate.org/engage/kotatsu/) platform.
- In case you want to add a new manga source, refer to the [parsers repository](https://github.com/KotatsuApp/kotatsu-parsers).
+ If you want to **fix bugs** or **implement new features** that **already have an [issue card](https://github.com/KotatsuApp/Kotatsu/issues):** please assign this issue to you and/or comment about it.
+ If you want to **implement a new feature:** open an issue or discussion regarding it to ensure it will be accepted.
+ **Translations** have to be managed using the [Weblate](https://hosted.weblate.org/engage/kotatsu/) platform.
+ In case you want to **add a new manga source,** refer to the [parsers repository](https://github.com/KotatsuApp/kotatsu-parsers).
Refactoring or some dev-faces improvements are also might be accepted, however please stick to the following principles:
- Performance matters. In the case of choosing between source code beauty and performance, performance should be a priority.
- Please, do not modify readme and other information files (except for typos).
- Avoid adding new dependencies unless required. APK size is important.
**Refactoring** or some **dev-faces improvements** might also be accepted. However, please stick to the following principles:
+ **Performance matters.** In the case of choosing between source code beauty and performance, performance should be a priority.
+ Please, **do not modify readme and other information files** (except for typos).
+ **Avoid adding new dependencies** unless required. APK size is important.

View File

@@ -16,8 +16,8 @@ android {
applicationId 'org.koitharu.kotatsu'
minSdk = 21
targetSdk = 34
versionCode = 611
versionName = '6.6'
versionCode = 616
versionName = '6.6.6'
generatedDensities = []
testInstrumentationRunner 'org.koitharu.kotatsu.HiltTestRunner'
ksp {
@@ -82,7 +82,7 @@ afterEvaluate {
}
dependencies {
//noinspection GradleDependency
implementation('com.github.KotatsuApp:kotatsu-parsers:e03d0efe71') {
implementation('com.github.KotatsuApp:kotatsu-parsers:7c871edbca') {
exclude group: 'org.json', module: 'json'
}
@@ -94,9 +94,9 @@ dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.activity:activity-ktx:1.8.2'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-service:2.6.2'
implementation 'androidx.lifecycle:lifecycle-process:2.6.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
implementation 'androidx.lifecycle:lifecycle-service:2.7.0'
implementation 'androidx.lifecycle:lifecycle-process:2.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
@@ -104,7 +104,7 @@ dependencies {
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha05'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.6.2'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.7.0'
implementation 'androidx.work:work-runtime:2.9.0'
//noinspection GradleDependency
@@ -138,8 +138,10 @@ dependencies {
implementation 'ch.acra:acra-http:5.11.3'
implementation 'ch.acra:acra-dialog:5.11.3'
compileOnly 'com.google.auto.service:auto-service-annotations:1.1.1'
ksp 'dev.zacsweers.autoservice:auto-service-ksp:1.1.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.13'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.json:json:20231013'

View File

@@ -36,7 +36,7 @@ class KotatsuApp : BaseApp() {
FragmentStrictMode.defaultPolicy = FragmentStrictMode.Policy.Builder()
.penaltyDeath()
.detectFragmentReuse()
// .detectWrongFragmentContainer() FIXME: migrate to ViewPager2
.detectWrongFragmentContainer()
.detectRetainInstanceUsage()
.detectSetUserVisibleHint()
.detectFragmentTagUsage()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
package org.koitharu.kotatsu.core
import android.content.Context
import com.google.auto.service.AutoService
import org.acra.builder.ReportBuilder
import org.acra.config.CoreConfiguration
import org.acra.config.ReportingAdministrator
@AutoService(ReportingAdministrator::class)
class ErrorReportingAdmin : ReportingAdministrator {
override fun shouldStartCollecting(
context: Context,
config: CoreConfiguration,
reportBuilder: ReportBuilder
): Boolean {
return reportBuilder.exception?.isDeadOs() != true
}
private fun Throwable.isDeadOs(): Boolean {
val className = javaClass.simpleName
return className == "DeadSystemException" || className == "DeadSystemRuntimeException" || cause?.isDeadOs() == true
}
}

View File

@@ -347,9 +347,13 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) }
var historySortOrder: ListSortOrder
get() = prefs.getEnumValue(KEY_HISTORY_ORDER, ListSortOrder.UPDATED)
get() = prefs.getEnumValue(KEY_HISTORY_ORDER, ListSortOrder.LAST_READ)
set(value) = prefs.edit { putEnumValue(KEY_HISTORY_ORDER, value) }
var allFavoritesSortOrder: ListSortOrder
get() = prefs.getEnumValue(KEY_FAVORITES_ORDER, ListSortOrder.NEWEST)
set(value) = prefs.edit { putEnumValue(KEY_FAVORITES_ORDER, value) }
val isRelatedMangaEnabled: Boolean
get() = prefs.getBoolean(KEY_RELATED_MANGA, true)
@@ -530,6 +534,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
const val KEY_READER_OPTIMIZE = "reader_optimize"
const val KEY_LOCAL_LIST_ORDER = "local_order"
const val KEY_HISTORY_ORDER = "history_order"
const val KEY_FAVORITES_ORDER = "fav_order"
const val KEY_WEBTOON_ZOOM = "webtoon_zoom"
const val KEY_PREFETCH_CONTENT = "prefetch_content"
const val KEY_APP_LOCALE = "app_locale"

View File

@@ -4,8 +4,10 @@ import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import androidx.annotation.AttrRes
import androidx.core.view.ancestors
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import org.koitharu.kotatsu.R
class FastScrollRecyclerView @JvmOverloads constructor(
@@ -15,6 +17,16 @@ class FastScrollRecyclerView @JvmOverloads constructor(
) : RecyclerView(context, attrs, defStyleAttr) {
val fastScroller = FastScroller(context, attrs)
var isVP2BugWorkaroundEnabled = false
set(value) {
field = value
if (value && isAttachedToWindow) {
checkIfInVP2()
} else if (!value) {
applyVP2Workaround = false
}
}
private var applyVP2Workaround = false
var isFastScrollerEnabled: Boolean = true
set(value) {
@@ -43,10 +55,29 @@ class FastScrollRecyclerView @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
fastScroller.attachRecyclerView(this)
if (isVP2BugWorkaroundEnabled) {
checkIfInVP2()
}
}
override fun onDetachedFromWindow() {
fastScroller.detachRecyclerView()
super.onDetachedFromWindow()
applyVP2Workaround = false
}
override fun isLayoutRequested(): Boolean {
return if (applyVP2Workaround) false else super.isLayoutRequested()
}
override fun requestLayout() {
super.requestLayout()
if (applyVP2Workaround && parent?.isLayoutRequested == true) {
parent?.requestLayout()
}
}
private fun checkIfInVP2() {
applyVP2Workaround = ancestors.any { it is ViewPager2 } == true
}
}

View File

@@ -0,0 +1,38 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.MenuItem
import android.view.View
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.MenuProvider
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
class PopupMenuMediator(
private val provider: MenuProvider,
) : View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
override fun onLongClick(v: View): Boolean {
val menu = PopupMenu(v.context, v)
provider.onCreateMenu(menu.menu, menu.menuInflater)
provider.onPrepareMenu(menu.menu)
if (!menu.menu.hasVisibleItems()) {
return false
}
menu.setOnMenuItemClickListener(this)
menu.setOnDismissListener(this)
menu.show()
return true
}
override fun onMenuItemClick(item: MenuItem): Boolean {
return provider.onMenuItemSelected(item)
}
override fun onDismiss(menu: PopupMenu) {
provider.onMenuClosed(menu.menu)
}
fun attach(view: View) {
view.setOnLongClickListener(this)
view.setOnContextClickListenerCompat(this)
}
}

View File

@@ -8,9 +8,11 @@ import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import androidx.annotation.Px
import androidx.annotation.StyleRes
import androidx.core.content.ContextCompat
import androidx.core.content.res.use
import androidx.core.graphics.ColorUtils
import com.google.android.material.R as materialR
fun Context.getThemeDrawable(
@AttrRes resId: Int,
@@ -75,3 +77,7 @@ fun TypedArray.getDrawableCompat(context: Context, index: Int): Drawable? {
val resId = getResourceId(index, 0)
return if (resId != 0) ContextCompat.getDrawable(context, resId) else null
}
@get:StyleRes
val DIALOG_THEME_CENTERED: Int
inline get() = materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered

View File

@@ -15,7 +15,9 @@ import androidx.core.view.descendants
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.button.MaterialButton
import com.google.android.material.progressindicator.BaseProgressIndicator
import com.google.android.material.slider.Slider
import com.google.android.material.tabs.TabLayout
@@ -161,3 +163,12 @@ val Toolbar.menuView: ActionMenuView?
menu // to call ensureMenu()
return children.firstNotNullOfOrNull { it as? ActionMenuView }
}
fun MaterialButton.setProgressIcon() {
val progressDrawable = CircularProgressDrawable(context)
progressDrawable.strokeWidth = resources.resolveDp(2f)
progressDrawable.setColorSchemeColors(currentTextColor)
progressDrawable.setTintList(textColors)
icon = progressDrawable
progressDrawable.start()
}

View File

@@ -8,12 +8,15 @@ import androidx.activity.OnBackPressedCallback
import androidx.appcompat.view.ActionMode
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.tabs.TabLayout
import org.koitharu.kotatsu.core.ui.util.ActionModeListener
import org.koitharu.kotatsu.core.util.ext.doOnExpansionsChanged
import org.koitharu.kotatsu.core.util.ext.setTabsEnabled
class ChaptersBottomSheetMediator(
private val behavior: BottomSheetBehavior<*>,
private val pager: ViewPager2,
private val tabLayout: TabLayout,
) : OnBackPressedCallback(false),
ActionModeListener,
OnLayoutChangeListener, View.OnGenericMotionListener {
@@ -75,8 +78,7 @@ class ChaptersBottomSheetMediator(
fun lock() {
lockCounter++
behavior.isDraggable = lockCounter <= 0
pager.isUserInputEnabled = lockCounter <= 0
updateLock()
}
fun unlock() {
@@ -84,7 +86,12 @@ class ChaptersBottomSheetMediator(
if (lockCounter < 0) {
lockCounter = 0
}
updateLock()
}
private fun updateLock() {
behavior.isDraggable = lockCounter <= 0
pager.isUserInputEnabled = lockCounter <= 0
tabLayout.setTabsEnabled(lockCounter <= 0)
}
}

View File

@@ -107,7 +107,7 @@ class DetailsActivity :
if (viewBinding.layoutBottom != null) {
val behavior = BottomSheetBehavior.from(checkNotNull(viewBinding.layoutBottom))
val bsMediator = ChaptersBottomSheetMediator(behavior, viewBinding.pager)
val bsMediator = ChaptersBottomSheetMediator(behavior, viewBinding.pager, viewBinding.tabs)
actionModeDelegate.addListener(bsMediator)
checkNotNull(viewBinding.layoutBsHeader).addOnLayoutChangeListener(bsMediator)
onBackPressedDispatcher.addCallback(bsMediator)
@@ -363,8 +363,9 @@ class DetailsActivity :
}
private fun initPager() {
viewBinding.pager.recyclerView?.isNestedScrollingEnabled = false
val adapter = DetailsPagerAdapter(this)
viewBinding.pager.recyclerView?.isNestedScrollingEnabled = false
viewBinding.pager.offscreenPageLimit = 1
viewBinding.pager.adapter = adapter
TabLayoutMediator(viewBinding.tabs, viewBinding.pager, adapter).attach()
viewBinding.pager.setCurrentItem(settings.defaultDetailsTab, false)

View File

@@ -59,6 +59,7 @@ class ChaptersFragment :
with(binding.recyclerViewChapters) {
checkNotNull(selectionController).attachToRecyclerView(this)
setHasFixedSize(true)
isNestedScrollingEnabled = false
adapter = chaptersAdapter
}
viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged)
@@ -83,6 +84,17 @@ class ChaptersFragment :
super.onDestroyView()
}
override fun onPause() {
// required for BottomSheetBehavior
requireViewBinding().recyclerViewChapters.isNestedScrollingEnabled = false
super.onPause()
}
override fun onResume() {
requireViewBinding().recyclerViewChapters.isNestedScrollingEnabled = true
super.onResume()
}
override fun onItemClick(item: ChapterListItem, view: View) {
if (selectionController?.onItemClick(item.chapter.id) == true) {
return

View File

@@ -88,6 +88,7 @@ class PagesFragment :
addItemDecoration(TypedListSpacingDecoration(context, false))
adapter = thumbnailsAdapter
setHasFixedSize(true)
isNestedScrollingEnabled = false
addOnLayoutChangeListener(spanResolver)
spanResolver?.setGridSize(settings.gridSize / 100f, this)
addOnScrollListener(ScrollListener().also { scrollListener = it })
@@ -112,6 +113,17 @@ class PagesFragment :
super.onDestroyView()
}
override fun onPause() {
// required for BottomSheetBehavior
requireViewBinding().recyclerView.isNestedScrollingEnabled = false
super.onPause()
}
override fun onResume() {
requireViewBinding().recyclerView.isNestedScrollingEnabled = true
super.onResume()
}
override fun onWindowInsetsChanged(insets: Insets) = Unit
override fun onItemClick(item: PageThumbnail, view: View) {

View File

@@ -7,6 +7,7 @@ import android.view.MenuItem
import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.settings.SettingsActivity
class DownloadsMenuProvider(
@@ -41,10 +42,8 @@ class DownloadsMenuProvider(
}
private fun confirmCancelAll() {
MaterialAlertDialogBuilder(
context,
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
).setTitle(R.string.cancel_all)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.cancel_all)
.setMessage(R.string.cancel_all_downloads_confirm)
.setIcon(R.drawable.ic_cancel_multiple)
.setNegativeButton(android.R.string.cancel, null)
@@ -54,10 +53,8 @@ class DownloadsMenuProvider(
}
private fun confirmRemoveCompleted() {
MaterialAlertDialogBuilder(
context,
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
).setTitle(R.string.remove_completed)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.remove_completed)
.setMessage(R.string.remove_completed_downloads_confirm)
.setIcon(R.drawable.ic_clear_all)
.setNegativeButton(android.R.string.cancel, null)

View File

@@ -1,9 +1,7 @@
package org.koitharu.kotatsu.explore.ui.adapter
import android.graphics.Color
import android.view.View
import androidx.lifecycle.LifecycleOwner
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R
@@ -15,10 +13,9 @@ import org.koitharu.kotatsu.core.ui.image.TrimTransformation
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.resolveDp
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
import org.koitharu.kotatsu.core.util.ext.setProgressIcon
import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ItemExploreButtonsBinding
@@ -30,7 +27,6 @@ import org.koitharu.kotatsu.explore.ui.model.MangaSourceItem
import org.koitharu.kotatsu.explore.ui.model.RecommendationsItem
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.parsers.model.Manga
import com.google.android.material.R as materialR
fun exploreButtonsAD(
clickListener: View.OnClickListener,
@@ -45,16 +41,7 @@ fun exploreButtonsAD(
bind {
if (item.isRandomLoading) {
val icon = CircularProgressDrawable(context)
icon.strokeWidth = context.resources.resolveDp(2f)
icon.setColorSchemeColors(
context.getThemeColor(
materialR.attr.colorPrimary,
Color.DKGRAY,
),
)
binding.buttonRandom.icon = icon
icon.start()
binding.buttonRandom.setProgressIcon()
} else {
binding.buttonRandom.setIconResource(R.drawable.ic_dice)
}

View File

@@ -95,6 +95,22 @@ abstract class FavouritesDao {
return findCoversImpl(query)
}
suspend fun findCovers(order: ListSortOrder, limit: Int): List<Cover> {
val orderBy = getOrderBy(order)
@Language("RoomSql")
val query = SimpleSQLiteQuery(
"SELECT manga.cover_url AS url, manga.source AS source FROM favourites " +
"LEFT JOIN manga ON favourites.manga_id = manga.manga_id " +
"WHERE deleted_at = 0 GROUP BY manga.manga_id ORDER BY $orderBy LIMIT ?",
arrayOf<Any>(limit),
)
return findCoversImpl(query)
}
@Query("SELECT COUNT(DISTINCT manga_id) FROM favourites WHERE deleted_at = 0")
abstract fun observeMangaCount(): Flow<Int>
@Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM favourites WHERE deleted_at = 0)")
abstract suspend fun findAllManga(): List<MangaEntity>
@@ -175,9 +191,10 @@ abstract class FavouritesDao {
ListSortOrder.RATING -> "manga.rating DESC"
ListSortOrder.NEWEST -> "favourites.created_at DESC"
ListSortOrder.ALPHABETIC -> "manga.title ASC"
ListSortOrder.NEW_CHAPTERS -> "(SELECT chapters_new FROM tracks WHERE tracks.manga_id = manga.manga_id) DESC"
ListSortOrder.UPDATED, // for legacy support
ListSortOrder.PROGRESS -> "(SELECT percent FROM history WHERE history.manga_id = manga.manga_id) DESC"
ListSortOrder.ALPHABETIC_REVERSE -> "manga.title DESC"
ListSortOrder.NEW_CHAPTERS -> "IFNULL((SELECT chapters_new FROM tracks WHERE tracks.manga_id = manga.manga_id), 0) DESC"
ListSortOrder.PROGRESS -> "IFNULL((SELECT percent FROM history WHERE history.manga_id = manga.manga_id), 0) DESC"
ListSortOrder.LAST_READ -> "IFNULL((SELECT updated_at FROM history WHERE history.manga_id = manga.manga_id), 0) DESC"
else -> throw IllegalArgumentException("Sort order $sortOrder is not supported")
}

View File

@@ -60,6 +60,11 @@ class FavouritesRepository @Inject constructor(
.flatMapLatest { order -> observeAll(categoryId, order) }
}
fun observeMangaCount(): Flow<Int> {
return db.getFavouritesDao().observeMangaCount()
.distinctUntilChanged()
}
fun observeCategories(): Flow<List<FavouriteCategory>> {
return db.getFavouriteCategoriesDao().observeAll().mapItems {
it.toFavouriteCategory()
@@ -89,6 +94,10 @@ class FavouritesRepository @Inject constructor(
}
}
suspend fun getAllFavoritesCovers(order: ListSortOrder, limit: Int): List<Cover> {
return db.getFavouritesDao().findCovers(order, limit)
}
fun observeCategory(id: Long): Flow<FavouriteCategory?> {
return db.getFavouriteCategoriesDao().observe(id)
.map { it?.toFavouriteCategory() }

View File

@@ -7,7 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import com.google.android.material.R as materialR
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
class CategoriesSelectionCallback(
private val recyclerView: RecyclerView,
@@ -75,7 +75,7 @@ class CategoriesSelectionCallback(
private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) {
val context = recyclerView.context
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setMessage(R.string.categories_delete_confirm)
.setTitle(R.string.remove_category)
.setIcon(R.drawable.ic_delete)

View File

@@ -76,7 +76,13 @@ class FavouriteCategoriesActivity :
}
}
override fun onItemClick(item: FavouriteCategory, view: View) {
override fun onItemClick(item: FavouriteCategory?, view: View) {
if (item == null) {
if (selectionController.count == 0) {
startActivity(FavouritesActivity.newIntent(view.context))
}
return
}
if (selectionController.onItemClick(item.id)) {
return
}
@@ -92,8 +98,12 @@ class FavouriteCategoriesActivity :
startActivity(intent)
}
override fun onItemLongClick(item: FavouriteCategory, view: View): Boolean {
return selectionController.onItemLongClick(item.id)
override fun onItemLongClick(item: FavouriteCategory?, view: View): Boolean {
return item != null && selectionController.onItemLongClick(item.id)
}
override fun onShowAllClick(isChecked: Boolean) {
viewModel.setAllCategoriesVisible(isChecked)
}
override fun onDragHandleTouch(holder: RecyclerView.ViewHolder): Boolean {

View File

@@ -5,9 +5,11 @@ import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
interface FavouriteCategoriesListListener : OnListItemClickListener<FavouriteCategory> {
interface FavouriteCategoriesListListener : OnListItemClickListener<FavouriteCategory?> {
fun onDragHandleTouch(holder: RecyclerView.ViewHolder): Boolean
fun onEditClick(item: FavouriteCategory, view: View)
fun onShowAllClick(isChecked: Boolean)
}

View File

@@ -5,17 +5,21 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.requireValue
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.domain.model.Cover
import org.koitharu.kotatsu.favourites.ui.categories.adapter.AllCategoriesListModel
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListModel
@@ -30,9 +34,13 @@ class FavouritesCategoriesViewModel @Inject constructor(
private var commitJob: Job? = null
val content = repository.observeCategoriesWithCovers()
.map { it.toUiList() }
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
val content = combine(
repository.observeCategoriesWithCovers(),
observeAllCategories(),
settings.observeAsFlow(AppSettings.KEY_ALL_FAVOURITES_VISIBLE) { isAllFavouritesVisible },
) { cats, all, showAll ->
cats.toUiList(all, showAll)
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
fun deleteCategories(ids: Set<Long>) {
launchJob(Dispatchers.Default) {
@@ -74,21 +82,46 @@ class FavouritesCategoriesViewModel @Inject constructor(
}
}
private fun Map<FavouriteCategory, List<Cover>>.toUiList(): List<ListModel> = map { (category, covers) ->
CategoryListModel(
mangaCount = covers.size,
covers = covers.take(3),
category = category,
isTrackerEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources,
)
}.ifEmpty {
listOf(
EmptyState(
icon = R.drawable.ic_empty_favourites,
textPrimary = R.string.text_empty_holder_primary,
textSecondary = R.string.empty_favourite_categories,
actionStringRes = 0,
private fun Map<FavouriteCategory, List<Cover>>.toUiList(
allFavorites: Pair<Int, List<Cover>>,
showAll: Boolean
): List<ListModel> {
if (isEmpty()) {
return listOf(
EmptyState(
icon = R.drawable.ic_empty_favourites,
textPrimary = R.string.text_empty_holder_primary,
textSecondary = R.string.empty_favourite_categories,
actionStringRes = 0,
),
)
}
val result = ArrayList<ListModel>(size + 1)
result.add(
AllCategoriesListModel(
mangaCount = allFavorites.first,
covers = allFavorites.second,
isVisible = showAll,
),
)
mapTo(result) { (category, covers) ->
CategoryListModel(
mangaCount = covers.size,
covers = covers.take(3),
category = category,
isTrackerEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources,
)
}
return result
}
private fun observeAllCategories(): Flow<Pair<Int, List<Cover>>> {
return settings.observeAsFlow(AppSettings.KEY_FAVORITES_ORDER) {
allFavoritesSortOrder
}.mapLatest { order ->
repository.getAllFavoritesCovers(order, limit = 3)
}.combine(repository.observeMangaCount()) { covers, count ->
count to covers
}
}
}

View File

@@ -0,0 +1,24 @@
package org.koitharu.kotatsu.favourites.ui.categories.adapter
import org.koitharu.kotatsu.favourites.domain.model.Cover
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
import org.koitharu.kotatsu.list.ui.model.ListModel
data class AllCategoriesListModel(
val mangaCount: Int,
val covers: List<Cover>,
val isVisible: Boolean,
) : ListModel {
override fun areItemsTheSame(other: ListModel): Boolean {
return other is AllCategoriesListModel
}
override fun getChangePayload(previousState: ListModel): Any? {
return if (previousState is AllCategoriesListModel && previousState.isVisible != isVisible) {
ListModelDiffCallback.PAYLOAD_CHECKED_CHANGED
} else {
super.getChangePayload(previousState)
}
}
}

View File

@@ -19,6 +19,7 @@ class CategoriesAdapter(
init {
addDelegate(ListItemType.CATEGORY_LARGE, categoryAD(coil, lifecycleOwner, onItemClickListener))
addDelegate(ListItemType.NAV_ITEM, allCategoriesAD(coil, lifecycleOwner, onItemClickListener))
addDelegate(ListItemType.STATE_EMPTY, emptyStateListAD(coil, lifecycleOwner, listListener))
addDelegate(ListItemType.STATE_LOADING, loadingStateAD())
}

View File

@@ -21,6 +21,7 @@ import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.source
import org.koitharu.kotatsu.databinding.ItemCategoriesAllBinding
import org.koitharu.kotatsu.databinding.ItemCategoryBinding
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesListListener
import org.koitharu.kotatsu.list.ui.model.ListModel
@@ -92,3 +93,68 @@ fun categoryAD(
}
}
}
fun allCategoriesAD(
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
clickListener: FavouriteCategoriesListListener,
) = adapterDelegateViewBinding<AllCategoriesListModel, ListModel, ItemCategoriesAllBinding>(
{ inflater, parent -> ItemCategoriesAllBinding.inflate(inflater, parent, false) },
) {
val eventListener = OnClickListener { v ->
if (v.id == R.id.imageView_visible) {
clickListener.onShowAllClick(!item.isVisible)
} else {
clickListener.onItemClick(null, v)
}
}
val backgroundColor = context.getThemeColor(android.R.attr.colorBackground)
ImageViewCompat.setImageTintList(
binding.imageViewCover3,
ColorStateList.valueOf(ColorUtils.setAlphaComponent(backgroundColor, 153)),
)
ImageViewCompat.setImageTintList(
binding.imageViewCover2,
ColorStateList.valueOf(ColorUtils.setAlphaComponent(backgroundColor, 76)),
)
binding.imageViewCover2.backgroundTintList =
ColorStateList.valueOf(ColorUtils.setAlphaComponent(backgroundColor, 76))
binding.imageViewCover3.backgroundTintList =
ColorStateList.valueOf(ColorUtils.setAlphaComponent(backgroundColor, 153))
val fallback = ColorDrawable(Color.TRANSPARENT)
val coverViews = arrayOf(binding.imageViewCover1, binding.imageViewCover2, binding.imageViewCover3)
val crossFadeDuration = context.getAnimationDuration(R.integer.config_defaultAnimTime).toInt()
itemView.setOnClickListener(eventListener)
binding.imageViewVisible.setOnClickListener(eventListener)
bind {
binding.textViewSubtitle.text = if (item.mangaCount == 0) {
getString(R.string.empty)
} else {
context.resources.getQuantityString(
R.plurals.items,
item.mangaCount,
item.mangaCount,
)
}
binding.imageViewVisible.setImageResource(
if (item.isVisible) {
R.drawable.ic_eye
} else {
R.drawable.ic_eye_off
},
)
repeat(coverViews.size) { i ->
val cover = item.covers.getOrNull(i)
coverViews[i].newImageRequest(lifecycleOwner, cover?.url)?.run {
placeholder(R.drawable.ic_placeholder)
fallback(fallback)
source(cover?.mangaSource)
crossfade(crossFadeDuration * (i + 1))
error(R.drawable.ic_error_placeholder)
allowRgb565(true)
enqueueWith(coil)
}
}
}
}

View File

@@ -4,7 +4,7 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
data class FavouriteTabModel(
val id: Long,
val title: String,
val title: String?,
) : ListModel {
override fun areItemsTheSame(other: ListModel): Boolean {

View File

@@ -0,0 +1,53 @@
package org.koitharu.kotatsu.favourites.ui.container
import android.content.Context
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
class FavouriteTabPopupMenuProvider(
private val context: Context,
private val viewModel: FavouritesContainerViewModel,
private val categoryId: Long
) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
val menuResId = if (categoryId == NO_ID) {
R.menu.popup_fav_tab_all
} else {
R.menu.popup_fav_tab
}
menuInflater.inflate(menuResId, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.action_hide -> viewModel.hide(categoryId)
R.id.action_edit -> context.startActivity(
FavouritesCategoryEditActivity.newIntent(context, categoryId),
)
R.id.action_delete -> confirmDelete()
else -> return false
}
return true
}
private fun confirmDelete() {
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setMessage(R.string.categories_delete_confirm)
.setTitle(R.string.remove_category)
.setIcon(R.drawable.ic_delete)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.remove) { _, _ ->
viewModel.deleteCategory(categoryId)
}.show()
}
}

View File

@@ -1,33 +1,46 @@
package org.koitharu.kotatsu.favourites.ui.container
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.recyclerview.widget.AdapterListUpdateCallback
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.viewpager2.adapter.FragmentStateAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.flow.FlowCollector
import org.koitharu.kotatsu.core.util.ContinuationResumeRunnable
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment
import org.koitharu.kotatsu.parsers.util.replaceWith
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
import kotlin.coroutines.suspendCoroutine
@Suppress("DEPRECATION")
class FavouritesContainerAdapter(
fm: FragmentManager
) : FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT),
class FavouritesContainerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment),
FlowCollector<List<FavouriteTabModel>> {
private val dataSet = ArrayList<FavouriteTabModel>()
private val differ = AsyncListDiffer(
AdapterListUpdateCallback(this),
AsyncDifferConfig.Builder(ListModelDiffCallback<FavouriteTabModel>())
.setBackgroundThreadExecutor(Dispatchers.Default.limitedParallelism(2).asExecutor())
.build(),
)
override fun getCount(): Int = dataSet.size
override fun getItemCount(): Int = differ.currentList.size
override fun getItem(position: Int): Fragment {
val item = dataSet[position]
override fun getItemId(position: Int): Long {
return differ.currentList[position].id
}
override fun containsItem(itemId: Long): Boolean {
return differ.currentList.any { x -> x.id == itemId }
}
override fun createFragment(position: Int): Fragment {
val item = differ.currentList[position]
return FavouritesListFragment.newInstance(item.id)
}
override fun getPageTitle(position: Int): CharSequence {
return dataSet[position].title
override suspend fun emit(value: List<FavouriteTabModel>) = suspendCoroutine { cont ->
differ.submitList(value, ContinuationResumeRunnable(cont))
}
override suspend fun emit(value: List<FavouriteTabModel>) {
dataSet.replaceWith(value)
notifyDataSetChanged()
}
fun getItem(position: Int): FavouriteTabModel = differ.currentList[position]
}

View File

@@ -1,55 +0,0 @@
package org.koitharu.kotatsu.favourites.ui.container
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.AdapterListUpdateCallback
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.flow.FlowCollector
import org.koitharu.kotatsu.core.util.ContinuationResumeRunnable
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
import kotlin.coroutines.suspendCoroutine
// FIXME migrate to ViewPager2 in FavouritesContainerFragment
class FavouritesContainerAdapter2(fragment: Fragment) :
FragmentStateAdapter(fragment.childFragmentManager, fragment.viewLifecycleOwner.lifecycle),
TabConfigurationStrategy,
FlowCollector<List<FavouriteTabModel>> {
private val differ = AsyncListDiffer(
AdapterListUpdateCallback(this),
AsyncDifferConfig.Builder(ListModelDiffCallback<FavouriteTabModel>())
.setBackgroundThreadExecutor(Dispatchers.Default.limitedParallelism(2).asExecutor())
.build(),
)
override fun getItemCount(): Int = differ.currentList.size
override fun getItemId(position: Int): Long {
return differ.currentList[position].id
}
override fun containsItem(itemId: Long): Boolean {
return differ.currentList.any { x -> x.id == itemId }
}
override fun createFragment(position: Int): Fragment {
val item = differ.currentList[position]
return FavouritesListFragment.newInstance(item.id)
}
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
val item = differ.currentList[position]
tab.text = item.title
tab.tag = item
}
override suspend fun emit(value: List<FavouriteTabModel>) = suspendCoroutine { cont ->
differ.submitList(value, ContinuationResumeRunnable(cont))
}
}

View File

@@ -12,14 +12,18 @@ import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import coil.ImageLoader
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.util.ActionModeListener
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.recyclerView
import org.koitharu.kotatsu.core.util.ext.setTabsEnabled
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.databinding.FragmentFavouritesContainerBinding
@@ -43,15 +47,21 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesContainerBind
override fun onViewBindingCreated(binding: FragmentFavouritesContainerBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState)
val adapter = FavouritesContainerAdapter(childFragmentManager)
binding.pager.adapter = adapter
binding.tabs.setupWithViewPager(binding.pager)
val pagerAdapter = FavouritesContainerAdapter(this)
binding.pager.adapter = pagerAdapter
binding.pager.offscreenPageLimit = 1
binding.pager.recyclerView?.isNestedScrollingEnabled = false
TabLayoutMediator(
binding.tabs,
binding.pager,
FavouritesTabConfigurationStrategy(pagerAdapter, viewModel),
).attach()
binding.stubEmpty.setOnInflateListener(this)
actionModeDelegate.addListener(this)
viewModel.categories.observe(viewLifecycleOwner, adapter)
viewModel.categories.observe(viewLifecycleOwner, pagerAdapter)
viewModel.isEmpty.observe(viewLifecycleOwner, ::onEmptyStateChanged)
addMenuProvider(FavouritesContainerMenuProvider(binding.root.context))
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.pager))
}
override fun onDestroyView() {

View File

@@ -4,30 +4,80 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.mapItems
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.ui.util.ReversibleHandle
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
import javax.inject.Inject
@HiltViewModel
class FavouritesContainerViewModel @Inject constructor(
favouritesRepository: FavouritesRepository,
private val settings: AppSettings,
private val favouritesRepository: FavouritesRepository,
) : BaseViewModel() {
val onActionDone = MutableEventFlow<ReversibleAction>()
private val categoriesStateFlow = favouritesRepository.observeCategoriesForLibrary()
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null)
val categories = categoriesStateFlow.filterNotNull()
.mapItems { FavouriteTabModel(it.id, it.title) }
.distinctUntilChanged()
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
val categories = combine(
categoriesStateFlow.filterNotNull(),
observeAllFavouritesVisibility(),
) { list, showAll ->
list.toUi(showAll)
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList())
val isEmpty = categoriesStateFlow.map {
it?.isEmpty() == true
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false)
private fun List<FavouriteCategory>.toUi(showAll: Boolean): List<FavouriteTabModel> {
if (isEmpty()) {
return emptyList()
}
val result = ArrayList<FavouriteTabModel>(if (showAll) size + 1 else size)
if (showAll) {
result.add(FavouriteTabModel(NO_ID, null))
}
mapTo(result) { FavouriteTabModel(it.id, it.title) }
return result
}
fun hide(categoryId: Long) {
launchJob(Dispatchers.Default) {
if (categoryId == NO_ID) {
settings.isAllFavouritesVisible = false
} else {
favouritesRepository.updateCategory(categoryId, isVisibleInLibrary = false)
val reverse = ReversibleHandle {
favouritesRepository.updateCategory(categoryId, isVisibleInLibrary = true)
}
onActionDone.call(ReversibleAction(R.string.category_hidden_done, reverse))
}
}
}
fun deleteCategory(categoryId: Long) {
launchJob(Dispatchers.Default) {
favouritesRepository.removeCategories(setOf(categoryId))
}
}
private fun observeAllFavouritesVisibility() = settings.observeAsFlow(
key = AppSettings.KEY_ALL_FAVOURITES_VISIBLE,
valueProducer = { isAllFavouritesVisible },
)
}

View File

@@ -0,0 +1,19 @@
package org.koitharu.kotatsu.favourites.ui.container
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator.TabConfigurationStrategy
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.util.PopupMenuMediator
class FavouritesTabConfigurationStrategy(
private val adapter: FavouritesContainerAdapter,
private val viewModel: FavouritesContainerViewModel,
) : TabConfigurationStrategy {
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
val item = adapter.getItem(position)
tab.text = item.title ?: tab.view.context.getString(R.string.all_favourites)
tab.tag = item
PopupMenuMediator(FavouriteTabPopupMenuProvider(tab.view.context, viewModel, item.id)).attach(tab.view)
}
}

View File

@@ -7,10 +7,10 @@ import android.view.View
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal
import org.koitharu.kotatsu.core.util.ext.withArgs
import org.koitharu.kotatsu.databinding.FragmentListBinding
@@ -30,9 +30,7 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis
override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState)
if (viewModel.categoryId != NO_ID) {
addMenuProvider(FavouritesListMenuProvider(binding.root.context, viewModel))
}
binding.recyclerView.isVP2BugWorkaroundEnabled = true
}
override fun onScrolledToEnd() = Unit
@@ -73,6 +71,18 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis
true
}
R.id.action_mark_current -> {
MaterialAlertDialogBuilder(context ?: return false)
.setTitle(item.title)
.setMessage(R.string.mark_as_completed_prompt)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok) { _, _ ->
viewModel.markAsRead(selectedItems)
mode.finish()
}.show()
true
}
else -> super.onActionItemClicked(controller, mode, item)
}
}

View File

@@ -1,30 +0,0 @@
package org.koitharu.kotatsu.favourites.ui.list
import android.content.Context
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
class FavouritesListMenuProvider(
private val context: Context,
private val viewModel: FavouritesListViewModel,
) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.opt_favourites, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_edit -> {
context.startActivity(FavouritesCategoryEditActivity.newIntent(context, viewModel.categoryId))
true
}
else -> false
}
}
}

View File

@@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
@@ -21,6 +23,7 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
import org.koitharu.kotatsu.history.domain.MarkAsReadUseCase
import org.koitharu.kotatsu.list.domain.ListExtraProvider
import org.koitharu.kotatsu.list.domain.ListSortOrder
import org.koitharu.kotatsu.list.ui.MangaListViewModel
@@ -28,6 +31,7 @@ import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.list.ui.model.toErrorState
import org.koitharu.kotatsu.list.ui.model.toUi
import org.koitharu.kotatsu.parsers.model.Manga
import javax.inject.Inject
@HiltViewModel
@@ -35,31 +39,37 @@ class FavouritesListViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val repository: FavouritesRepository,
private val listExtraProvider: ListExtraProvider,
private val markAsReadUseCase: MarkAsReadUseCase,
settings: AppSettings,
downloadScheduler: DownloadWorker.Scheduler,
) : MangaListViewModel(settings, downloadScheduler) {
val categoryId: Long = savedStateHandle[ARG_CATEGORY_ID] ?: NO_ID
private val refreshTrigger = MutableStateFlow(Any())
override val listMode = settings.observeAsFlow(AppSettings.KEY_LIST_MODE_FAVORITES) { favoritesListMode }
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, settings.favoritesListMode)
val sortOrder: StateFlow<ListSortOrder?> = if (categoryId == NO_ID) {
MutableStateFlow(null)
settings.observeAsFlow(AppSettings.KEY_FAVORITES_ORDER) {
allFavoritesSortOrder
}
} else {
repository.observeCategory(categoryId)
.map { it?.order }
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null)
}
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null)
override val content = combine(
if (categoryId == NO_ID) {
repository.observeAll(ListSortOrder.NEWEST)
sortOrder.filterNotNull().flatMapLatest {
repository.observeAll(it)
}
} else {
repository.observeAll(categoryId)
},
listMode,
) { list, mode ->
refreshTrigger,
) { list, mode, _ ->
when {
list.isEmpty() -> listOf(
EmptyState(
@@ -80,10 +90,19 @@ class FavouritesListViewModel @Inject constructor(
emit(listOf(it.toErrorState(canRetry = false)))
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
override fun onRefresh() = Unit
override fun onRefresh() {
refreshTrigger.value = Any()
}
override fun onRetry() = Unit
fun markAsRead(items: Set<Manga>) {
launchLoadingJob(Dispatchers.Default) {
markAsReadUseCase(items)
onRefresh()
}
}
fun removeFromFavourites(ids: Set<Long>) {
if (ids.isEmpty()) {
return

View File

@@ -35,11 +35,12 @@ abstract class HistoryDao {
fun observeAll(order: ListSortOrder): Flow<List<HistoryWithManga>> {
val orderBy = when (order) {
ListSortOrder.UPDATED -> "history.updated_at DESC"
ListSortOrder.LAST_READ -> "history.updated_at DESC"
ListSortOrder.NEWEST -> "history.created_at DESC"
ListSortOrder.PROGRESS -> "history.percent DESC"
ListSortOrder.ALPHABETIC -> "manga.title"
ListSortOrder.NEW_CHAPTERS -> "(SELECT chapters_new FROM tracks WHERE tracks.manga_id = manga.manga_id) DESC"
ListSortOrder.ALPHABETIC_REVERSE -> "manga.title DESC"
ListSortOrder.NEW_CHAPTERS -> "IFNULL((SELECT chapters_new FROM tracks WHERE tracks.manga_id = manga.manga_id), 0) DESC"
else -> throw IllegalArgumentException("Sort order $order is not supported")
}

View File

@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.db.entity.toMangaTags
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.findById
import org.koitharu.kotatsu.core.model.isLocal
import org.koitharu.kotatsu.core.model.isNsfw
import org.koitharu.kotatsu.core.parser.MangaDataRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.util.ReversibleHandle
@@ -161,7 +162,7 @@ class HistoryRepository @Inject constructor(
}
fun shouldSkip(manga: Manga): Boolean {
return manga.isNsfw && settings.isHistoryExcludeNsfw || settings.isIncognitoModeEnabled
return ((manga.source.isNsfw() || manga.isNsfw) && settings.isHistoryExcludeNsfw) || settings.isIncognitoModeEnabled
}
fun observeShouldSkip(manga: Manga): Flow<Boolean> {

View File

@@ -0,0 +1,49 @@
package org.koitharu.kotatsu.history.domain
import dagger.Reusable
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.history.data.HistoryRepository
import org.koitharu.kotatsu.parsers.model.Manga
import javax.inject.Inject
@Reusable
class MarkAsReadUseCase @Inject constructor(
private val historyRepository: HistoryRepository,
private val mangaRepositoryFactory: MangaRepository.Factory,
) {
suspend operator fun invoke(manga: Manga) {
val repo = mangaRepositoryFactory.create(manga.source)
val details = if (manga.chapters.isNullOrEmpty()) {
repo.getDetails(manga)
} else {
manga
}
val lastChapter = checkNotNull(details.chapters).last()
val pages = repo.getPages(lastChapter)
historyRepository.addOrUpdate(
manga = details,
chapterId = lastChapter.id,
page = pages.lastIndex,
scroll = 0,
percent = 1f,
)
}
suspend operator fun invoke(manga: Collection<Manga>) {
when (manga.size) {
0 -> Unit
1 -> invoke(manga.first())
else -> supervisorScope {
manga.map {
launch {
invoke(it)
}
}.joinAll()
}
}
}
}

View File

@@ -5,6 +5,7 @@ import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.view.ActionMode
import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.os.NetworkManageIntent
@@ -54,6 +55,18 @@ class HistoryListFragment : MangaListFragment() {
true
}
R.id.action_mark_current -> {
MaterialAlertDialogBuilder(context ?: return false)
.setTitle(item.title)
.setMessage(R.string.mark_as_completed_prompt)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok) { _, _ ->
viewModel.markAsRead(selectedItems)
mode.finish()
}.show()
true
}
else -> super.onActionItemClicked(controller, mode, item)
}
}

View File

@@ -8,6 +8,7 @@ import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
@@ -36,7 +37,7 @@ class HistoryListMenuProvider(
private fun showClearHistoryDialog() {
val selectionListener = RememberSelectionDialogListener(2)
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.clear_history)
.setSingleChoiceItems(
arrayOf(

View File

@@ -25,6 +25,7 @@ import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.core.util.ext.onFirst
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
import org.koitharu.kotatsu.history.data.HistoryRepository
import org.koitharu.kotatsu.history.domain.MarkAsReadUseCase
import org.koitharu.kotatsu.history.domain.model.MangaWithHistory
import org.koitharu.kotatsu.list.domain.ListExtraProvider
import org.koitharu.kotatsu.list.domain.ListSortOrder
@@ -39,6 +40,7 @@ import org.koitharu.kotatsu.list.ui.model.toGridModel
import org.koitharu.kotatsu.list.ui.model.toListDetailedModel
import org.koitharu.kotatsu.list.ui.model.toListModel
import org.koitharu.kotatsu.local.data.LocalMangaRepository
import org.koitharu.kotatsu.parsers.model.Manga
import java.time.Instant
import javax.inject.Inject
@@ -48,6 +50,7 @@ class HistoryListViewModel @Inject constructor(
settings: AppSettings,
private val extraProvider: ListExtraProvider,
private val localMangaRepository: LocalMangaRepository,
private val markAsReadUseCase: MarkAsReadUseCase,
networkState: NetworkState,
downloadScheduler: DownloadWorker.Scheduler,
) : MangaListViewModel(settings, downloadScheduler) {
@@ -121,6 +124,12 @@ class HistoryListViewModel @Inject constructor(
}
}
fun markAsRead(items: Set<Manga>) {
launchLoadingJob(Dispatchers.Default) {
markAsReadUseCase(items)
}
}
private suspend fun mapList(
list: List<MangaWithHistory>,
grouped: Boolean,
@@ -163,7 +172,7 @@ class HistoryListViewModel @Inject constructor(
}
private fun MangaHistory.header(order: ListSortOrder): ListHeader? = when (order) {
ListSortOrder.UPDATED -> ListHeader(calculateTimeAgo(updatedAt))
ListSortOrder.LAST_READ -> ListHeader(calculateTimeAgo(updatedAt))
ListSortOrder.NEWEST -> ListHeader(calculateTimeAgo(createdAt))
ListSortOrder.PROGRESS -> ListHeader(
when (percent) {
@@ -175,6 +184,7 @@ class HistoryListViewModel @Inject constructor(
)
ListSortOrder.ALPHABETIC,
ListSortOrder.ALPHABETIC_REVERSE,
ListSortOrder.RELEVANCE,
ListSortOrder.NEW_CHAPTERS,
ListSortOrder.RATING -> null

View File

@@ -9,21 +9,22 @@ enum class ListSortOrder(
@StringRes val titleResId: Int,
) {
UPDATED(R.string.updated),
NEWEST(R.string.order_added),
PROGRESS(R.string.progress),
ALPHABETIC(R.string.by_name),
ALPHABETIC_REVERSE(R.string.by_name_reverse),
RATING(R.string.by_rating),
RELEVANCE(R.string.by_relevance),
NEW_CHAPTERS(R.string.new_chapters),
LAST_READ(R.string.last_read),
;
fun isGroupingSupported() = this == UPDATED || this == NEWEST || this == PROGRESS
fun isGroupingSupported() = this == LAST_READ || this == NEWEST || this == PROGRESS
companion object {
val HISTORY: Set<ListSortOrder> = EnumSet.of(UPDATED, NEWEST, PROGRESS, ALPHABETIC, NEW_CHAPTERS)
val FAVORITES: Set<ListSortOrder> = EnumSet.of(ALPHABETIC, NEWEST, RATING, NEW_CHAPTERS, PROGRESS)
val HISTORY: Set<ListSortOrder> = EnumSet.of(LAST_READ, NEWEST, PROGRESS, ALPHABETIC, ALPHABETIC_REVERSE, NEW_CHAPTERS)
val FAVORITES: Set<ListSortOrder> = EnumSet.of(ALPHABETIC, ALPHABETIC_REVERSE, NEWEST, RATING, NEW_CHAPTERS, PROGRESS, LAST_READ)
val SUGGESTIONS: Set<ListSortOrder> = EnumSet.of(RELEVANCE)
operator fun invoke(value: String, fallback: ListSortOrder) = entries.find(value) ?: fallback

View File

@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.require
import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
import org.koitharu.kotatsu.list.domain.ListSortOrder
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import javax.inject.Inject
@@ -65,7 +66,11 @@ class ListConfigViewModel @Inject constructor(
val value = getSortOrders()?.getOrNull(position) ?: return
when (section) {
is ListConfigSection.Favorites -> launchJob {
favouritesRepository.setCategoryOrder(section.categoryId, value)
if (section.categoryId == NO_ID) {
settings.allFavoritesSortOrder = value
} else {
favouritesRepository.setCategoryOrder(section.categoryId, value)
}
}
ListConfigSection.General -> Unit
@@ -75,9 +80,13 @@ class ListConfigViewModel @Inject constructor(
}
}
private fun getCategorySortOrder(id: Long): ListSortOrder = runBlocking {
private fun getCategorySortOrder(id: Long): ListSortOrder = if (id == NO_ID) {
settings.allFavoritesSortOrder
} else runBlocking {
runCatchingCancellable {
favouritesRepository.getCategory(id).order
}.getOrDefault(ListSortOrder.NEWEST)
}.getOrElse {
settings.allFavoritesSortOrder
}
}
}

View File

@@ -47,7 +47,7 @@ class SingleMangaImporter @Inject constructor(
val contentResolver = storageManager.contentResolver
val name = contentResolver.resolveName(uri) ?: throw IOException("Cannot fetch name from uri: $uri")
if (!hasCbzExtension(name)) {
throw UnsupportedFileException("Unsupported file on $uri")
throw UnsupportedFileException("Unsupported file $name on $uri")
}
val dest = File(getOutputDir(), name)
runInterruptible {

View File

@@ -9,13 +9,20 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.AlertDialogFragment
import org.koitharu.kotatsu.core.util.ext.tryLaunch
import org.koitharu.kotatsu.databinding.DialogImportBinding
import org.koitharu.kotatsu.local.data.LocalStorageManager
import javax.inject.Inject
@AndroidEntryPoint
class ImportDialogFragment : AlertDialogFragment<DialogImportBinding>(), View.OnClickListener {
@Inject
lateinit var storageManager: LocalStorageManager
private val importFileCall = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) {
startImport(it)
}
@@ -55,6 +62,9 @@ class ImportDialogFragment : AlertDialogFragment<DialogImportBinding>(), View.On
if (uris.isEmpty()) {
return
}
uris.forEach {
storageManager.takePermissions(it)
}
val ctx = requireContext()
ImportWorker.start(ctx, uris)
Toast.makeText(ctx, R.string.import_will_start_soon, Toast.LENGTH_LONG).show()

View File

@@ -26,6 +26,15 @@ import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
class LocalListFragment : MangaListFragment(), FilterOwner {
init {
withArgs(1) {
putSerializable(
RemoteListFragment.ARG_SOURCE,
MangaSource.LOCAL,
) // required by FilterCoordinator
}
}
override val viewModel by viewModels<LocalListViewModel>()
override val filter: MangaFilter
@@ -97,14 +106,4 @@ class LocalListFragment : MangaListFragment(), FilterOwner {
Snackbar.LENGTH_SHORT,
).show()
}
companion object {
fun newInstance() = LocalListFragment().withArgs(1) {
putSerializable(
RemoteListFragment.ARG_SOURCE,
MangaSource.LOCAL,
) // required by FilterCoordinator
}
}
}

View File

@@ -134,13 +134,13 @@ class MainNavigationDelegate(
private fun onNavigationItemSelected(@IdRes itemId: Int): Boolean {
return setPrimaryFragment(
when (itemId) {
R.id.nav_history -> HistoryListFragment()
R.id.nav_favorites -> FavouritesContainerFragment()
R.id.nav_explore -> ExploreFragment()
R.id.nav_feed -> FeedFragment()
R.id.nav_local -> LocalListFragment.newInstance()
R.id.nav_suggestions -> SuggestionsFragment()
R.id.nav_bookmarks -> BookmarksFragment()
R.id.nav_history -> HistoryListFragment::class.java
R.id.nav_favorites -> FavouritesContainerFragment::class.java
R.id.nav_explore -> ExploreFragment::class.java
R.id.nav_feed -> FeedFragment::class.java
R.id.nav_local -> LocalListFragment::class.java
R.id.nav_suggestions -> SuggestionsFragment::class.java
R.id.nav_bookmarks -> BookmarksFragment::class.java
else -> return false
},
)
@@ -157,16 +157,17 @@ class MainNavigationDelegate(
else -> 0
}
private fun setPrimaryFragment(fragment: Fragment): Boolean {
if (fragmentManager.isStateSaved) {
private fun setPrimaryFragment(fragmentClass: Class<out Fragment>): Boolean {
if (fragmentManager.isStateSaved || fragmentClass.isInstance(primaryFragment)) {
return false
}
val fragment = instantiateFragment(fragmentClass)
fragment.enterTransition = MaterialFadeThrough()
fragmentManager.beginTransaction()
.setReorderingAllowed(true)
.replace(R.id.container, fragment, TAG_PRIMARY)
.replace(R.id.container, fragmentClass, null, TAG_PRIMARY)
.runOnCommit { onFragmentChanged(fragment, fromUser = true) }
.commit()
onFragmentChanged(fragment, fromUser = true)
return true
}
@@ -182,6 +183,11 @@ class MainNavigationDelegate(
}
}
private fun instantiateFragment(fragmentClass: Class<out Fragment>): Fragment {
val classLoader = navBar.context.classLoader
return fragmentManager.fragmentFactory.instantiate(classLoader, fragmentClass.name)
}
private fun observeSettings(lifecycleOwner: LifecycleOwner) {
settings.observe()
.filter { x -> x == AppSettings.KEY_TRACKER_ENABLED || x == AppSettings.KEY_SUGGESTIONS }

View File

@@ -201,7 +201,7 @@ class PageLoader @Inject constructor(
private suspend fun loadPageImpl(page: MangaPage, progress: MutableStateFlow<Float>): Uri = semaphore.withPermit {
val pageUrl = getPageUrl(page)
check(pageUrl.isNotBlank()) { "Cannot obtain full image url" }
check(pageUrl.isNotBlank()) { "Cannot obtain full image url for $page" }
val uri = Uri.parse(pageUrl)
return if (uri.isZipUri()) {
if (uri.scheme == URI_SCHEME_ZIP) {

View File

@@ -10,7 +10,6 @@ import android.transition.TransitionManager
import android.transition.TransitionSet
import android.view.Gravity
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
@@ -40,6 +39,7 @@ import org.koitharu.kotatsu.core.parser.MangaIntent
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.widgets.ZoomControl
import org.koitharu.kotatsu.core.util.GridTouchHelper
import org.koitharu.kotatsu.core.util.IdlingDetector
@@ -140,6 +140,7 @@ class ReaderActivity :
viewModel.content.observe(this) {
onLoadingStateChanged(viewModel.isLoading.value)
}
viewModel.incognitoMode.observe(this, MenuInvalidator(this))
viewModel.isScreenshotsBlockEnabled.observe(this, this::setWindowSecure)
viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn)
viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged)
@@ -152,6 +153,7 @@ class ReaderActivity :
viewModel.isZoomControlsEnabled.observe(this) {
viewBinding.zoomControl.isVisible = it
}
addMenuProvider(ReaderTopMenuProvider(this, viewModel))
}
override fun getParentActivityIntent(): Intent? {
@@ -190,21 +192,12 @@ class ReaderActivity :
viewBinding.slider.isRtl = mode == ReaderMode.REVERSED
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.opt_reader_top, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_settings -> {
startActivity(SettingsActivity.newReaderSettingsIntent(this))
}
R.id.action_chapters -> {
ChaptersSheet.show(supportFragmentManager)
}
R.id.action_pages_thumbs -> {
val state = viewModel.getCurrentState() ?: return false
PagesThumbnailsSheet.show(

View File

@@ -0,0 +1,48 @@
package org.koitharu.kotatsu.reader.ui
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
class ReaderTopMenuProvider(
private val activity: ReaderActivity,
private val viewModel: ReaderViewModel,
) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.opt_reader_top, menu)
}
override fun onPrepareMenu(menu: Menu) {
menu.findItem(R.id.action_incognito)?.isVisible = viewModel.incognitoMode.value
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_chapters -> {
ChaptersSheet.show(activity.supportFragmentManager)
true
}
R.id.action_incognito -> {
showIncognitoModeDialog()
true
}
else -> false
}
}
private fun showIncognitoModeDialog() {
MaterialAlertDialogBuilder(activity, DIALOG_THEME_CENTERED)
.setIcon(R.drawable.ic_incognito)
.setTitle(R.string.incognito_mode)
.setMessage(R.string.incognito_mode_hint)
.setPositiveButton(R.string.got_it, null)
.show()
}
}

View File

@@ -96,6 +96,12 @@ class ReaderViewModel @Inject constructor(
val onShowToast = MutableEventFlow<Int>()
val uiState = MutableStateFlow<ReaderUiState?>(null)
val incognitoMode = if (isIncognito) {
MutableStateFlow(true)
} else mangaFlow.map {
it != null && historyRepository.shouldSkip(it)
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false)
val content = MutableStateFlow(ReaderContent(emptyList(), null))
val manga: MangaDetails?
get() = mangaData.value
@@ -256,7 +262,7 @@ class ReaderViewModel @Inject constructor(
}
@MainThread
fun onCurrentPageChanged(position: Int) {
fun onCurrentPageChanged(lowerPos: Int, upperPos: Int) {
val prevJob = stateChangeJob
val pages = content.value.pages // capture immediately
stateChangeJob = launchJob(Dispatchers.Default) {
@@ -265,7 +271,8 @@ class ReaderViewModel @Inject constructor(
if (pages.size != content.value.pages.size) {
return@launchJob // TODO
}
pages.getOrNull(position)?.let { page ->
val centerPos = (lowerPos + upperPos) / 2
pages.getOrNull(centerPos)?.let { page ->
currentState.update { cs ->
cs?.copy(chapterId = page.chapterId, page = page.index)
}
@@ -275,14 +282,14 @@ class ReaderViewModel @Inject constructor(
return@launchJob
}
ensureActive()
if (position >= pages.lastIndex - BOUNDS_PAGE_OFFSET) {
if (upperPos >= pages.lastIndex - BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.last().chapterId, isNext = true)
}
if (position <= BOUNDS_PAGE_OFFSET) {
if (lowerPos <= BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.first().chapterId, isNext = false)
}
if (pageLoader.isPrefetchApplicable()) {
pageLoader.prefetch(pages.trySublist(position + 1, position + PREFETCH_LIMIT))
pageLoader.prefetch(pages.trySublist(upperPos + 1, upperPos + PREFETCH_LIMIT))
}
}
}

View File

@@ -172,7 +172,8 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
}
private fun notifyPageChanged(page: Int) {
viewModel.onCurrentPageChanged(reversed(page))
val pos = reversed(page)
viewModel.onCurrentPageChanged(pos, pos)
}
private fun reversed(position: Int): Int {

View File

@@ -42,7 +42,6 @@ open class PageHolder(
bindingInfo.buttonRetry.setOnClickListener(this)
@Suppress("LeakingThis")
bindingInfo.buttonErrorDetails.setOnClickListener(this)
binding.textViewNumber.isVisible = settings.isPagesNumbersEnabled
}
override fun onResume() {
@@ -61,6 +60,7 @@ open class PageHolder(
delegate.reload()
}
binding.ssiv.applyDownsampling(isResumed())
binding.textViewNumber.isVisible = settings.isPagesNumbersEnabled
}
@SuppressLint("SetTextI18n")

View File

@@ -170,7 +170,7 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
}
private fun notifyPageChanged(page: Int) {
viewModel.onCurrentPageChanged(page)
viewModel.onCurrentPageChanged(page, page)
}
companion object {

View File

@@ -24,7 +24,8 @@ import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
import javax.inject.Inject
@AndroidEntryPoint
class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>() {
class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>(),
WebtoonRecyclerView.OnWebtoonScrollListener {
@Inject
lateinit var networkState: NetworkState
@@ -46,7 +47,7 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
with(binding.recyclerView) {
setHasFixedSize(true)
adapter = readerAdapter
addOnPageScrollListener(PageScrollListener())
addOnPageScrollListener(this@WebtoonReaderFragment)
recyclerLifecycleDispatcher = RecyclerViewLifecycleDispatcher().also {
addOnScrollListener(it)
}
@@ -70,6 +71,15 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
exceptionResolver = exceptionResolver,
)
override fun onScrollChanged(
recyclerView: WebtoonRecyclerView,
dy: Int,
firstVisiblePosition: Int,
lastVisiblePosition: Int,
) {
viewModel.onCurrentPageChanged(firstVisiblePosition, lastVisiblePosition)
}
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
val setItems = launch {
requireAdapter().setItems(pages)
@@ -91,7 +101,7 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
?.restoreScroll(pendingState.scroll)
}
}
notifyPageChanged(position)
viewModel.onCurrentPageChanged(position, position)
} else {
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
.show()
@@ -121,10 +131,6 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
viewBinding?.frame?.onZoomOut()
}
private fun notifyPageChanged(page: Int) {
viewModel.onCurrentPageChanged(page)
}
override fun switchPageBy(delta: Int) {
with(requireViewBinding().recyclerView) {
if (isAnimationEnabled()) {
@@ -147,12 +153,4 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
}
return true
}
private inner class PageScrollListener : WebtoonRecyclerView.OnPageScrollListener() {
override fun onPageChanged(recyclerView: WebtoonRecyclerView, index: Int) {
super.onPageChanged(recyclerView, index)
notifyPageChanged(index)
}
}
}

View File

@@ -6,8 +6,8 @@ import android.view.View
import androidx.core.view.ViewCompat.TYPE_TOUCH
import androidx.core.view.forEach
import androidx.core.view.iterator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition
import java.util.LinkedList
import java.util.WeakHashMap
@@ -15,7 +15,8 @@ class WebtoonRecyclerView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
private var onPageScrollListeners: MutableList<OnPageScrollListener>? = null
private var onPageScrollListeners = LinkedList<OnWebtoonScrollListener>()
private val scrollDispatcher = WebtoonScrollDispatcher()
private val detachedViews = WeakHashMap<View, Unit>()
private var isFixingScroll: Boolean = false
@@ -103,22 +104,20 @@ class WebtoonRecyclerView @JvmOverloads constructor(
return 0
}
fun addOnPageScrollListener(listener: OnPageScrollListener) {
val list = onPageScrollListeners ?: LinkedList<OnPageScrollListener>().also { onPageScrollListeners = it }
list.add(listener)
fun addOnPageScrollListener(listener: OnWebtoonScrollListener) {
onPageScrollListeners.add(listener)
}
fun removeOnPageScrollListener(listener: OnPageScrollListener) {
onPageScrollListeners?.remove(listener)
fun removeOnPageScrollListener(listener: OnWebtoonScrollListener) {
onPageScrollListeners.remove(listener)
}
private fun notifyScrollChanged(dy: Int) {
val listeners = onPageScrollListeners
if (listeners.isNullOrEmpty()) {
if (listeners.isEmpty()) {
return
}
val centerPosition = findCenterViewPosition()
listeners.forEach { it.dispatchScroll(this, dy, centerPosition) }
scrollDispatcher.dispatchScroll(this, dy)
}
fun relayoutChildren() {
@@ -162,20 +161,30 @@ class WebtoonRecyclerView @JvmOverloads constructor(
else -> false
}
abstract class OnPageScrollListener {
private class WebtoonScrollDispatcher {
private var lastPosition = NO_POSITION
private var firstPos = NO_POSITION
private var lastPos = NO_POSITION
fun dispatchScroll(recyclerView: WebtoonRecyclerView, dy: Int, centerPosition: Int) {
onScroll(recyclerView, dy)
if (centerPosition != NO_POSITION && centerPosition != lastPosition) {
lastPosition = centerPosition
onPageChanged(recyclerView, centerPosition)
fun dispatchScroll(rv: WebtoonRecyclerView, dy: Int) {
val lm = rv.layoutManager as? LinearLayoutManager
if (lm == null) {
firstPos = NO_POSITION
lastPos = NO_POSITION
return
}
val newFirstPos = lm.findFirstVisibleItemPosition()
val newLastPos = lm.findLastVisibleItemPosition()
if (newFirstPos != firstPos || newLastPos != lastPos) {
firstPos = newFirstPos
lastPos = newLastPos
rv.onPageScrollListeners.forEach { it.onScrollChanged(rv, dy, newFirstPos, newLastPos) }
}
}
}
open fun onScroll(recyclerView: WebtoonRecyclerView, dy: Int) = Unit
interface OnWebtoonScrollListener {
open fun onPageChanged(recyclerView: WebtoonRecyclerView, index: Int) = Unit
fun onScrollChanged(recyclerView: WebtoonRecyclerView, dy: Int, firstVisiblePosition: Int, lastVisiblePosition: Int)
}
}

View File

@@ -111,6 +111,7 @@ class RemoteListFragment : MangaListFragment(), FilterOwner {
override fun onPrepareMenu(menu: Menu) {
super.onPrepareMenu(menu)
menu.findItem(R.id.action_search)?.isVisible = viewModel.isSearchAvailable
menu.findItem(R.id.action_random)?.isEnabled = !viewModel.isRandomLoading.value
menu.findItem(R.id.action_filter_reset)?.isVisible = viewModel.header.value.isFilterApplied
}

View File

@@ -68,6 +68,9 @@ open class RemoteListViewModel @Inject constructor(
private var loadingJob: Job? = null
private var randomJob: Job? = null
val isSearchAvailable: Boolean
get() = repository.isSearchSupported
override val content = combine(
mangaList.map { it?.distinctById()?.skipNsfwIfNeeded() },
listMode,

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.scrobbling.common.domain
import androidx.annotation.FloatRange
import androidx.collection.LongSparseArray
import androidx.collection.getOrElse
import androidx.core.text.parseAsHtml
@@ -11,9 +12,11 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.util.ext.findKeyByValue
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.sanitize
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerRepository
import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo
@@ -21,13 +24,12 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import java.util.EnumMap
abstract class Scrobbler(
protected val db: MangaDatabase,
val scrobblerService: ScrobblerService,
private val repository: org.koitharu.kotatsu.scrobbling.common.data.ScrobblerRepository,
private val repository: ScrobblerRepository,
) {
private val infoCache = LongSparseArray<ScrobblerMangaInfo>()
@@ -76,7 +78,12 @@ abstract class Scrobbler(
return entity.toScrobblingInfo()
}
abstract suspend fun updateScrobblingInfo(mangaId: Long, rating: Float, status: ScrobblingStatus?, comment: String?)
abstract suspend fun updateScrobblingInfo(
mangaId: Long,
@FloatRange(from = 0.0, to = 1.0) rating: Float,
status: ScrobblingStatus?,
comment: String?,
)
fun observeScrobblingInfo(mangaId: Long): Flow<ScrobblingInfo?> {
return db.getScrobblingDao().observe(scrobblerService.id, mangaId)

View File

@@ -23,6 +23,8 @@ import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setProgressIcon
import org.koitharu.kotatsu.core.util.ext.setTabsEnabled
import org.koitharu.kotatsu.core.util.ext.withArgs
import org.koitharu.kotatsu.databinding.SheetScrobblingSelectorBinding
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
@@ -80,6 +82,15 @@ class ScrobblingSelectorSheet :
viewModel.onClose.observeEvent(viewLifecycleOwner) {
dismiss()
}
viewModel.isLoading.observe(viewLifecycleOwner) { isLoading ->
binding.buttonDone.isEnabled = !isLoading
if (isLoading) {
binding.buttonDone.setProgressIcon()
} else {
binding.buttonDone.icon = null
}
binding.tabs.setTabsEnabled(!isLoading)
}
viewModel.selectedScrobblerIndex.observe(viewLifecycleOwner) { index ->
val tab = binding.tabs.getTabAt(index)
if (tab != null && !tab.isSelected) {
@@ -100,7 +111,7 @@ class ScrobblingSelectorSheet :
}
override fun onItemClick(item: ScrobblerManga, view: View) {
viewModel.selectedItemId.value = item.id
viewModel.selectItem(item.id)
}
override fun onRetryClick(error: Throwable) {

View File

@@ -14,20 +14,24 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.findById
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.core.parser.MangaIntent
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.require
import org.koitharu.kotatsu.core.util.ext.requireValue
import org.koitharu.kotatsu.history.data.HistoryRepository
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus
import org.koitharu.kotatsu.scrobbling.common.ui.selector.model.ScrobblerHint
import javax.inject.Inject
@@ -35,6 +39,8 @@ import javax.inject.Inject
class ScrobblingSelectorViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
scrobblers: Set<@JvmSuppressWildcards Scrobbler>,
private val historyRepository: HistoryRepository,
private val mangaRepositoryFactory: MangaRepository.Factory,
) : BaseViewModel() {
val manga = savedStateHandle.require<ParcelableManga>(MangaIntent.KEY_MANGA).manga
@@ -92,6 +98,13 @@ class ScrobblingSelectorViewModel @Inject constructor(
loadList(append = false)
}
fun selectItem(id: Long) {
if (doneJob?.isActive == true) {
return
}
selectedItemId.value = id
}
fun loadNextPage() {
if (scrobblerMangaList.value.isNotEmpty() && hasNextPage.value) {
loadList(append = true)
@@ -109,7 +122,7 @@ class ScrobblingSelectorViewModel @Inject constructor(
if (loadingJob?.isActive == true) {
return
}
loadingJob = launchLoadingJob(Dispatchers.Default) {
loadingJob = launchJob(Dispatchers.Default) {
listError.value = null
val offset = if (append) scrobblerMangaList.value.size else 0
runCatchingCancellable {
@@ -136,8 +149,31 @@ class ScrobblingSelectorViewModel @Inject constructor(
if (targetId == NO_ID) {
onClose.call(Unit)
}
doneJob = launchJob(Dispatchers.Default) {
doneJob = launchLoadingJob(Dispatchers.Default) {
val prevInfo = currentScrobbler.getScrobblingInfoOrNull(manga.id)
currentScrobbler.linkManga(manga.id, targetId)
val history = historyRepository.getOne(manga)
currentScrobbler.updateScrobblingInfo(
mangaId = manga.id,
rating = prevInfo?.rating ?: manga.rating,
status = prevInfo?.status ?: if (history == null) {
ScrobblingStatus.PLANNED
} else {
ScrobblingStatus.READING
},
comment = prevInfo?.comment,
)
if (history != null) {
val chapter = mangaRepositoryFactory.create(manga.source)
.getDetails(manga)
.chapters?.findById(history.chapterId)
if (chapter != null) {
currentScrobbler.scrobble(
mangaId = manga.id,
chapter = chapter,
)
}
}
onClose.call(Unit)
}
}

View File

@@ -118,7 +118,7 @@ class MangaListActivity :
fm.commit {
setReorderingAllowed(true)
val fragment = if (source == MangaSource.LOCAL) {
LocalListFragment.newInstance()
LocalListFragment()
} else {
RemoteListFragment.newInstance(source)
}

View File

@@ -113,10 +113,14 @@ class MultiSearchViewModel @Inject constructor(
}
val semaphore = Semaphore(MAX_PARALLELISM)
for (source in sources) {
val repository = mangaRepositoryFactory.create(source)
if (!repository.isSearchSupported) {
continue
}
launch {
val item = runCatchingCancellable {
semaphore.withPermit {
mangaRepositoryFactory.create(source).getList(offset = 0, filter = MangaListFilter.Search(q))
repository.getList(offset = 0, filter = MangaListFilter.Search(q))
.toUi(ListMode.GRID, extraProvider)
}
}.fold(

View File

@@ -8,6 +8,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.resolve
import org.koitharu.kotatsu.core.util.ext.tryLaunch
import com.google.android.material.R as materialR
@@ -43,7 +44,7 @@ class SearchSuggestionMenuProvider(
}
private fun clearSearchHistory() {
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered)
MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.clear_search_history)
.setIcon(R.drawable.ic_clear_all)
.setMessage(R.string.text_clear_search_history_prompt)

View File

@@ -16,7 +16,8 @@ import io.noties.markwon.Markwon
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.github.AppVersion
import org.koitharu.kotatsu.core.util.FileSize
import com.google.android.material.R as materialR
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
class AppUpdateDialog(private val activity: AppCompatActivity) {
@@ -42,10 +43,7 @@ class AppUpdateDialog(private val activity: AppCompatActivity) {
appendLine()
append(Markwon.create(activity).toMarkdown(version.description))
}
MaterialAlertDialogBuilder(
activity,
materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
)
MaterialAlertDialogBuilder(activity, DIALOG_THEME_CENTERED)
.setTitle(R.string.app_update_available)
.setMessage(message)
.setIcon(R.drawable.ic_app_update)
@@ -68,7 +66,7 @@ class AppUpdateDialog(private val activity: AppCompatActivity) {
}
}
private fun downloadUpdateImpl() {
private fun downloadUpdateImpl() = runCatching {
val version = latestVersion
val url = version.apkUrl.toUri()
val dm = activity.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
@@ -78,7 +76,10 @@ class AppUpdateDialog(private val activity: AppCompatActivity) {
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setMimeType("application/vnd.android.package-archive")
dm.enqueue(request)
}.onSuccess {
Toast.makeText(activity, R.string.download_started, Toast.LENGTH_SHORT).show()
}.onFailure { e ->
Toast.makeText(activity, e.getDisplayMessage(activity.resources), Toast.LENGTH_SHORT).show()
}
private fun openInBrowser() {

View File

@@ -352,7 +352,7 @@ class SuggestionsWorker @AssistedInject constructor(
val request = PeriodicWorkRequestBuilder<SuggestionsWorker>(6, TimeUnit.HOURS)
.setConstraints(createConstraints())
.addTag(TAG)
.setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
.setBackoffCriteria(BackoffPolicy.LINEAR, 1, TimeUnit.HOURS)
.build()
workManager
.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.UPDATE, request)

View File

@@ -323,7 +323,7 @@ class TrackWorker @AssistedInject constructor(
val request = PeriodicWorkRequestBuilder<TrackWorker>(4, TimeUnit.HOURS)
.setConstraints(constraints)
.addTag(TAG)
.setBackoffCriteria(BackoffPolicy.LINEAR, 5, TimeUnit.MINUTES)
.setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
.build()
workManager
.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.UPDATE, request)
@@ -373,7 +373,7 @@ class TrackWorker @AssistedInject constructor(
const val TAG = "tracking"
const val TAG_ONESHOT = "tracking_oneshot"
const val MAX_PARALLELISM = 3
const val MAX_ATTEMPTS = 4
const val MAX_ATTEMPTS = 3
const val DATA_KEY_SUCCESS = "success"
const val DATA_KEY_FAILED = "failed"
const val KEY_RETRY_IDS = "retry"

View File

@@ -52,6 +52,7 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="textPassword"
android:maxLength="24"
android:singleLine="true"
@@ -80,4 +81,4 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -53,6 +53,7 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="textPassword"
android:maxLength="24"
android:singleLine="true"
@@ -94,4 +95,4 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -14,7 +14,7 @@
app:tabGravity="start"
app:tabMode="scrollable" />
<org.koitharu.kotatsu.core.ui.widgets.EnhancedViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_selector"
android:minHeight="98dp"
android:paddingStart="?android:listPreferredItemPaddingStart"
tools:ignore="RtlSymmetry">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover3"
android:layout_width="0dp"
android:layout_height="64dp"
android:layout_marginStart="24dp"
android:layout_marginBottom="12dp"
android:background="?attr/colorSecondaryContainer"
android:backgroundTintMode="src_atop"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="W,13:18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover.Small"
app:tintMode="src_atop"
tools:backgroundTint="#99FFFFFF"
tools:src="@tools:sample/backgrounds/scenic"
tools:tint="#99FFFFFF" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover2"
android:layout_width="0dp"
android:layout_height="64dp"
android:layout_marginStart="12dp"
android:background="?attr/colorSecondaryContainer"
android:backgroundTintMode="src_atop"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="W,13:18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover.Small"
app:tintMode="src_atop"
tools:backgroundTint="#4DFFFFFF"
tools:src="@tools:sample/backgrounds/scenic"
tools:tint="#4DFFFFFF" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover1"
android:layout_width="0dp"
android:layout_height="64dp"
android:layout_marginTop="12dp"
android:background="?attr/colorSecondaryContainer"
android:backgroundTintMode="src_atop"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="W,13:18"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover.Small"
tools:src="@tools:sample/backgrounds/scenic" />
<TextView
android:id="@+id/textView_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginEnd="?listPreferredItemPaddingEnd"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/all_favourites"
android:textAppearance="?attr/textAppearanceBodyLarge"
app:layout_constraintBottom_toTopOf="@id/textView_subtitle"
app:layout_constraintEnd_toStartOf="@id/imageView_visible"
app:layout_constraintStart_toEndOf="@id/imageView_cover3"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/textView_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_normal"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/imageView_visible"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/imageView_cover3"
app:layout_constraintTop_toBottomOf="@id/textView_title"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintWidth_default="wrap"
tools:text="@tools:sample/lorem[1]" />
<ImageView
android:id="@+id/imageView_visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/show_all"
android:padding="@dimen/margin_normal"
android:src="@drawable/ic_eye"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -34,7 +34,7 @@
app:tabMode="scrollable"
tools:ignore="UnusedAttribute" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/button_done"
style="@style/Widget.Material3.Button.UnelevatedButton"
android:layout_width="wrap_content"

View File

@@ -27,6 +27,12 @@
android:title="@string/categories"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_mark_current"
android:icon="@drawable/ic_eye_check"
android:title="@string/mark_as_completed"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_select_all"
android:icon="?actionModeSelectAllDrawable"

View File

@@ -27,4 +27,10 @@
android:title="@string/add_to_favourites"
app:showAsAction="ifRoom|withText" />
</menu>
<item
android:id="@+id/action_mark_current"
android:icon="@drawable/ic_eye_check"
android:title="@string/mark_as_completed"
app:showAsAction="ifRoom|withText" />
</menu>

View File

@@ -1,13 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="AlwaysShowAction">
<item
android:id="@+id/action_chapters"
android:icon="@drawable/ic_expand_more"
android:title="@string/chapters"
android:orderInCategory="0"
android:title="@string/chapters"
app:showAsAction="always" />
</menu>
<item
android:id="@+id/action_incognito"
android:icon="@drawable/ic_incognito"
android:title="@string/incognito_mode"
android:visible="false"
app:showAsAction="always" />
</menu>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_edit"
android:title="@string/edit_category"
android:titleCondensed="@string/edit" />
<item
android:id="@+id/action_delete"
android:title="@string/delete" />
<item
android:id="@+id/action_hide"
android:title="@string/hide" />
</menu>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_hide"
android:title="@string/hide" />
</menu>

View File

@@ -283,4 +283,8 @@
<string name="empty_favourite_categories">لا توجد فئات مفضلة</string>
<string name="screenshots_policy">سياسة لقطة الشاشة</string>
<string name="done">تم</string>
<string name="no_thanks">لا شكرا</string>
<string name="enable">تفعيل</string>
<string name="cancel_all_downloads_confirm">سيتم إلغاء جميع التنزيلات النشطة، وستُفقَد البيانات المحملة جزئيًا</string>
<string name="text_downloads_list_holder">ليس لديك أية تنزيلات</string>
</resources>

View File

@@ -543,4 +543,12 @@
<string name="restore">Аднавіць</string>
<string name="backup_date_">Дата стварэння рэзервовай копіі: %s</string>
<string name="sync_auth">Увайдзіце, каб сінхранізаваць уліковы запіс</string>
<string name="by_name_reverse">Імя (зваротнае)</string>
<string name="content_rating">Рэйтынг кантэнту</string>
<string name="genres_exclude">Выключыць жанры</string>
<string name="rating_safe">Бяспечны</string>
<string name="rating_suggestive">З падказкамі</string>
<string name="rating_adult">Дарослы</string>
<string name="default_tab">Ўкладка па змаўчанні</string>
<string name="state_upcoming">Чакаецца</string>
</resources>

View File

@@ -261,7 +261,7 @@
<string name="appwidget_shelf_description">Manga aus deinen Favoriten</string>
<string name="appwidget_recent_description">Deine kürzlich gelesenen Manga</string>
<string name="report">Melden</string>
<string name="tracking">Nachverfolgung</string>
<string name="tracking">Externe Plattformen (Tracking)</string>
<string name="logout">Abmelden</string>
<string name="status_planned">Geplant</string>
<string name="status_on_hold">In der Warteschleife</string>
@@ -270,7 +270,7 @@
<string name="show_reading_indicators_summary">Zeige gelesenen Prozentsatz in Verlauf und Favoriten</string>
<string name="clear_cookies_summary">Kann bei einigen Probleme helfen. Alle Anmeldungen werden ungültig</string>
<string name="status_completed">Abgeschlossen</string>
<string name="exclude_nsfw_from_history_summary">Als NSFW markierte Manga werden nicht dem Verlauf beigefügt und dein Lesefortschritt wird nicht gespeichert</string>
<string name="exclude_nsfw_from_history_summary">Als NSFW markierte Manga werden nicht in den Verlauf aufgenommen und Ihr Fortschritt wird nicht gespeichert</string>
<string name="data_deletion">Datenlöschung</string>
<string name="invalid_domain_message">Ungültige Domain</string>
<string name="status_reading">Lese</string>
@@ -347,7 +347,7 @@
<string name="share_logs">Protokolle teilen</string>
<string name="enable_logging">Protokollierung aktivieren</string>
<string name="language">Sprache</string>
<string name="enable_logging_summary">Einige Aktionen zu Debug-Zwecken aufzeichnen</string>
<string name="enable_logging_summary">Einige Aktionen zu Debug-Zwecken aufzeichnen. Aktiviere dies nicht, wenn Du dir nicht sicher bist, was du tust.</string>
<string name="history_shortcuts">Zeige Verknüpfungen zu aktuellen Manga</string>
<string name="history_shortcuts_summary">Neueste Manga durch langes Drücken auf das Anwendungssymbol verfügbar machen</string>
<string name="show_suspicious_content">Verdächtige Inhalte anzeigen</string>
@@ -358,10 +358,10 @@
<string name="nothing_here">Hier ist nichts</string>
<string name="services">Dienste</string>
<string name="theme_name_kanade">Kanade</string>
<string name="scrobbling_empty_hint">Um deinen Lesefortschritt nachzuverfolgen, wähle MenuTrack auf dem Manga Details Bildschirm.</string>
<string name="scrobbling_empty_hint">Um deinen Lesefortschritt nachzuverfolgen, wähle MenüLesefortschritt aufzeichnen auf dem Manga Details Bildschirm.</string>
<string name="find_similar">Ähnliche finden</string>
<string name="theme_name_sakura">Sakura</string>
<string name="allow_unstable_updates_summary">Schlage Updates zu Beta-Versionen der App vor</string>
<string name="allow_unstable_updates_summary">Benachrichtigungen über instabile Versionen erhalten</string>
<string name="allow_unstable_updates">Erlaube instabile Updates</string>
<string name="got_it">Alles klar</string>
<string name="sources_reorder_tip">Drücke und halte eine Quelle, um diese umzusortieren</string>
@@ -382,7 +382,7 @@
<string name="sync_settings">Synchronisationseinstellungen</string>
<string name="sync_host_description">Du kannst einen Standard- oder einen selbst gehosteten Synchronisations-Server verwenden. Ändere diese Einstellungen nicht, wenn du dich nicht auskennst.</string>
<string name="ignore_ssl_errors">Ignoriere SSL Errors</string>
<string name="mirror_switching_summary">Wechsel bei Fehlern automatisch die Domains für Manga-Quellen, falls Mirrors verfügbar sind</string>
<string name="mirror_switching_summary">Automatischer Domain-Wechsel für Manga-Quellen, falls Spiegelserver verfügbar sind</string>
<string name="status_re_reading">Lese erneut</string>
<string name="sync_auth_hint">Du kannst dich mit einem bestehenden Account anmelden oder einen neuen erstellen</string>
<string name="user_agent">UserAgent-Kopfzeile</string>
@@ -465,4 +465,94 @@
<string name="in_progress">In Arbeit</string>
<string name="related_manga">Verwandte Manga</string>
<string name="clear_source_cookies_summary">Cookies nur für bestimmte Domain löschen. In den meisten Fällen wird die Genehmigung ungültig</string>
<string name="default_section">Standard-Abschnitt</string>
<string name="catalog">Katalog</string>
<string name="manage_sources">Quellen verwalten</string>
<string name="content_type_manga">Manga</string>
<string name="content_type_hentai">Hentai</string>
<string name="content_type_other">Sonstige</string>
<string name="sources_catalog">Quellenkatalog</string>
<string name="source_enabled">Quelle aktiviert</string>
<string name="keep_screen_on">Bildschirm eingeschaltet lassen</string>
<string name="lock_screen_rotation">Bildschirm-Ausrichtung sperren</string>
<string name="manga_list">Manga liste</string>
<string name="disable_nsfw">NSFW deaktivieren</string>
<string name="too_many_requests_message">Zu viele Anfragen. Probier es später erneut</string>
<string name="items_limit_exceeded">Es können keine weiteren Elemente hinzugefügt werden</string>
<string name="zoom_out">Herauszoomen</string>
<string name="reader_zoom_buttons">Zoom - Schaltflächen anzeigen</string>
<string name="periodic_backups">Periodische Backups</string>
<string name="backup_frequency">Häufigkeit der Backup-Erstellung</string>
<string name="error_multiple_genres_not_supported">Filtern nach mehreren Genres wird von dieser Manga-Quelle nicht unterstützt</string>
<string name="webtoon_zoom_summary">Zoom-Geste in Webtoon-Modus erlauben</string>
<string name="available_d">Verfügbar: %1$d</string>
<string name="on_device">Auf dem Gerät</string>
<string name="directories">Verzeichnisse</string>
<string name="to_top">Nach oben</string>
<string name="moved_to_top">Nach oben verschoben</string>
<string name="state_paused">Pausiert</string>
<string name="zoom_in">Hereinzoomen</string>
<string name="reader_zoom_buttons_summary">Ob die Zoom - Schaltflächen in der unteren rechten Ecke angezeigt werden sollen</string>
<string name="reader_optimize">Speicherverbrauch reduzieren (beta)</string>
<string name="reader_optimize_summary">Qualität von nicht sichtbaren Seiten verringern, um den Speicherverbrauch zu reduzieren</string>
<string name="state">Zustand</string>
<string name="error_multiple_states_not_supported">Filtern nach mehreren Zuständen wird von dieser Manga-Quelle nicht unterstützt</string>
<string name="error_search_not_supported">Die Suchfunktion wird von dieser Manga-Quelle nicht unterstützt</string>
<string name="enhanced_colors">32-bit Farbmodus</string>
<string name="suggest_new_sources">Neue Quellen nach einem Update vorschlagen</string>
<string name="by_relevance">Relevanz</string>
<string name="categories">Kategorien</string>
<string name="frequency_every_day">Täglich</string>
<string name="frequency_every_2_days">Alle 2 Tage</string>
<string name="frequency_twice_per_month">Zweimal pro Monat</string>
<string name="frequency_once_per_week">Einmal pro Woche</string>
<string name="frequency_once_per_month">Einmal pro Monat</string>
<string name="periodic_backups_enable">Periodische Backups aktivieren</string>
<string name="backups_output_directory">Speicher-Verzeichnis für Backups</string>
<string name="last_successful_backup">Letztes erfolgreiches Backup: %s</string>
<string name="state_upcoming">Erwartet</string>
<string name="by_name_reverse">Name reserviert</string>
<string name="advanced">Erweitert</string>
<string name="content_type_comics">Comics</string>
<string name="source_summary_pattern">%1$s, %2$s</string>
<string name="no_manga_sources_found">Keine verfügbaren Manga-Quellen für deinen Suchbegriff gefunden</string>
<string name="welcome_text">Bitte wähle aus, welche Inhalte-Quellen du aktivieren möchtest. Dies kannst du auch später in den Einstellungen konfigurieren</string>
<string name="sync_auth">Melde dich beim Sync - Account an</string>
<string name="downloads_settings_info">Du kannst die Download-Verlangsamung für jede Manga-Quelle einzeln in den Quelleneinstellungen aktivieren, wenn du Probleme mit der serverseitigen Blockierung hast</string>
<string name="skip">Überspringen</string>
<string name="restore">Wiederherstellen</string>
<string name="backup_date_">Sicherungsdatum: %s</string>
<string name="content_rating">Einstufung (Inhalt)</string>
<string name="genres_exclude">Genres ausschließen</string>
<string name="rating_safe">Sicher</string>
<string name="rating_suggestive">Suggestiv</string>
<string name="rating_adult">Erwachsene</string>
<string name="online_variant">Online-Variante</string>
<string name="keep_screen_on_summary">Bildschirm nicht ausschalten, während du Manga liest</string>
<string name="default_tab">Standard-Reiter</string>
<string name="related_manga_summary">Zeige eine Liste ähnlicher Manga. Diese kann in einigen Fällen ungenau sein oder fehlen</string>
<string name="grayscale">Graustufen</string>
<string name="globally">Global</string>
<string name="this_manga">Dieses Manga</string>
<string name="color_correction_apply_text">Diese Einstellungen können global oder nur auf das aktuelle Manga angewendet werden. Werden sie global angewendet, bleiben individuelle Einstellungen erhalten.</string>
<string name="apply">Anwenden</string>
<string name="manual">Anleitung</string>
<string name="speed_value">x%.1f</string>
<string name="error_filter_states_genre_not_supported">Die Filterung nach Genre und Status wird von dieser Quelle nicht unterstützt</string>
<string name="error_filter_locale_genre_not_supported">Die Filterung nach Genre und Lokalisation wird von dieser Quelle nicht unterstützt</string>
<string name="error_corrupted_file">Es wurden ungültige Daten zurückgegeben oder die Datei ist beschädigt</string>
<string name="genres_search_hint">Beginne den Genre-Namen einzutippen</string>
<string name="no_manga_sources_catalog_text">In diesem Abschnitt sind keine Quellen verfügbar, oder es wurde bereits alles hinzugefügt.
\nBleibe dran für neue Quellen</string>
<string name="mark_as_completed">Als fertig markieren</string>
<string name="mark_as_completed_prompt">Ausgewählte Manga als vollständig gelesen markieren?
\n
\nAchtung: Der aktuelle Lesefortschritt geht verloren.</string>
<string name="main_screen_sections">Hauptbildschirm - Abschnitte</string>
<string name="disable_nsfw_summary">Deaktiviere NSFW - Quellen und verberge Erwachsenen-Manga von der Liste, wenn möglich</string>
<string name="disable_battery_optimization_summary_downloads">Könnte dir damit helfen, den Download zu starten, wenn du Probleme damit hast</string>
<string name="state_abandoned">Verworfen</string>
<string name="enhanced_colors_summary">Reduziert das Banding (harte Farbverläufe), kann aber die Leistung beeinträchtigen</string>
<string name="suggest_new_sources_summary">Aufforderung zur Aktivierung neu hinzugefügter Quellen nach Aktualisierung der Anwendung</string>
<string name="list_options">Listenoptionen</string>
</resources>

View File

@@ -1,27 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="days_ago">
<item quantity="one">%1$d μέρα πριν</item>
<item quantity="other">%1$d μέρες πριν</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$dστοιχείο</item>
<item quantity="other">%1$dστοιχεία</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$dνέο κεφάλαιο</item>
<item quantity="other">%1$dνέα κεφάλαια</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">%1$dώρα πριν</item>
<item quantity="other">%1$dώρες πριν</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$dκεφάλαιο</item>
<item quantity="other">%1$dκεφάλαια</item>
</plurals>
<plurals name="minutes_ago">
<item quantity="one">%1$dλεπτό πριν</item>
<item quantity="other">%1$d λεπτά πριν</item>
</plurals>
</resources>
<plurals name="days_ago">
<item quantity="one">%1$d μέρα πριν</item>
<item quantity="other">%1$d μέρες πριν</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$d στοιχείο</item>
<item quantity="other">%1$d στοιχεία</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$d νέο κεφάλαιο</item>
<item quantity="other">%1$d νέα κεφάλαια</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">%1$d ώρα πριν</item>
<item quantity="other">%1$d ώρες πριν</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d κεφάλαιο</item>
<item quantity="other">%1$d κεφάλαια</item>
</plurals>
<plurals name="minutes_ago">
<item quantity="one">%1$d λεπτό πριν</item>
<item quantity="other">%1$d λεπτά πριν</item>
</plurals>
<plurals name="months_ago">
<item quantity="one">%1$d μήνας πριν</item>
<item quantity="other">%1$d μήνες πριν</item>
</plurals>
</resources>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="local_storage">Εσωτερικός χώρος</string>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="local_storage">Τοπικός χώρος αποθήκευσης</string>
<string name="favourites">Αγαπημένα</string>
<string name="history">Ιστορικό</string>
<string name="error_occurred">Προέκυψε σφάλμα</string>
@@ -8,7 +8,7 @@
<string name="grid">Πλέγμα</string>
<string name="list_mode">Εμφάνιση ως λίστα</string>
<string name="settings">Ρυθμίσεις</string>
<string name="remote_sources">Πηγές μάνγκα</string>
<string name="remote_sources">Πηγές manga</string>
<string name="computing_">Επεξεργασία…</string>
<string name="close">Κλείσιμο</string>
<string name="clear_history">Εκκαθάριση ιστορικού</string>
@@ -22,7 +22,7 @@
<string name="create_shortcut">Δημιουργία συντόμευσης…</string>
<string name="share_s">Κοινοποίηση %s</string>
<string name="search">Αναζήτηση</string>
<string name="search_manga">Αναζήτηση μάνγκα</string>
<string name="search_manga">Αναζήτηση manga</string>
<string name="manga_downloading_">Λήψη…</string>
<string name="download_complete">Κατεβασμένο</string>
<string name="downloads">Λήψεις</string>
@@ -37,18 +37,18 @@
<string name="remove">Διαγραφή</string>
<string name="save_page">Αποθήκευση σελίδας</string>
<string name="page_saved">Αποθηκευμένα</string>
<string name="share_image">Κοινή χρήση εικόνας</string>
<string name="share_image">Κοινοποίηση εικόνας</string>
<string name="_import">Εισαγωγή</string>
<string name="delete">Διαγραφή</string>
<string name="text_file_not_supported">Επιλέξτε ένα αρχείο ZIP ή CBZ.</string>
<string name="no_description">Χωρίς περιγραφή</string>
<string name="clear_pages_cache">Εκκαθάριση μνήμης cache της σελίδας</string>
<string name="clear_pages_cache">Εκκαθάριση προσωρινής μνήμης της σελίδας</string>
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
<string name="standard">Τυπικό</string>
<string name="webtoon">Μάνχγουα</string>
<string name="webtoon">Webtoon</string>
<string name="search_on_s">Αναζήτηση στο %s</string>
<string name="delete_manga">Διαγραφή μάνγκα</string>
<string name="text_delete_local_manga">Μόνιμη διαγραφή του \"%s\" από τη συσκευή;</string>
<string name="delete_manga">Διαγραφή manga</string>
<string name="text_delete_local_manga">Διαγραφή του \"%s\" από τη συσκευή;</string>
<string name="reader_settings">Ρυθμίσεις λειτουργίας ανάγνωσης</string>
<string name="switch_pages">Αλλαγή σελίδων</string>
<string name="network_error">Σφάλμα δικτύου</string>
@@ -63,7 +63,7 @@
<string name="processing_">Επεξεργασία…</string>
<string name="by_name">Όνομα</string>
<string name="popular">Δημοφιλή</string>
<string name="sort_order">Τρόπος Ταξινόμησης</string>
<string name="sort_order">Τρόπος ταξινόμησης</string>
<string name="theme">Θέμα</string>
<string name="light">Φωτεινό</string>
<string name="pages">Σελίδες</string>
@@ -79,4 +79,480 @@
<string name="theme_name_mion">Μιόν</string>
<string name="theme_name_rikka">Ρίκκα</string>
<string name="theme_name_sakura">Σακούρα</string>
</resources>
<string name="notifications">Ειδοποιήσεις</string>
<string name="vibration">Δόνηση</string>
<string name="favourites_categories">Αγαπημένες κατηγορίες</string>
<string name="text_shelf_holder_primary">Τα manga σου θα εμφανίζονται εδώ</string>
<string name="text_shelf_holder_secondary">Βρες κάτι να διαβάσεις στο τμήμα «Εξερεύνηση»</string>
<string name="manga_save_location">Φάκελος λήψεων</string>
<string name="not_available">Μη διαθέσιμο</string>
<string name="all_favourites">Όλα τα αγαπημένα</string>
<string name="favourites_category_empty">Άδεια κατηγορία</string>
<string name="read_later">Θα διαβαστούν αργότερα</string>
<string name="updates">Ενημερώσεις</string>
<string name="search_results">Αποτελέσματα αναζήτησης</string>
<string name="new_version_s">Νέα έκδοση: %s</string>
<string name="size_s">Μέγεθος: %s</string>
<string name="clear_updates_feed">Εκκαθάριση τροφοδοτικού ενημερώσεων</string>
<string name="updates_feed_cleared">Καθαρίστηκε</string>
<string name="rotate_screen">Περιστροφή οθόνης</string>
<string name="update">Ενημέρωση</string>
<string name="feed_will_update_soon">Η ενημέρωση του τροφοδοτικού θα αρχίσει σύντομα</string>
<string name="dont_check">Μην κοιτάξεις</string>
<string name="enter_password">Εισαγωγή κωδικού</string>
<string name="check_for_updates">Κοίτα για ενημερώσεις</string>
<string name="right_to_left">Δεξιά προς τα αριστερά</string>
<string name="create_category">Νέα κατηγορία</string>
<string name="scale_mode">Είδος κλίμακας</string>
<string name="zoom_mode_fit_center">Γέμισμα στο κέντρο</string>
<string name="zoom_mode_fit_height">Γέμισμα βάσει ύψους</string>
<string name="zoom_mode_fit_width">Γέμισμα βάσει πλάτους</string>
<string name="zoom_mode_keep_start">Κράτα το κατά την εκκίνηση</string>
<string name="black_dark_theme">Μαύρο</string>
<string name="black_dark_theme_summary">Λιγότερη κατανάλωση ενέργειας με οθόνες AMOLED</string>
<string name="backup_restore">Αντίγραφο ασφαλείας και επαναφορά</string>
<string name="create_backup">Δημιουργία αντιγράφου ασφαλείας</string>
<string name="restore_backup">Επαναφορά αντιγράφου ασφαλείας</string>
<string name="data_restored">Επαναφέρθηκε</string>
<string name="preparing_">Ετοιμάζεται…</string>
<string name="file_not_found">Δεν βρέθηκε αρχείο</string>
<string name="data_restored_with_errors">Τα δεδομένα επαναφέρθηκαν, αλλά υπήρξαν σφάλματα</string>
<string name="backup_information">Μπορείς να δημιουργήσεις αντίγραφα ασφαλείας του ιστορικού σου και των αγαπημένων σου και να τα επαναφέρεις</string>
<string name="cookies_cleared">Όλα τα cookies καθαρίστηκαν</string>
<string name="check_for_new_chapters">Κοίτα για νέα κεφάλαια</string>
<string name="genres">Είδη</string>
<string name="suggestions_info">Όλα τα δεδομένα αναλύονται στην συσκευή αυτή και δεν στέλνονται πουθενά αλλού.</string>
<string name="text_suggestion_holder">Ξεκίνα να διαβάσεις manga και θα λαμβάνεις εξατομικευμένες προτάσεις</string>
<string name="exclude_nsfw_from_suggestions">Να μην προτείνονται manga που είναι NSFW</string>
<string name="filter_load_error">Η φόρτωση της λίστας ειδών απέτυχε</string>
<string name="search_chapters">Βρες το κεφάλαιο</string>
<string name="chapters_empty">Αυτό το manga δεν έχει κεφάλαια</string>
<string name="chapters_will_removed_background">Τα κεφάλαια θα διαγράφονται στο παρασκήνιο</string>
<string name="account_already_exists">Ο λογαριασμός υπάρχει ήδη</string>
<string name="back">Πίσω</string>
<string name="hide">Κρύψε</string>
<string name="check_new_chapters_title">Κοίτα για νέα κεφάλαια και ενημέρωσε με</string>
<string name="taps_on_edges">Πλευρικά πατήματα</string>
<string name="volume_buttons">Κουμπιά έντασης</string>
<string name="clear_thumbs_cache">Εκκαθάριση προσωρινής μνήμης σκίτσων</string>
<string name="clear_search_history">Εκκαθάριση ιστορικού αναζήτησης</string>
<string name="search_history_cleared">Καθαρίστηκε</string>
<string name="gestures_only">Μόνο με χειρονομίες</string>
<string name="internal_storage">Εσωτερικός χώρος αποθήκευσης</string>
<string name="external_storage">Εξωτερικός χώρος αποθήκευσης</string>
<string name="domain">Τομέας</string>
<string name="app_update_available">Μια νέα έκδοση της εφαρμογής έγινε διαθέσιμη</string>
<string name="open_in_browser">Άνοιγμα μέσω περιηγητή</string>
<string name="large_manga_save_confirm">Αυτό το manga έχει %s. Να αποθηκευτεί ολόκληρο;</string>
<string name="save_manga">Αποθήκευση</string>
<string name="text_empty_holder_primary">Λίγο άδειο δεν είναι το μέρος…</string>
<string name="text_search_holder_secondary">Προσπάθησε να αναδιατυπώσεις την αναζήτηση.</string>
<string name="text_history_holder_primary">Ό,τι διαβάζεις θα εμφανίζεται εδώ</string>
<string name="text_history_holder_secondary">Βρες κάτι να διαβάσεις στο τμήμα «Εξερεύνηση»</string>
<string name="text_local_holder_primary">Αποθήκευσε κάτι πρώτα</string>
<string name="text_local_holder_secondary">Αποθήκευσε κάτι από διαδικτυακές πηγές ή εισήγαγε το από αρχείο.</string>
<string name="manga_shelf">Ράφι</string>
<string name="recent_manga">Πρόσφατα</string>
<string name="pages_animation">Κίνηση σελίδας</string>
<string name="wrong_password">Λανθασμένος κωδικός</string>
<string name="protect_application">Προστάτευσε την εφαρμογή</string>
<string name="protect_application_summary">Ζήτηση κωδικού κατά την εκκίνηση του Kotatsu</string>
<string name="repeat_password">Επανάληψη κωδικού</string>
<string name="passwords_mismatch">Ασύμφωνοι κωδικοί</string>
<string name="about">Σχετικά</string>
<string name="app_version">Έκδοση %s</string>
<string name="just_now">Μόλις τώρα</string>
<string name="group">Ομάδα</string>
<string name="today">Σήμερα</string>
<string name="yesterday">Χθες</string>
<string name="long_ago">Πριν πολύ καιρό</string>
<string name="tap_to_try_again">Πάτα για να ξαναπροσπαθήσεις</string>
<string name="reader_mode_hint">Η επιλεγμένες ρυθμίσεις θα αποθηκευτούν για το παρόν manga</string>
<string name="silent">Αθόρυβο</string>
<string name="read_more">Διάβασε περισσότερα</string>
<string name="queued">Στην ουρά</string>
<string name="chapter_is_missing">Λείπει το κεφάλαιο</string>
<string name="about_app_translation_summary">Μετάφρασε την εφαρμογή</string>
<string name="about_app_translation">Μετάφραση</string>
<string name="auth_complete">Εξουσιοδοτημένο</string>
<string name="auth_not_supported_by">Η σύνδεση στο %s δεν υποστηρίζεται</string>
<string name="text_clear_cookies_prompt">Θα αποσυνδεθείς από όλες τις πηγές</string>
<string name="state_finished">Ολοκληρώθηκε</string>
<string name="state_ongoing">Σε εξέλιξη</string>
<string name="system_default">Προεπιλεγμένο</string>
<string name="exclude_nsfw_from_history">Να μην συμπεριλαμβάνονται στο ιστορικό manga που είναι NSFW</string>
<string name="show_pages_numbers">Αριθμημένες σελίδες</string>
<string name="enabled">Ενεργοποιημένο</string>
<string name="onboard_text">Επίλεξε γλώσσες στις οποίες θέλεις να διαβάσεις manga. Μπορείς να αλλάξεις την επιλογή σου αργότερα από τις ρυθμίσεις.</string>
<string name="never">Ποτέ</string>
<string name="preload_pages">Προφόρτωση σελίδων</string>
<string name="logged_in_as">Συνδέθηκες ως %s</string>
<string name="always">Πάντα</string>
<string name="nsfw">18+</string>
<string name="various_languages">Διάφορες γλώσσες</string>
<string name="percent_string_pattern">%1$s%%</string>
<string name="appearance">Εμφάνιση</string>
<string name="suggestions_updating">Οι προτάσεις ενημερώνονται</string>
<string name="suggestions_excluded_genres">Να μην συμπεριλαμβάνονται τα είδη</string>
<string name="suggestions_excluded_genres_summary">Ξεκαθάρισε ποια είδη δεν δες να βλέπεις στα προτεινόμενα</string>
<string name="text_delete_local_manga_batch">Διαγραφή των επιλεγμένων στοιχείων από την συσκευή;</string>
<string name="removal_completed">Η εκκαθάριση ολοκληρώθηκε</string>
<string name="sync">Συγχρονισμός</string>
<string name="sync_title">Συγχρόνισε τα δεδομένα σου</string>
<string name="email_enter_hint">Εισήγαγε το email σου για να προχωρήσεις</string>
<string name="new_sources_text">Νέες πηγές manga είναι διαθέσιμες</string>
<string name="notifications_enable">Ενεργοποίηση ειδοποιήσεων</string>
<string name="download">Λήψη</string>
<string name="notifications_settings">Ρυθμίσεις ειδοποιήσεων</string>
<string name="done">Ολοκληρώθηκε</string>
<string name="reverse">Αντιστροφή</string>
<string name="sign_in">Σύνδεση</string>
<string name="auth_required">Συνδέσου για να δεις το περιεχόμενο</string>
<string name="reset_filter">Επαναφορά φίλτρου</string>
<string name="download_slowdown">Καθυστέρηση λήψεων</string>
<string name="local_manga_processing">Επεξεργασία αποθηκευμένων manga</string>
<string name="canceled">Ακυρώθηκε</string>
<string name="_continue">Συνέχισε</string>
<string name="error">Σφάλμα</string>
<string name="new_chapters">Νέα κεφάλαια</string>
<string name="notification_sound">Ήχος ειδοποιήσεων</string>
<string name="cannot_find_available_storage">Μη διαθέσιμος χώρος αποθήκευσης</string>
<string name="light_indicator">Δείκτης LED</string>
<string name="other_storage">Άλλος χώρος αποθήκευσης</string>
<string name="remove_category">Αφαίρεση</string>
<string name="text_feed_holder">Νέα κεφάλαια από ό,τι διαβάζεις θα φαίνονται εδώ</string>
<string name="track_sources">Ψάξε για ενημερώσεις</string>
<string name="no_update_available">Δεν είναι διαθέσιμη κάποια ενημέρωση</string>
<string name="data_restored_success">Όλα τα δεδομένα επαναφέρθηκαν</string>
<string name="protect_application_subtitle">Εισήγαγε κωδικό με τον οποίο θα ανοίγεις την εφαρμογή</string>
<string name="captcha_required">Απαιτείται έλεγχος CAPTCHA</string>
<string name="captcha_solve">Επίλυση</string>
<string name="clear_cookies">Εκκαθάριση cookies</string>
<string name="clear_feed">Εκκαθάριση τροφοδοτικού</string>
<string name="text_clear_updates_feed_prompt">Εκκαθάριση ολόκληρου του ιστορικού;</string>
<string name="next">Επόμενο</string>
<string name="confirm">Επιβεβαίωση</string>
<string name="welcome">Καλώς ήρθες</string>
<string name="available_sources">Διαθέσιμες πηγές</string>
<string name="default_s">Προεπιλεγμένο: %s</string>
<string name="text_clear_search_history_prompt">Εκκαθάριση όλων των πρόσφατων αναζητήσεων;</string>
<string name="backup_saved">Το αντίγραφο ασφαλείας αποθηκεύτηκε</string>
<string name="password_length_hint">Ο κωδικός πρέπει να αποτελείται από 4, ή περισσότερους, χαρακτήρες</string>
<string name="tracker_warning">Το συστήματα μερικών συσκευών λειτουργούν διαφορετικά, και αυτό μπορεί να επηρεάσει τις λειτουργίες στο παρασκήνιο.</string>
<string name="screenshots_policy">Πολιτική στιγμιότυπων οθόνης</string>
<string name="screenshots_block_nsfw">Να μην επιτρέπονται σε NSFW manga</string>
<string name="enabled_sources">Χρησιμοποιημένες πηγές</string>
<string name="screenshots_allow">Επίτρεψε</string>
<string name="screenshots_block_all">Να απαγορεύονται πάντα</string>
<string name="suggestions_summary">Να προτείνονται manga βάσει των προτιμήσεων σου</string>
<string name="disabled">Απενεργοποιημένο</string>
<string name="suggestions">Προτάσεις</string>
<string name="only_using_wifi">Μόνο με Wi-Fi</string>
<string name="suggestions_enable">Ενεργοποίηση προτάσεων</string>
<string name="download_slowdown_summary">Βοηθάει στην αποφυγή μπλοκαρίσματος της διεύθυνσης IP σου</string>
<string name="show_notification_new_chapters_on">Θα λαμβάνεις ειδοποιήσεις για ενημερώσεις σχετικά με τα manga που διαβάζεις</string>
<string name="show_notification_new_chapters_off">Δεν θα λαμβάνεις ειδοποιήσεις αλλά νέα κεφάλαια θα φαίνονται στην λίστα</string>
<string name="state_upcoming">Ανερχόμενο</string>
<string name="by_name_reverse">Όνομα - αντεστρεμένα</string>
<string name="advanced">Για προχωρημένους</string>
<string name="default_section">Προεπιλεγμένο τμήμα</string>
<string name="catalog">Κατάλογος</string>
<string name="manage_sources">Διαχείριση πηγών</string>
<string name="content_type_comics">Comics</string>
<string name="content_type_manga">Manga</string>
<string name="content_type_hentai">Hentai</string>
<string name="content_type_other">Άλλα</string>
<string name="source_summary_pattern">%1$s, %2$s</string>
<string name="sources_catalog">Κατάλογος πηγών</string>
<string name="source_enabled">Η πηγή είναι ενεργοποιημένη</string>
<string name="no_manga_sources_catalog_text">Δεν υπάρχουν διαθέσιμες πηγές σε αυτό το τμήμα, ή πιθανώς όλες έχουν προστεθεί.
\nΜείνετε σε επαφή</string>
<string name="no_manga_sources_found">Η αναζήτηση σας δεν επέφερε διαθέσιμα manga</string>
<string name="invalid_port_number">Μη έγκυρος αριθμός θύρας</string>
<string name="user_agent">Επικεφαλίδα UserAgent</string>
<string name="history_cleared">Το ιστορικό καθαρίστηκε</string>
<string name="no_bookmarks_summary">Μπορείς να χρησιμοποιήσεις σελιδοδείκτη όσο διαβάζεις manga</string>
<string name="random">Τυχαίο</string>
<string name="exit_confirmation">Επιβεβαίωση εξόδου</string>
<string name="saved_manga">Αποθηκευμένα manga</string>
<string name="pages_cache">Προσωρινή μνήμη σελίδων</string>
<string name="other_cache">Προσωρινή μνήμη άλλων</string>
<string name="removed_from_favourites">Αφαιρέθηκε από τα αγαπημένα</string>
<string name="no_chapters">Δεν έχει κεφάλαια</string>
<string name="reader_info_pattern">Κεφ. %1$d/%2$d Σελ. %3$d/%4$d</string>
<string name="reader_info_bar">Εμφάνιση μπάρας πληροφοριών στο εργαλείο ανάγνωσης</string>
<string name="import_completed_hint">Μπορείς να διαγράψεις το αρχικό αρχείο από τον χώρο αποθήκευσης για να απελευθερώσεις χώρο</string>
<string name="import_will_start_soon">Η εισαγωγή θα ξεκινήσει σύντομα</string>
<string name="reset">Επαναφορά</string>
<string name="color_correction_hint">Οι επιλεγμένες ρυθμίσεις χρώματος θα αποθηκευτούν για αυτό το manga</string>
<string name="compact">Συμπαγής</string>
<string name="language">Γλώσσα</string>
<string name="scrobbling_empty_hint">Για να καταγράψεις την πρόοδο σου, επίλεξε Μενού → Καταγραφή στην οθόνη λεπτομερειών για το manga.</string>
<string name="services">Υπηρεσίες</string>
<string name="allow_unstable_updates">Επίτρεψε ασταθείς ενημερώσεις</string>
<string name="sources_reorder_tip">Πάτα παρατεταμένα ένα στοιχείο για να το αναταξινομήσεις</string>
<string name="settings_apply_restart_required">Κάνε επανεκκίνηση της εφαρμογής για να εφαρμοστούν οι αλλαγές, παρακαλώ</string>
<string name="comics_archive_import_description">Μπορείς να επιλέξεις ένα ή περισσότερα .cbz ή .zip αρχεία, κάθε ένα θα αναγνωρίζεται ως ξεχωριστό manga.</string>
<string name="speed">Ταχύτητα</string>
<string name="restore_backup_description">Εισήγαγε ένα αντίγραφο ασφαλείας δεδομένων χρήστη</string>
<string name="show_on_shelf">Εμφάνιζε στο Ράφι</string>
<string name="find_similar">Βρες παρόμοια</string>
<string name="ignore_ssl_errors">Αγνόησε σφάλματα SSL</string>
<string name="no_thanks">Όχι ευχαριστώ</string>
<string name="cancel_all_downloads_confirm">Όλες οι τρέχουσες λήψεις θα ακυρωθούν, και δεδομένα που έχουν ληφθεί μερικώς θα χαθούν</string>
<string name="downloads_cancelled">Οι λήψεις ακυρώθηκαν</string>
<string name="translations">Μεταφράσεις</string>
<string name="proxy">Διακομιστής μεσολάβησης</string>
<string name="images_proxy_title">Διακομιστής μεσολάβησης βελτιστοποίησης εικόνων</string>
<string name="invert_colors">Αντιστροφή χρωμάτων</string>
<string name="username">Όνομα χρήστη</string>
<string name="network">Δίκτυο</string>
<string name="data_and_privacy">Δεδομένα και ιδιωτικότητα</string>
<string name="restore_summary">Επανάφερε κάποιο αντίγραφο ασφαλείας</string>
<string name="webtoon_zoom_summary">Επίτρεψε την χειρονομία μεγέθυνσης στην λειτουργία Webtoon</string>
<string name="show_pages_numbers_summary">Εμφάνιζε τους αριθμούς των σελίδων στην κάτω γωνία</string>
<string name="pages_animation_summary">Δείχνε την κίνηση των σελίδων κατά την αλλαγή τους</string>
<string name="detect_reader_mode">Αυτόματη αναγνώριση κατάλληλης λειτουργίας ανάγνωσης</string>
<string name="bookmarks_removed">Οι σελιδοδείκτες αφαιρέθηκαν</string>
<string name="no_manga_sources">Δεν υπάρχουν πηγές για manga</string>
<string name="no_manga_sources_text">Ενεργοποίησε πηγές για manga ώστε να διαβάσεις manga διαδικτυακά</string>
<string name="reorder">Αναταξινόμηση</string>
<string name="empty">Άδειο</string>
<string name="explore">Εξερεύνησε</string>
<string name="confirm_exit">Πάτα Πίσω ξανά για να επιστρέψεις στην προηγούμενη οθόνη</string>
<string name="exit_confirmation_summary">Πάτα Πίσω δύο φορές για να βγεις από την εφαρμογή</string>
<string name="storage_usage">Χρησιμοποίηση χώρου αποθήκευσης</string>
<string name="available">Διαθέσιμο</string>
<string name="memory_usage_pattern">%s - %s</string>
<string name="options">Επιλογές</string>
<string name="not_found_404">Το περιεχόμενο δεν βρέθηκε, και πιθανώς να έχει αφαιρεθεί</string>
<string name="incognito_mode">Λειτουργία Incognito</string>
<string name="automatic_scroll">Αυτόματη ολίσθηση</string>
<string name="comics_archive">Αρχειοθήκη για κόμικς</string>
<string name="folder_with_images">Φάκελος με εικόνες</string>
<string name="importing_manga">Εισαγωγή manga σε εξέλιξη</string>
<string name="import_completed">Η εισαγωγή ολοκληρώθηκε</string>
<string name="feed">Τροφοδοτικό</string>
<string name="history_shortcuts">Εμφάνιζε συντομεύσεις σχετικά με πρόσφατα manga</string>
<string name="history_shortcuts_summary">Κάνε πρόσφατα manga διαθέσιμα πατώντας παρατεταμένα το εικονίδιο της εφαρμογής</string>
<string name="contrast">Αντίθεση</string>
<string name="reader_control_ltr_summary">Το πάτημα της δεξιάς πλευράς, ή του κουμπιού μείωσης της έντασης, πάντα προχωράει στην επόμενη σελίδα</string>
<string name="reader_control_ltr">Εργονομικός χειρισμός του εργαλείου ανάγνωσης</string>
<string name="color_correction">Χρωματική διόρθωση</string>
<string name="brightness">Φωτεινότητα</string>
<string name="text_unsaved_changes_prompt">Αποθήκευση ή αναίρεση των μη αποθηκευμένων επιλογών;</string>
<string name="discard">Απόρριψη</string>
<string name="error_no_space_left">Δεν έχει μείνει επαρκής αποθηκευτικός χώρος στην συσκευή</string>
<string name="reader_slider">Εμφάνιζε τον σύρτη αλλαγής σελίδων</string>
<string name="webtoon_zoom">Μεγέθυνση Γουέμπτουν</string>
<string name="different_languages">Διαφορετικές γλώσσες</string>
<string name="network_unavailable">Δεν υπάρχει διαθέσιμο δίκτυο</string>
<string name="server_error">Σφάλμα διακομιστή (%1$d). Παρακαλώ ξαναπροσπαθήστε αργότερα</string>
<string name="clear_new_chapters_counters">Επιπλέον, σβήσε πληροφορίες περί νέων κεφαλαίων</string>
<string name="network_unavailable_hint">Άνοιξε το Wi-Fi ή τα δεδομένα για να διαβάσεις manga διαδικτυακώς</string>
<string name="welcome_text">Παρακαλώ επίλεξε ποιες πηγές περιεχομένου θα ήθελες να ενεργοποιήσεις. Αυτό μπορεί να ρυθμιστεί ναι αργότερα από τις ρυθμίσεις</string>
<string name="sync_auth">Συνδέσου στον λογαριασμό συγχρονισμού</string>
<string name="downloads_settings_info">Μπορείς να ενεργοποιήσεις την καθυστέρηση λήψεων για κάθε πηγή manga ξεχωριστά μέσω των ρυθμίσεων των πηγών αν αντιμετωπίζεις προβλήματα με μπλοκάρισμα από πλευράς του διακομιστή</string>
<string name="details_button_tip">Πάτα παρατεταμένα το κουμπί Διάβασε για να δεις περαιτέρω επιλογές</string>
<string name="prefetch_content">Προφόρτωση περιεχομένου</string>
<string name="skip">Προσπέραση</string>
<string name="restore">Επαναφορά</string>
<string name="backup_date_">Ημερομηνία δημιουργίας αντιγράφου ασφαλείας: %s</string>
<string name="content_rating">Ηλικιακή βαθμολογία περιεχομένου</string>
<string name="genres_exclude">Να μην συμπεριλαμβάνονται τα είδη</string>
<string name="rating_safe">Ασφαλές</string>
<string name="rating_suggestive">Άσεμνο</string>
<string name="rating_adult">Για ενήλικες</string>
<string name="clear_source_cookies_summary">Σβήσε τα cookies για τους επιλεγμένους τομέες μόνο. Στις περισσότερες περιπτώσεις θα ακυρωθεί η εξουσιοδότηση</string>
<string name="online_variant">Διαδικτυακή έκδοση</string>
<string name="keep_screen_on">Κράτα την οθόνη ανοιχτή</string>
<string name="keep_screen_on_summary">Να μην κλείνει η οθόνη κατά την ανάγνωση manga</string>
<string name="lock_screen_rotation">Κλείδωσε την περιστροφή οθόνης</string>
<string name="allow_unstable_updates_summary">Λάβε ειδοποιήσεις για ασταθείς εκδόσεις</string>
<string name="download_started">Η λήψη ξεκίνησε</string>
<string name="manga_list">Λίστα manga</string>
<string name="theme_name_dynamic">Δυναμικό</string>
<string name="disable_nsfw">Απενεργοποιήση NSFW</string>
<string name="got_it">Έγινε</string>
<string name="default_tab">Προεπιλεγμένη καρτέλα</string>
<string name="manga_branch_title_template">%1$s (%2$s)</string>
<string name="download_option_all_chapters">Όλα τα μεταφρασμένα κεφάλαια %s</string>
<string name="download_option_whole_manga">Ολόκληρο το manga</string>
<string name="download_option_first_n_chapters">Πρώτα %s</string>
<string name="download_option_next_unread_n_chapters">Τα επόμενα μη αναγνωσμένα %s</string>
<string name="download_option_all_unread">Όλα τα μη αναγνωσμένα κεφάλαια</string>
<string name="download_option_all_unread_b">Όλα τα μην αναγνωσμένα κεφάλαια (%s)</string>
<string name="download_option_manual_selection">Χειροκίνητη επιλογή κεφαλαίων</string>
<string name="description">Περιγραφή</string>
<string name="this_month">Αυτόν τον μήνα</string>
<string name="voice_search">Φωνητική αναζήτηση</string>
<string name="related_manga">Σχετικά manga</string>
<string name="color_light">Φωτεινό</string>
<string name="color_white">Άσπρο</string>
<string name="color_black">Μαύρο</string>
<string name="background">Παρασκήνιο</string>
<string name="data_not_restored">Τα δεδομένα δεν επαναφέρθηκαν</string>
<string name="suggestions_wifi_only_summary">Να μην ενημερώνονται οι προτιμήσεις κατά την χρήση μετρημένων συνδέσεων δικτύου</string>
<string name="search_hint">Εισήγαγε τίτλο manga, είδος, ή το όνομα πηγής</string>
<string name="progress">Πρόοδος</string>
<string name="order_added">Προστέθηκε</string>
<string name="manage_categories">Διαχείριση κατηγοριών</string>
<string name="view_list">Δες την λίστα</string>
<string name="show">Εμφάνισε</string>
<string name="downloaded">Ληφθέντα</string>
<string name="too_many_requests_message">Υπερβολικά πολλά αιτήματα. Ξαναδοκιμάστε αργότερα</string>
<string name="manage">Διαχείριση</string>
<string name="no_bookmarks_yet">Δεν έχεις κάποιον σελιδοδείκτη ακόμα</string>
<string name="share_logs">Κοινοποίηση logs</string>
<string name="custom_directory">Directory της επιλογής σου</string>
<string name="no_access_to_file">Δεν έχεις πρόσβαση σε αυτό το αρχείο ή directory</string>
<string name="local_manga_directories">Directory για τοπικά manga</string>
<string name="captcha_required_summary">%s απαιτεί την επίλυση ενός CAPTCHA για να λειτουργήσει κανονικά</string>
<string name="password">Κωδικός</string>
<string name="authorization_optional">Εξουσιοδότηση (προαιρετική)</string>
<string name="source_disabled">Η πηγή είναι απενεργοποιημένη</string>
<string name="grayscale">Κλίμακα του γκρι</string>
<string name="globally">Σε όλη την έκταση της εφαρμογής</string>
<string name="this_manga">Αυτό το manga</string>
<string name="color_correction_apply_text">Αυτές οι ρυθμίσεις μπορούν να εφαρμοστούν σε όλη την έκταση της βιβλιοθήκης ή μόνο για αυτό το manga. Αν εφαρμοστούν σε όλη την έκταση της βιβλιοθήκης, οι ξεχωριστές ρυθμίσεις δεν θα επηρεαστούν.</string>
<string name="apply">Εφαρμογή</string>
<string name="type">Τύπος</string>
<string name="address">Διεύθυνση</string>
<string name="port">Θύρα</string>
<string name="mark_as_current">Σημείωσε ως τρέχων</string>
<string name="show_suspicious_content">Εμφάνιζε ύποπτο περιεχόμενο</string>
<string name="color_theme">Χρωματικός συνδυασμός</string>
<string name="state_abandoned">Παρατήθηκε</string>
<string name="sync_settings">Ρυθμίσεις συγχρονισμού</string>
<string name="server_address">Διεύθυνση διακομιστή</string>
<string name="manual">Χειροκίνητα</string>
<string name="available_d">Διαθέσιμα: %1$d</string>
<string name="disable_nsfw_summary">Απενεργοποίηση NSFW πηγών και απόκρυψη manga για ενηλίκους από την λίστα αν είναι δυνατό</string>
<string name="speed_value">x%.1f</string>
<string name="mirror_switching">Αυτόματη επιλογή mirror</string>
<string name="pause">Παύση</string>
<string name="resume">Συνέχιση</string>
<string name="paused">Σε παύση</string>
<string name="cancel_all">Ακύρωση όλων</string>
<string name="downloads_wifi_only">Λήψη μόνο μέσω Wi-Fi</string>
<string name="downloads_wifi_only_summary">Σταματημός της λήψης με την αλλαγή σε δεδομένα</string>
<string name="suggestion_manga">Προτάσεις: %s</string>
<string name="suggestions_notifications_summary">Εμφάνιζε μερικές φορές ειδοποιήσεις με προτεινόμενα manga</string>
<string name="more">Περισσότερα</string>
<string name="enable">Ενεργοποίησε</string>
<string name="remove_completed">Αφαίρεσε τα ολοκληρωμένα</string>
<string name="languages">Γλώσσες</string>
<string name="error_filter_locale_genre_not_supported">Το φιλτράρισμα δια είδους και τοποθεσίας δεν υποστηρίζεται από αυτήν την πηγή</string>
<string name="error_filter_states_genre_not_supported">Το φιλτράρισμα δια είδους και κατάστασης δεν υποστηρίζεται από αυτήν την πηγή</string>
<string name="invalid_value_message">Μη έγκυρη τιμή</string>
<string name="error_corrupted_file">Μη έγκυρα δεδομένα επιστρέφονται ή το αρχείο είναι διεφθαρμένο</string>
<string name="in_progress">Σε εξέλιξη</string>
<string name="on_device">Στην συσκευή</string>
<string name="directories">Directories</string>
<string name="main_screen_sections">Τμήματα αρχικής οθόνης</string>
<string name="to_top">Στην κορυφή</string>
<string name="moved_to_top">Κινήθηκε στην κορυφή</string>
<string name="genres_search_hint">Ξεκίνα να γράφεις το όνομα του είδους</string>
<string name="state_paused">Σε παύση</string>
<string name="zoom_out">Σμίκρυνση</string>
<string name="zoom_in">Μεγέθυνση</string>
<string name="reader_zoom_buttons">Εμφάνιζε κουμπιά για μεγέθυνση</string>
<string name="reader_zoom_buttons_summary">Εμφάνιση κουμπιών μεγέθυνσης στην κάτω δεξιά γωνία ή όχι</string>
<string name="reader_optimize">Μείωση κατανάλωσης μνήμης (beta)</string>
<string name="mark_as_completed">Σημείωσε ως ολοκληρωμένο</string>
<string name="mark_as_completed_prompt">Σημείωση του επιλεγμένου manga ως ολοκληρωμένου;
\n
\nΠροσοχή: η πρόοδος σου θα χαθεί.</string>
<string name="disable_battery_optimization_summary_downloads">Ενδέχεται να βοηθήσει με την εκκίνηση της λήψης αν αντιμετωπίζεις προβλήματα σχετικά με αυτήν</string>
<string name="categories_delete_confirm">Είσαι σίγουρος πως θες να διαγράψεις τις επιλεγμένες αγαπημένες κατηγορίες;
\nΌλα τα manga που ανήκουν σε αυτές θα χαθούν, και αυτό είναι μη αναστρέψιμο.</string>
<string name="downloads_resumed">Οι λήψεις έχουν ξαναξεκινήσει</string>
<string name="downloads_paused">Οι λήψεις παύθηκαν</string>
<string name="remove_completed_downloads_confirm">Το ιστορικό λήψεων σου θα διαγραφεί</string>
<string name="text_downloads_list_holder">Δεν έχεις κάποια λήψη</string>
<string name="downloads_removed">Οι λήψεις αφαιρέθηκαν</string>
<string name="suggestions_enable_prompt">Θέλεις να λαμβάνεις εξατομικευμένες προτάσεις για manga;</string>
<string name="web_view_unavailable">WebView μη διαθέσιμο: κοίτα αν κάποιος πάροχος WebView είναι εγκατεστημένο.</string>
<string name="manga_error_description_pattern">Πληροφορίες σφάλματος:&lt;br&gt;&lt;tt&gt;%1$s&lt;/tt&gt;&lt;br&gt;&lt;br&gt;1. Προσπάθησε να &lt;a href=%2$s&gt;ανοίξεις το manga μέσω ενός περιηγητή&lt;/a&gt; για να βεβαιωθείς για την διαθεσιμότητα του στην πηγή.&lt;br&gt;2. Βεβαιώσου πως χρησιμοποιείς την &lt;a href=kotatsu://about&gt;πιο πρόσφατη έκδοση του Kotatsu.&lt;/a&gt;&lt;br&gt;3. Αν είναι διαθέσιμο, στείλε αναφορά του σφάλματος στους δημιουργούς.</string>
<string name="clear_network_cache">Καθάρισε προσωρινή μνήμη δικτύου</string>
<string name="images_procy_description">Χρησιμοποίησε την υπηρεσία wsrv.nl για να μειώσεις την κίνηση δικτύου και να αυξήσεις την ταχύτητα φόρτωσης εικόνων αν είναι δυνατό</string>
<string name="reader_info_bar_summary">Εμφάνιζε την ώρα και την πρόοδο στο πάνω μέρος της οθόνης</string>
<string name="enable_logging">Ενεργοποίηση καταγραφής logs</string>
<string name="pick_custom_directory">Διάλεξε directory της επιλογής σου</string>
<string name="enable_logging_summary">Κατάγραψε μερικές δράσεις που θα προορίζονται για την εξφαλμάτωση. Μην το ενεργοποιήσεις αν δεν είσαι βέβαιος για το τι κάνεις</string>
<string name="show_in_grid_view">Εμφάνιζε με μορφή πλέγματος</string>
<string name="mirror_switching_summary">Αυτόματη αλλαγή τομέων για πήγες manga σε περίπτωση σφαλμάτων αν υπάρχει διαθεσιμότητα mirror</string>
<string name="folder_with_images_import_description">Μπορείς να επιλέξεις ένα directory με φακέλους αρχειοθέτησης ή εικόνες. Κάθε φάκελος αρχειοθέτησης (ή subdirectory) θα αναγνωρίζεται ως κεφάλαιο.</string>
<string name="sync_host_description">Μπορείς να χρησιμοποιήσεις έναν self-hosted διακομιστή συγχρονισμού, ή έναν από τους προεπιλεγμένους. Μην πειράξεις αυτή την ρύθμιση αν δεν ξέρεις τι κάνεις.</string>
<string name="sync_auth_hint">Μπορείς να συνδεθείς σε έναν προϋπάρχον λογαριασμό ή να φτιάξεις έναν καινούριο</string>
<string name="color_dark">Σκοτεινό</string>
<string name="data_not_restored_text">Βεβαιώσου πως έχεις επιλέξει το σωστό αντίγραφο ασφαλείας</string>
<string name="tracker_wifi_only_summary">Να μην γίνεται έλεγχος για νέα κεφάλαια κατά την χρήση μετρημένων συνδέσεων δικτύου</string>
<string name="unknown">Άγνωστο</string>
<string name="related_manga_summary">Εμφάνιζε μία λίστα σχετικών manga. Υπάρχει το ενδεχόμενο ανακρίβειας ή πλήρης απώλειας</string>
<string name="items_limit_exceeded">Δεν μπορούν να προστεθούν περαιτέρω στοιχεία</string>
<string name="reader_optimize_summary">Μείωση της ποιότητας των άφαντων σελίδων για την μείωση της χρησιμοποιούμενης μνήμης</string>
<string name="state">Κατάσταση</string>
<string name="error_multiple_genres_not_supported">Το φιλτράρισμα δια πολλών ειδών δεν υποστηρίζεται από αυτήν την πηγή manga</string>
<string name="error_multiple_states_not_supported">Το φιλτράρισμα δια πολλών καταστάσεων δεν υποστηρίζεται από αυτήν την πηγή manga</string>
<string name="error_search_not_supported">Η αναζήτηση δεν υποστηρίζεται από αυτήν την πηγή manga</string>
<string name="enhanced_colors_summary">Μειώνει την ένταση της χρωματικής ζώνης, αλλά μπορεί να επηρεάσει την επίδοση</string>
<string name="enhanced_colors">Λειτουργία χρώματος 32-bit</string>
<string name="suggest_new_sources">Να προτείνονται νέες πηγές μετά από ενημέρωση της εφαρμογής</string>
<string name="suggest_new_sources_summary">Εντολή για ενεργοποίηση καινούριων πηγών μετά την ενημέρωση της εφαρμογής</string>
<string name="list_options">Επιλογές λίστας</string>
<string name="by_relevance">Σχετικότητα</string>
<string name="categories">Κατηγορίες</string>
<string name="periodic_backups">Περιοδική δημιουργία αντιγράφων ασφαλείας</string>
<string name="backup_frequency">Συχνότητα δημιουργίας αντιγράφων ασφαλείας</string>
<string name="frequency_every_day">Κάθε μέρα</string>
<string name="frequency_every_2_days">Κάθε δύο μέρες</string>
<string name="frequency_once_per_week">Μία φορά την εβδομάδα</string>
<string name="frequency_twice_per_month">Δύο φορές τον μήνα</string>
<string name="frequency_once_per_month">Μία φορά τον μήνα</string>
<string name="periodic_backups_enable">Ενεργοποίηση περιοδικής δημιουργίας αντιγράφων ασφαλείας</string>
<string name="backups_output_directory">Directory όπου θα αποθηκεύονται τα αντίγραφα ασφαλείας</string>
<string name="last_successful_backup">Τελευταία επιτυχής δημιουργία αντιγράφου ασφαλείας: %s</string>
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%1$d από %2$d σέ</string>
<string name="edit_category">Επεξεργασία κατηγορίας</string>
<string name="tracking">Καταγραφή</string>
<string name="empty_favourite_categories">Χωρίς αγαπημένες κατηγορίες</string>
<string name="logout">Αποσύνδεση</string>
<string name="bookmarks">Σελιδοδείκτες</string>
<string name="bookmark_removed">Σελιδοδείκτης αφαιρέθηκε</string>
<string name="bookmark_added">Σελιδοδείκτης προστέθηκε</string>
<string name="undo">Αναίρεση</string>
<string name="removed_from_history">Αφαιρέθηκε από το ιστορικό</string>
<string name="detect_reader_mode_summary">Αυτόματη ανίχνευση αν το manga είναι webtoon</string>
<string name="status_planned">Προγραμματισμένο</string>
<string name="status_reading">Ανάγνωση</string>
<string name="status_re_reading">Επανάναγνωση</string>
<string name="status_completed">Ολοκληρώθηκε</string>
<string name="status_on_hold">Σε αναμονή</string>
<string name="status_dropped">Διακόπηκε</string>
<string name="disable_all">Απενεργοποίηση όλων</string>
<string name="use_fingerprint">Χρήση ανιχνευτή δακτυλικού αποτυπώματος αν διατίθεται</string>
<string name="show_reading_indicators_summary">Εμφάνιση ποσοστού ανάγνωσης στο ιστορικό και τα αγαπημένα</string>
<string name="name">Όνομα</string>
<string name="dns_over_https">DNS μέσω HTTPS</string>
<string name="default_mode">Προεπιλεγμένη λειτουργία</string>
<string name="disable_battery_optimization">Απενεργοποίηση βελτιστοποίησης μπαταρίας</string>
<string name="disable_battery_optimization_summary">Βοηθά στους ελέγχους ενημέρωσης στο παρασκήνιο</string>
<string name="crash_text">Κάτι πήγε στραβά. Παρακαλούμε υποβάλετε αναφορά σφάλματος στους προγραμματιστές για να μας βοηθήσετε να το διορθώσουμε.</string>
<string name="send">Αποστολή</string>
<string name="report">Αναφορά</string>
<string name="show_reading_indicators">Εμφάνιση δεικτών προόδου ανάγνωσης</string>
<string name="data_deletion">Διαγραφή δεδομένων</string>
<string name="show_all">Εμφάνιση όλων</string>
<string name="invalid_domain_message">Μη έγκυρο domain</string>
<string name="select_range">Επιλογή εύρους</string>
<string name="last_2_hours">Τελευταίες 2 ώρες</string>
<string name="edit">Επεξεργασία</string>
<string name="appwidget_shelf_description">Manga από τα αγαπημένα σας</string>
<string name="bookmark_add">Προσθήκη σελιδοδείκτη</string>
<string name="bookmark_remove">Αφαίρεση σελιδοδείκτη</string>
<string name="exclude_nsfw_from_history_summary">Manga που χαρακτηρίζονται ως NSFW δεν θα προστίθενται ποτέ στο ιστορικό και η πρόοδος σου δεν θα αποθηκεύεται</string>
<string name="clear_all_history">Εκκαθάριση όλου του ιστορικού</string>
<string name="appwidget_recent_description">Τα πρόσφατα διαβασμένα manga σου</string>
<string name="clear_cookies_summary">Μπορεί να βοηθήσει σε περίπτωση κάποιων προβλημάτων. Όλες οι εξουσιοδοτήσεις θα ακυρωθούν</string>
</resources>

View File

@@ -67,7 +67,7 @@
<string name="grid_size">Tamaño de la cuadrícula</string>
<string name="search_on_s">Buscar en %s</string>
<string name="delete_manga">Borrar manga</string>
<string name="text_delete_local_manga">¿Borrar \"%s\" del dispositivo permanentemente\?</string>
<string name="text_delete_local_manga">¿Borrar permanentemente \"%s\" del dispositivo?</string>
<string name="reader_settings">Ajustes del lector</string>
<string name="switch_pages">Cambiar de página</string>
<string name="taps_on_edges">Toques de borde</string>
@@ -98,7 +98,7 @@
<string name="manga_shelf">Estante</string>
<string name="recent_manga">Reciente</string>
<string name="pages_animation">Animación de página</string>
<string name="manga_save_location">Carpeta para descargas</string>
<string name="manga_save_location">Carpeta de descargas</string>
<string name="not_available">No disponible</string>
<string name="cannot_find_available_storage">No hay almacenamiento disponible</string>
<string name="other_storage">Otro almacenamiento</string>
@@ -107,7 +107,7 @@
<string name="favourites_category_empty">Categoría vacía</string>
<string name="read_later">Leer más tarde</string>
<string name="updates">Actualizaciones</string>
<string name="text_feed_holder">Aquí verás los nuevos episodios del manga que estás leyendo</string>
<string name="text_feed_holder">Aquí se muestran los nuevos capítulos de lo que está leyendo</string>
<string name="search_results">Resultados de la búsqueda</string>
<string name="new_version_s">Nueva versión: %s</string>
<string name="size_s">Tamaño: %s</string>
@@ -169,7 +169,7 @@
<string name="protect_application_subtitle">Introduce la contraseña que se requerirá cuando se inicie la aplicación</string>
<string name="confirm">Confirmar</string>
<string name="password_length_hint">La contraseña debe tener al menos 4 caracteres</string>
<string name="text_local_holder_secondary">Puedes guardarlo desde fuentes in línea o importarlo desde un archivo.</string>
<string name="text_local_holder_secondary">Guarda algo de un catálogo en línea o impórtalo desde un archivo.</string>
<string name="text_local_holder_primary">Todavía no tienes ningún manga guardado</string>
<string name="text_history_holder_secondary">Encuentra qué leer en la sección «Explorar»</string>
<string name="text_history_holder_primary">Lo que leas se mostrará aquí</string>
@@ -551,4 +551,8 @@
<string name="rating_adult">Adulto</string>
<string name="content_rating">Clasificación del contenido</string>
<string name="default_tab">Pestaña por defecto</string>
<string name="mark_as_completed">Marcar como completado</string>
<string name="mark_as_completed_prompt">¿Marcar el manga seleccionado como completamente leído?
\n
\nAdvertencia: el progreso de lectura actual se perderá.</string>
</resources>

View File

@@ -1,33 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="minutes_ago">
<item quantity="one">Il y a %1$d minute</item>
<item quantity="many">Il y a %1$d minutes</item>
<item quantity="other">Il y a %1$d minutes</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$d élément</item>
<item quantity="many">%1$d éléments</item>
<item quantity="other">%1$d éléments</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$d nouveau chapitre</item>
<item quantity="many">%1$d nouveaux chapitres</item>
<item quantity="other">%1$d nouveaux chapitres</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d chapitre</item>
<item quantity="many">%1$d chapitres</item>
<item quantity="other">%1$d chapitres</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">Il y a %1$d heure</item>
<item quantity="many">Il y a %1$d heures</item>
<item quantity="other">Il y a %1$d heures</item>
</plurals>
<plurals name="days_ago">
<item quantity="one">Il y a %1$d jour</item>
<item quantity="many">Il y a %1$d jours</item>
<item quantity="other">Il y a %1$d jours</item>
</plurals>
</resources>
<plurals name="minutes_ago">
<item quantity="one">Il y a %1$d minute</item>
<item quantity="many">Il y a %1$d minutes</item>
<item quantity="other">Il y a %1$d minutes</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$d élément</item>
<item quantity="many">%1$d éléments</item>
<item quantity="other">%1$d éléments</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$d nouveau chapitre</item>
<item quantity="many">%1$d nouveaux chapitres</item>
<item quantity="other">%1$d nouveaux chapitres</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d chapitre</item>
<item quantity="many">%1$d chapitres</item>
<item quantity="other">%1$d chapitres</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">Il y a %1$d heure</item>
<item quantity="many">Il y a %1$d heures</item>
<item quantity="other">Il y a %1$d heures</item>
</plurals>
<plurals name="days_ago">
<item quantity="one">Il y a %1$d jour</item>
<item quantity="many">Il y a %1$d jours</item>
<item quantity="other">Il y a %1$d jours</item>
</plurals>
<plurals name="months_ago">
<item quantity="one">Il y a %1$d mois</item>
<item quantity="many">Il y a %1$d mois</item>
<item quantity="other">Il y a %1$d mois</item>
</plurals>
</resources>

View File

@@ -528,4 +528,26 @@
<string name="backups_output_directory">Sauvegardes répertoire de sortie</string>
<string name="suggest_new_sources_summary">Prompt pour permettre des sources nouvellement ajoutées après la mise à jour de l\'application</string>
<string name="content_type_other">Autre</string>
<string name="state_upcoming">A venir</string>
<string name="welcome_text">S\'il vous plaît choisissez les sources que vous souhaitez activer. Cela peux aussi être fait plus tard dans les paramètres</string>
<string name="sync_auth">Connectez-vous pour synchroniser le compte</string>
<string name="skip">Passer</string>
<string name="restore">Restaurer</string>
<string name="content_rating">Note du contenu</string>
<string name="genres_exclude">Exclure les genres</string>
<string name="rating_safe">Sûr</string>
<string name="rating_adult">Adulte</string>
<string name="default_tab">Onglet par défaut</string>
<string name="color_correction_apply_text">Ces paramètres peuvent être appliqué globalement ou uniquement au manga actuel. S\'il est activé globalement il ne remplacera les paramètres individuel.</string>
<string name="globally">Globalement</string>
<string name="this_manga">Ce manga</string>
<string name="apply">Appliqué</string>
<string name="genres_search_hint">Commence a écrit un nom de genre</string>
<string name="downloads_settings_info">Vous pouvez activer la vitesse de téléchargement réduite individuellement pour chaque source de manga dans les paramètres si vous rencontrez des problèmes de bloquage avec le serveur.</string>
<string name="backup_date_">Date de sauvegarde: %s</string>
<string name="by_name_reverse">Nom réservé</string>
<string name="mark_as_completed">Marque comme terminé</string>
<string name="mark_as_completed_prompt">Marqué le manga sélectionné en terminé?
\n
\nAttention: la progression actuelle sera perdu.</string>
</resources>

View File

@@ -91,7 +91,7 @@
<string name="feed_will_update_soon">फीड अपडेट शीघ्र ही आरंभ होगा</string>
<string name="app_update_available">इस ऐप का नया संस्करण उपलब्ध हैं</string>
<string name="new_version_s">नया संस्करण: %s</string>
<string name="text_delete_local_manga">डिवाइस में से %s ko सदा के लिए निकाल दे\?</string>
<string name="text_delete_local_manga">डिवाइस से \"% s\" को स्थायी रूप से हटा दे?</string>
<string name="text_history_holder_primary">जो भी आप पढ़ोगे वे सब यहां दिखेगा</string>
<string name="delete_manga">मांगा को नष्ट करे</string>
<string name="notification_sound">सूचना की ध्वनि</string>

View File

@@ -6,20 +6,20 @@
<string name="error_occurred">Terjadi kesalahan</string>
<string name="network_error">Kesalahan jaringan</string>
<string name="details">Detail</string>
<string name="grid">Kisi</string>
<string name="list_mode">Mode daftar</string>
<string name="grid">Kotak</string>
<string name="list_mode">Gaya list</string>
<string name="settings">Pengaturan</string>
<string name="remote_sources">Sumber manga</string>
<string name="remote_sources">Sumber</string>
<string name="loading_">Memuat…</string>
<string name="computing_">Menghitung…</string>
<string name="chapter_d_of_d">Bab %1$d dari %2$d</string>
<string name="close">Tutup</string>
<string name="try_again">Coba lagi</string>
<string name="nothing_found">Hasil tidak ditemukan</string>
<string name="history_is_empty">Belum ada riwayat</string>
<string name="nothing_found">Tidak ketemu</string>
<string name="history_is_empty">Histori kosong</string>
<string name="read">Baca</string>
<string name="you_have_not_favourites_yet">Belum ada favorit</string>
<string name="add_to_favourites">Favoritkan ini</string>
<string name="add_to_favourites">Buat favorit</string>
<string name="add_new_category">Kategori baru</string>
<string name="add">Tambah</string>
<string name="save">Simpan</string>
@@ -36,8 +36,8 @@
<string name="popular">Populer</string>
<string name="updated">Diperbarui</string>
<string name="newest">Terbaru</string>
<string name="by_rating">Peringkat</string>
<string name="sort_order">Urutkan berdasarkan</string>
<string name="by_rating">Nilai</string>
<string name="sort_order">Urutkan</string>
<string name="filter">Filter</string>
<string name="theme">Tema</string>
<string name="light">Terang</string>
@@ -46,12 +46,12 @@
<string name="pages">Halaman</string>
<string name="clear">Bersihkan</string>
<string name="remove">Hapus</string>
<string name="clear_history">Bersihkan riwayat</string>
<string name="clear_history">Hapus histori</string>
<string name="delete">Hapus</string>
<string name="operation_not_supported">Tindakan ini tidak didukung</string>
<string name="text_file_not_supported">Pilih antara berkas ZIP atau CBZ.</string>
<string name="no_description">Tidak ada deskripsi</string>
<string name="_s_deleted_from_local_storage">\"%s\" dihapus dari penyimpanan lokal</string>
<string name="_s_deleted_from_local_storage">\"%s\" dihapus dari penyimpanan</string>
<string name="save_page">Simpan halaman</string>
<string name="page_saved">Disimpan</string>
<string name="share_image">Bagikan gambar</string>
@@ -67,8 +67,8 @@
<string name="switch_pages">Ganti halaman</string>
<string name="chapters">Bab</string>
<string name="list">Daftar</string>
<string name="detailed_list">Daftar terperinci</string>
<string name="text_clear_history_prompt">Bersihkan semua riwayat baca secara permanen\?</string>
<string name="detailed_list">Daftar rinci</string>
<string name="text_clear_history_prompt">Yakin ingin mereset history?</string>
<string name="webtoon">Webtoon</string>
<string name="read_mode">Mode baca</string>
<string name="volume_buttons">Tombol volume</string>

View File

@@ -1,27 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="new_chapters">
<item quantity="one">%1$d nuovo capitolo</item>
<item quantity="other">%1$d nuovi capitoli</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$d élément</item>
<item quantity="other">%1$d éléments</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d capitolo</item>
<item quantity="other">%1$d capitoli</item>
</plurals>
<plurals name="minutes_ago">
<item quantity="one">%1$d minuto fa</item>
<item quantity="other">%1$d minuti fa</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">%1$d ora fa</item>
<item quantity="other">%1$d ore fa</item>
</plurals>
<plurals name="days_ago">
<item quantity="one">%1$d giorno fa</item>
<item quantity="other">%1$d giorni fa</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$d nuovo capitolo</item>
<item quantity="many">%1$d nuovi capitoli</item>
<item quantity="other" />
</plurals>
<plurals name="items">
<item quantity="one">%1$d elemento</item>
<item quantity="many">%1$d elementi</item>
<item quantity="other"/>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d capitolo</item>
<item quantity="many">%1$d capitoli</item>
<item quantity="other" />
</plurals>
<plurals name="minutes_ago">
<item quantity="one">%1$d minuto fa</item>
<item quantity="many">%1$d minuti fa</item>
<item quantity="other" />
</plurals>
<plurals name="hours_ago">
<item quantity="one">%1$d ora fa</item>
<item quantity="many">%1$d ore fa</item>
<item quantity="other" />
</plurals>
<plurals name="days_ago">
<item quantity="one">%1$d giorno fa</item>
<item quantity="many">%1$d giorni fa</item>
<item quantity="other" />
</plurals>
<plurals name="months_ago">
<item quantity="one">%1$d mese fa</item>
<item quantity="many">%1$d mesi fa</item>
<item quantity="other"/>
</plurals>
</resources>

View File

@@ -48,7 +48,7 @@
<string name="list_mode">Modalità elenco</string>
<string name="grid">Griglia</string>
<string name="detailed_list">Elenco dettagliato</string>
<string name="text_delete_local_manga">Vuoi davvero eliminare «%s» dalla memoria locale del tuo dispositivo\?</string>
<string name="text_delete_local_manga">Vuoi davvero eliminare «%s» dalla memoria locale del tuo dispositivo?</string>
<string name="_s_deleted_from_local_storage">«%s» eliminato dall\'archiviazione locale</string>
<string name="list">Lista</string>
<string name="chapters">Capitoli</string>
@@ -113,11 +113,11 @@
<string name="other_storage">Altro spazio di archiviazione</string>
<string name="cannot_find_available_storage">Impossibile trovare uno spazio di archiviazione disponibile</string>
<string name="not_available">Non disponibile</string>
<string name="manga_save_location">Posizione per lo scaricamento dei manga</string>
<string name="manga_save_location">Cartella di scaricamento</string>
<string name="pages_animation">Animazione delle pagine</string>
<string name="recent_manga">Manga recenti</string>
<string name="manga_shelf">Scaffale da manga</string>
<string name="text_local_holder_secondary">Puoi salvarlo da fonti in linea o importarlo da un file.</string>
<string name="text_local_holder_secondary">Salva qualcosa da un catalogo online o importalo da un file.</string>
<string name="text_local_holder_primary">Non hai ancora salvato nessun manga</string>
<string name="text_history_holder_secondary">Trova cosa leggere nella sezione «Esplora»</string>
<string name="text_history_holder_primary">I manga che stai leggendo saranno visualizzati qui</string>
@@ -543,4 +543,16 @@
<string name="got_it">Ho capito</string>
<string name="comics_archive_import_description">Puoi selezionare uno o più file .cbz o .zip, ogni file sarà riconosciuto come un manga a parte.</string>
<string name="show_on_shelf">Mostra sullo Scaffale</string>
<string name="state_upcoming">Prossime</string>
<string name="by_name_reverse">Nome invertito</string>
<string name="content_rating">Classificazione dei contenuti</string>
<string name="genres_exclude">Escludi generi</string>
<string name="rating_safe">Sicuro</string>
<string name="rating_suggestive">Suggestivi</string>
<string name="rating_adult">Adulto</string>
<string name="default_tab">Scheda predefinita</string>
<string name="mark_as_completed">Segna come completo</string>
<string name="mark_as_completed_prompt">Segna il manga selezionato come completamente letto?
\n
\nAttenzione: l\'attuale avanzamento della lettura sarà perso.</string>
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="new_chapters">
<item quantity="other">%1$d bab baharu</item>
</plurals>
<plurals name="chapters">
<item quantity="other">%1$d bab</item>
</plurals>
<plurals name="minutes_ago">
<item quantity="other">%1$d minit lalu</item>
</plurals>
<plurals name="hours_ago">
<item quantity="other">%1$d jam lalu</item>
</plurals>
<plurals name="days_ago">
<item quantity="other">%1$d hari lalu</item>
</plurals>
<plurals name="months_ago">
<item quantity="other">%1$d bulan lalu</item>
</plurals>
<plurals name="items">
<item quantity="other">%1$d item</item>
</plurals>
</resources>

View File

@@ -0,0 +1,311 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="enter_password">Masukkan kata laluan</string>
<string name="protect_application_summary">Minta kata laluan ketika memulakan Kotatsu</string>
<string name="repeat_password">Ulang kata laluan</string>
<string name="zoom_mode_fit_center">Muat di tengah</string>
<string name="create_category">Kategori baharu</string>
<string name="scale_mode">Mod skala</string>
<string name="zoom_mode_fit_height">Muat ke ketinggian</string>
<string name="favourites">Kegemaran</string>
<string name="history">Sejarah</string>
<string name="network_error">Ralat rangkaian</string>
<string name="details">Perincian</string>
<string name="chapters">Bab</string>
<string name="list">Senarai</string>
<string name="detailed_list">Senarai terperinci</string>
<string name="grid">Grid</string>
<string name="list_mode">Mod senarai</string>
<string name="settings">Tetapan</string>
<string name="remote_sources">Sumber Manga</string>
<string name="loading_">Memuat…</string>
<string name="computing_">Mengira…</string>
<string name="chapter_d_of_d">Bab %1$d daripada %2$d</string>
<string name="close">Tutup</string>
<string name="try_again">Cuba semula</string>
<string name="clear_history">Padam sejarah</string>
<string name="history_is_empty">Tiada sejarah lagi</string>
<string name="read">Baca</string>
<string name="add_new_category">Kategori baharu</string>
<string name="add">Tambah</string>
<string name="save">Simpan</string>
<string name="share">Kongsi</string>
<string name="create_shortcut">Buat pintasan…</string>
<string name="search">Cari</string>
<string name="search_manga">Cari manga</string>
<string name="manga_downloading_">Memuat turun…</string>
<string name="download_complete">Dimuat turun</string>
<string name="downloads">Muat turun</string>
<string name="by_name">Nama</string>
<string name="popular">Popular</string>
<string name="updated">Dikemaskini</string>
<string name="newest">Terbaharu</string>
<string name="by_rating">Rating</string>
<string name="sort_order">Turutan isihan</string>
<string name="filter">Tapis</string>
<string name="light">Terang</string>
<string name="dark">Gelap</string>
<string name="automatic">Ikut sistem</string>
<string name="pages">Muka surat</string>
<string name="clear">Kosongkan</string>
<string name="text_clear_history_prompt">Kosongkan semua sejarah pembacaan selama-lamanya?</string>
<string name="remove">Buang</string>
<string name="_s_deleted_from_local_storage">\"%s\" dibuang daripada storan tempatan</string>
<string name="save_page">Simpan muka surat</string>
<string name="share_image">Kongsi imej</string>
<string name="_import">Import</string>
<string name="text_file_not_supported">Pilih antara fail ZIP atau CBZ.</string>
<string name="no_description">Tiada huraian</string>
<string name="clear_pages_cache">Kosongkan cache muka surat</string>
<string name="standard">Standard</string>
<string name="webtoon">Webtoon</string>
<string name="_continue">Sambung</string>
<string name="error">Ralat</string>
<string name="clear_search_history">Kosongkan sejarah carian</string>
<string name="search_history_cleared">Dikosongkan</string>
<string name="gestures_only">Gerak isyarat sahaja</string>
<string name="internal_storage">Storan dalaman</string>
<string name="external_storage">Storan luaran</string>
<string name="app_update_available">Sebuah versi baru apl tersedia</string>
<string name="open_in_browser">Buka dalam pelayar web</string>
<string name="large_manga_save_confirm">Manga ini mempunyai %s. Simpan kesemuanya?</string>
<string name="save_manga">Simpan</string>
<string name="notifications">Notifikasi</string>
<string name="new_chapters">Bab baharu</string>
<string name="notification_sound">Suara pemberitahuan</string>
<string name="light_indicator">Penunjuk LED</string>
<string name="vibration">Getaran</string>
<string name="remove_category">Buang</string>
<string name="text_history_holder_primary">Apa yang anda baca akan dipaparkan di sini</string>
<string name="text_shelf_holder_primary">Manga anda akan dipaparkan di sini</string>
<string name="text_shelf_holder_secondary">Cari apa yang boleh dibaca melalui seksyen «Jelajah»</string>
<string name="text_local_holder_primary">Simpan sesuatu dahulu</string>
<string name="text_local_holder_secondary">Simpan sesuatu daripada katalog dalam talian atau import daripada fail.</string>
<string name="manga_shelf">Rak</string>
<string name="recent_manga">Terbaharu</string>
<string name="cannot_find_available_storage">Tiada storan tersedia</string>
<string name="other_storage">Storan lain</string>
<string name="done">Tamat</string>
<string name="favourites_category_empty">Kategori kosong</string>
<string name="read_later">Baca kemudian</string>
<string name="search_results">Hasil carian</string>
<string name="track_sources">Cari kemas kini</string>
<string name="protect_application">Lindung apl</string>
<string name="passwords_mismatch">Kata laluan tidak padan</string>
<string name="about">Tentang</string>
<string name="app_version">Versi %s</string>
<string name="check_for_updates">Semak kemas kini</string>
<string name="no_update_available">Tiada kemas kini tersedia</string>
<string name="right_to_left">Kanan-ke-kiri</string>
<string name="zoom_mode_fit_width">Muat ke kelebaran</string>
<string name="zoom_mode_keep_start">Kekalkan di permulaan</string>
<string name="black_dark_theme">Hitam</string>
<string name="black_dark_theme_summary">Menggunakan kurang kuasa pada skrin AMOLED</string>
<string name="backup_restore">Penyandaran dan pemulihan</string>
<string name="create_backup">Buat penyandaran data</string>
<string name="restore_backup">Pulihkan daripada sandaran</string>
<string name="data_restored">Dipulihkan</string>
<string name="preparing_">Bersedia…</string>
<string name="file_not_found">Fail tidak ditemui</string>
<string name="data_restored_success">Semua data telah dipulih</string>
<string name="data_restored_with_errors">Data telah dipulih, namun terdapat ralat</string>
<string name="just_now">Sebentar tadi</string>
<string name="yesterday">Semalam</string>
<string name="long_ago">Lama dahulu</string>
<string name="group">Kumpul</string>
<string name="today">Hari ini</string>
<string name="tap_to_try_again">Ketik untuk cuba semula</string>
<string name="silent">Senyap</string>
<string name="captcha_required">CAPTCHA diperlukan</string>
<string name="captcha_solve">Selesai</string>
<string name="clear_cookies">Kosongkan kuki</string>
<string name="cookies_cleared">Semua kuki telah dibuang</string>
<string name="clear_feed">Kosongkan siaran</string>
<string name="text_clear_updates_feed_prompt">Kosongkan semua sejarah kemas kini selama-lamanya?</string>
<string name="check_for_new_chapters">Semak untuk bab baharu</string>
<string name="reverse">Songsang</string>
<string name="sign_in">Log masuk</string>
<string name="auth_required">Log masuk untuk melihat kandungan ini</string>
<string name="next">Seterusnya</string>
<string name="protect_application_subtitle">Masukkan kata laluan untuk memulakan apl dengan</string>
<string name="confirm">Sah</string>
<string name="password_length_hint">Kata laluan mesti mempunyai 4 aksara atau lebih</string>
<string name="welcome">Selamat Datang</string>
<string name="read_more">Baca lagi</string>
<string name="auth_complete">Diizinkan</string>
<string name="auth_not_supported_by">Log masuk pada %s tidak disokong</string>
<string name="text_clear_cookies_prompt">Anda akan dilog keluar daripada semua sumber</string>
<string name="genres">Genre</string>
<string name="state_finished">Selesai</string>
<string name="state_ongoing">Sedang berlangsung</string>
<string name="system_default">Lalai</string>
<string name="exclude_nsfw_from_history">Kecualikan manga NSFW daripada sejarah</string>
<string name="show_pages_numbers">Muka surat bernombor</string>
<string name="enabled_sources">Sumber digunakan</string>
<string name="screenshots_policy">Polisi tangkapan skrin</string>
<string name="screenshots_allow">Benarkan</string>
<string name="screenshots_block_nsfw">Sekat pada NSFW</string>
<string name="screenshots_block_all">Sentiasa sekat</string>
<string name="suggestions">Pengesyoran</string>
<string name="suggestions_enable">Bolehkan pengesyoran</string>
<string name="suggestions_summary">Syor manga berdasarkan keutamaan</string>
<string name="text_suggestion_holder">Mula baca manga dan anda akan mendapat pengesyoran peribadi</string>
<string name="enabled">Dibolehkan</string>
<string name="disabled">Dilumpuhkan</string>
<string name="filter_load_error">Tidak boleh memuat senarai genre</string>
<string name="reset_filter">Set semula tapisan</string>
<string name="never">Jangan</string>
<string name="only_using_wifi">Hanya pada Wi-Fi</string>
<string name="always">Sentiasa</string>
<string name="preload_pages">Pramuat muka surat</string>
<string name="logged_in_as">Dilog masuk sebagai %s</string>
<string name="nsfw">18+</string>
<string name="various_languages">Pelbagai bahasa</string>
<string name="search_chapters">Cari bab</string>
<string name="chapters_empty">Tiada bab dalam manga ini</string>
<string name="percent_string_pattern">%1$s%%</string>
<string name="appearance">Penampilan</string>
<string name="suggestions_updating">Pengemaskinian pengesyoran</string>
<string name="suggestions_excluded_genres_summary">Tentukan genre yang anda tidak mahu lihat dalam pengesyoran</string>
<string name="text_delete_local_manga_batch">Buang item yang dipilih daripada peranti selama-lamanya?</string>
<string name="removal_completed">Pembuangan selesai</string>
<string name="local_manga_processing">Pemprosesan manga disimpan</string>
<string name="canceled">Dibatalkan</string>
<string name="account_already_exists">Akaun telahpun wujud</string>
<string name="back">Kembali</string>
<string name="sync">Penyegerakkan</string>
<string name="sync_title">Segerakkan data anda</string>
<string name="email_enter_hint">Masukkan email anda untuk menyambung</string>
<string name="hide">Sembunyi</string>
<string name="new_sources_text">Sumber manga baharu tersedia</string>
<string name="check_new_chapters_title">Semak untuk bab baharu dan beritahu mengenainya</string>
<string name="show_notification_new_chapters_on">Anda akan menerima pemberitahuan mengenai kemas kini manga yang anda sedang baca</string>
<string name="show_notification_new_chapters_off">Anda tidak akan menerima pemberitahuan namun bab baharu akan ditonjolkan dalam senarai</string>
<string name="edit_category">Sunting kategori</string>
<string name="tracking">Penjejakan</string>
<string name="empty_favourite_categories">Tiada kategori kegemaran</string>
<string name="logout">Log keluar</string>
<string name="bookmark_add">Tambah penanda</string>
<string name="bookmark_remove">Buang penanda</string>
<string name="bookmark_removed">Penanda dibuang</string>
<string name="bookmark_added">Penanda ditambah</string>
<string name="undo">Buat asal</string>
<string name="removed_from_history">Dibuang daripada sejarah</string>
<string name="dns_over_https">DNS atas HTTPS</string>
<string name="default_mode">Mod lalai</string>
<string name="detect_reader_mode">Autokesan mod pembaca</string>
<string name="disable_battery_optimization">Lumpuhkan pengoptimuman bateri</string>
<string name="disable_battery_optimization_summary">Membantu penyemakan kemas kini dalam latar belakang</string>
<string name="send">Hantar</string>
<string name="status_planned">Dirancang</string>
<string name="status_reading">Dibaca</string>
<string name="status_re_reading">Dibaca semula</string>
<string name="status_completed">Selesai</string>
<string name="status_on_hold">Dijeda</string>
<string name="status_dropped">Dihentikan</string>
<string name="disable_all">Lumpuhkan semua</string>
<string name="use_fingerprint">Guna cap jari sekiranya tersedia</string>
<string name="appwidget_shelf_description">Manga daripada kegemaran anda</string>
<string name="appwidget_recent_description">Manga yang anda baru baca</string>
<string name="report">Lapor</string>
<string name="show_reading_indicators">Tunjukkan penunjuk kemajuan pembacaan</string>
<string name="data_deletion">Pembuangan data</string>
<string name="exclude_nsfw_from_history_summary">Manga ditanda sebagai NSFW tidak akan ditambahkan dalam sejarah dan kemajuan tidak akan disimpan</string>
<string name="show_all">Tunjuk semua</string>
<string name="invalid_domain_message">Domain tidak sah</string>
<string name="select_range">Pilih julat</string>
<string name="clear_all_history">Kosongkan semua sejarah</string>
<string name="last_2_hours">2 jam lepas</string>
<string name="history_cleared">Sejarah dikosongkan</string>
<string name="manage">Urus</string>
<string name="no_bookmarks_yet">Tiada penanda lagi</string>
<string name="no_bookmarks_summary">Anda boleh membuat penanda ketika membaca manga</string>
<string name="no_manga_sources">Tiada sumber manga</string>
<string name="no_manga_sources_text">Bolehkan sumber manga untuk membaca manga di dalam talian</string>
<string name="random">Rawak</string>
<string name="categories_delete_confirm">Adakah anda pasti anda mahu membuang kategori kegemaran yang dipilih?
\nSemua manga di dalamnya akan hilang dan ini tidak boleh diundur semula.</string>
<string name="reorder">Susun semula</string>
<string name="empty">Kosong</string>
<string name="explore">Jelajah</string>
<string name="confirm_exit">Tekan Kembali sekali lagi untuk keluar</string>
<string name="exit_confirmation_summary">Tekan Kembali dua kali untuk keluar apl</string>
<string name="exit_confirmation">Pengesahan keluar</string>
<string name="pages_cache">Cache muka surat</string>
<string name="other_cache">Cache lain-lain</string>
<string name="storage_usage">Penggunaan storan</string>
<string name="available">Tersedia</string>
<string name="memory_usage_pattern">%s - %s</string>
<string name="removed_from_favourites">Dibuang daripada kegemaran</string>
<string name="options">Pilihan</string>
<string name="local_storage">Storan tempatan</string>
<string name="reader_mode_hint">Tetapan yang telah dipilih akan diperingati untuk manga ini</string>
<string name="backup_information">Anda boleh membuat sandaran sejarah dan kegemaran anda dan pulihkannya</string>
<string name="default_s">Lalai: %s</string>
<string name="text_clear_search_history_prompt">Buang semua carian terkini selama-lamanya?</string>
<string name="tracker_warning">Sesetengah peranti mempunyai kelakuan sistem berlainan, yang mampu merosakkan tugasan latar belakang.</string>
<string name="queued">Dibariskan</string>
<string name="chapter_is_missing">Bab ini hilang</string>
<string name="backup_saved">Sandaran disimpan</string>
<string name="about_app_translation">Terjemahan</string>
<string name="about_app_translation_summary">Terjemahkan apl ini</string>
<string name="error_occurred">Sebuah ralat telah berlaku</string>
<string name="share_s">Kongsi %s</string>
<string name="available_sources">Sumber tersedia</string>
<string name="nothing_found">Tiada dijumpai</string>
<string name="suggestions_info">Semua data hanya dianalisa secara tempatan pada peranti ini dan tidak dihantar ke mana-mana.</string>
<string name="you_have_not_favourites_yet">Tiada kegemaran lagi</string>
<string name="exclude_nsfw_from_suggestions">Jangan syor manga NSFW</string>
<string name="processing_">Memproses…</string>
<string name="onboard_text">Pilih bahasa untuk manga yang anda mahu baca. Anda boleh mengubah ini kemudian melalui tetapan.</string>
<string name="add_to_favourites">Tambah dalam kegemaran</string>
<string name="theme">Tema</string>
<string name="suggestions_excluded_genres">Kecualikan genre</string>
<string name="download_slowdown_summary">Membantu mengelakkan alamat IP anda disekat</string>
<string name="delete">Buang</string>
<string name="search_on_s">Cari pada %s</string>
<string name="clear_thumbs_cache">Kosongkan cache imej kenit</string>
<string name="chapters_will_removed_background">Bab akan dibuang dalam latar belakang</string>
<string name="operation_not_supported">Operasi ini tidak disokong</string>
<string name="delete_manga">Buang manga</string>
<string name="taps_on_edges">Ketik tepi</string>
<string name="page_saved">Disimpan</string>
<string name="domain">Domain</string>
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">%1$d daripada %2$d pada</string>
<string name="read_mode">Mod pembacaan</string>
<string name="text_delete_local_manga">Buang \"%s\" selama-lamanya daripada peranti?</string>
<string name="reader_settings">Tetapan pembaca</string>
<string name="download">Muat turun</string>
<string name="notifications_settings">Tetapan pemberitahuan</string>
<string name="grid_size">Saiz grid</string>
<string name="switch_pages">Tukar muka surat</string>
<string name="text_empty_holder_primary">Ianya agak kosong di sini…</string>
<string name="text_search_holder_secondary">Cuba untuk merumuskan semula carian.</string>
<string name="updates">Kemas kini</string>
<string name="all_favourites">Semua kegemaran</string>
<string name="favourites_categories">Kategori kegemaran</string>
<string name="text_history_holder_secondary">Cari apa yang boleh dibaca melalui seksyen «Jelajah»</string>
<string name="pages_animation">Animasi muka surat</string>
<string name="manga_save_location">Folder muat turun</string>
<string name="not_available">Tidak tersedia</string>
<string name="notifications_enable">Bolehkan pemberitahuan</string>
<string name="name">Nama</string>
<string name="edit">Sunting</string>
<string name="bookmarks">Penanda</string>
<string name="clear_cookies_summary">Boleh membantu sekiranya terdapat isu. Semua keizinan akan dinyahsahkan</string>
<string name="detect_reader_mode_summary">Kesan sekiranya manga adalah webtoon secara automatik</string>
<string name="show_reading_indicators_summary">Tunjuk peratusan dibaca dalam sejarah dan kegemaran</string>
<string name="bookmarks_removed">Penanda dibuang</string>
<string name="crash_text">Sebuah ralat telah berlaku. Sila hantar laporan pepijat kepada pembangun untuk membantu kami membetulkannya.</string>
<string name="saved_manga">Manga disimpan</string>
<string name="text_feed_holder">Bab-bab baharu bacaan anda ditunjukkan di sini</string>
<string name="size_s">Saiz: %s</string>
<string name="new_version_s">Versi baharu: %s</string>
<string name="clear_updates_feed">Kosongkan siaran kemaskini</string>
<string name="updates_feed_cleared">Dikosongkan</string>
<string name="wrong_password">Kata laluan salah</string>
<string name="rotate_screen">Putar skrin</string>
<string name="update">Kemas kini</string>
<string name="feed_will_update_soon">Kemaskini siaran akan bermula sebentar</string>
<string name="dont_check">Jangan semak</string>
</resources>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="favourites">ਮਨਪਸੰਦ</string>
<string name="history">ਇਤਿਹਾਸ</string>
<string name="error_occurred">ਇੱਕ ਗਲਤੀ ਆਈ ਹੈ</string>
<string name="details">ਵੇਰਵਾ</string>
<string name="chapters">ਅਧਿਆਇ</string>
<string name="grid">ਗਰਿੱਡ</string>
<string name="list_mode">ਲਿਸਟ ਮੋਡ</string>
<string name="settings">ਸੈਟਿੰਗ</string>
<string name="remote_sources">ਮਾਂਗਾ ਸਰੋਤ</string>
<string name="loading_">ਲੋਡ…</string>
<string name="computing_">ਹਿਸਾਬ ਲਾ ਰਿਹਾ</string>
<string name="chapter_d_of_d">%2$d ਦਾ %1$d ਅਧਿਆਇ</string>
<string name="close">ਬੰਦ</string>
<string name="try_again">ਮੁੜ ਕੋਸ਼ਿਸ਼ ਕਰੋ</string>
<string name="local_storage">ਸਥਾਨਕ ਸਟੋਰੇਜ</string>
<string name="network_error">ਨੈੱਟਵਰਕ ਖਰਾਬ</string>
<string name="list">ਲਿਸਟ</string>
<string name="detailed_list">ਵੇਰਵਾ ਲਿਸਟ</string>
</resources>

View File

@@ -543,4 +543,16 @@
<string name="backup_date_">Data de backup: %s</string>
<string name="grayscale">Tons de Cinza</string>
<string name="sync_auth">Faça login para sincronizar a conta</string>
<string name="state_upcoming">por vir</string>
<string name="by_name_reverse">Nome invertido</string>
<string name="rating_safe">seguro</string>
<string name="rating_suggestive">sugestivo</string>
<string name="genres_exclude">excluir gênero</string>
<string name="rating_adult">Adulto</string>
<string name="default_tab">Aba padrão</string>
<string name="content_rating">Classificação do Conteúdo</string>
<string name="mark_as_completed_prompt">Deseja marcar o mangá selecionado como completo?
\n
\nAviso: o progresso de leitura atual será perdido.</string>
<string name="mark_as_completed">Marcar como completo</string>
</resources>

View File

@@ -3,36 +3,36 @@
<plurals name="minutes_ago">
<item quantity="one">%1$d minuto atrás</item>
<item quantity="many">%1$d minutos atrás</item>
<item quantity="other"></item>
<item quantity="other">%1$d minutos atrás</item>
</plurals>
<plurals name="items">
<item quantity="one">%1$d item</item>
<item quantity="many">%1$d itens</item>
<item quantity="other"></item>
<item quantity="one">%1$d elemento</item>
<item quantity="many">%1$d elementos</item>
<item quantity="other">%1$d elementos</item>
</plurals>
<plurals name="chapters">
<item quantity="one">%1$d capítulo</item>
<item quantity="many">%1$d capítulos</item>
<item quantity="other"></item>
<item quantity="other">%1$d capítulos</item>
</plurals>
<plurals name="new_chapters">
<item quantity="one">%1$d novo capítulo</item>
<item quantity="many">%1$d novos capítulos</item>
<item quantity="other"></item>
<item quantity="other">%1$d capítulos novos</item>
</plurals>
<plurals name="months_ago">
<item quantity="one">%1$d mês atrás</item>
<item quantity="many">%1$d meses atrás</item>
<item quantity="other"></item>
<item quantity="other">%1$d meses atrás</item>
</plurals>
<plurals name="days_ago">
<item quantity="one">%1$d dia atrás</item>
<item quantity="many">%1$d dias atrás</item>
<item quantity="other"></item>
<item quantity="other">%1$d dias atrás</item>
</plurals>
<plurals name="hours_ago">
<item quantity="one">%1$d hora atrás</item>
<item quantity="many">%1$d horas atrás</item>
<item quantity="other"></item>
<item quantity="other">%1$d horas atrás</item>
</plurals>
</resources>

View File

@@ -543,4 +543,12 @@
<string name="backups_output_directory">Local de saída de backups</string>
<string name="content_type_other">Outros</string>
<string name="sync_auth">Faça login para sincronizar a conta</string>
<string name="state_upcoming">Próximo</string>
<string name="content_rating">Avaliação do conteúdo</string>
<string name="genres_exclude">Excluir gêneros</string>
<string name="rating_safe">Seguro</string>
<string name="rating_suggestive">Sugestivo</string>
<string name="rating_adult">Adulto</string>
<string name="default_tab">Guia padrão</string>
<string name="by_name_reverse">Nome invertido</string>
</resources>

View File

@@ -547,4 +547,8 @@
<string name="state_upcoming">Ожидается</string>
<string name="genres_exclude">Исключить жанры</string>
<string name="default_tab">Вкладка по умолчанию</string>
<string name="content_rating">Рейтинг контента</string>
<string name="rating_safe">Безопасный</string>
<string name="rating_suggestive">С намёками</string>
<string name="rating_adult">Взрослый</string>
</resources>

View File

@@ -545,4 +545,14 @@
<string name="sync_auth">Пријавите се за синхронизацију налога</string>
<string name="by_name_reverse">Обрнуто име</string>
<string name="state_upcoming">Излази</string>
<string name="genres_exclude">Искључи жанрове</string>
<string name="rating_safe">Безбедно</string>
<string name="rating_suggestive">Препоручљиво</string>
<string name="default_tab">Подразумевана картица</string>
<string name="content_rating">Оцена садржаја</string>
<string name="rating_adult">За одрасле</string>
<string name="mark_as_completed">Означи као завршено</string>
<string name="mark_as_completed_prompt">Означи изабрану мангу као потпуно прочитану?
\n
\nУпозорење: тренутни напредак читања ће бити изгубљен</string>
</resources>

View File

@@ -17,7 +17,7 @@
<string name="history_is_empty">Geçmiş yok</string>
<string name="read">Oku</string>
<string name="you_have_not_favourites_yet">Henüz favorileriniz yok</string>
<string name="add_to_favourites">Favoriniz</string>
<string name="add_to_favourites">Favorilere ekle</string>
<string name="add_new_category">Yeni kategori</string>
<string name="add">Ekle</string>
<string name="save">Kaydet</string>
@@ -28,16 +28,16 @@
<string name="manga_downloading_">İndiriliyor…</string>
<string name="processing_">İşleniyor…</string>
<string name="download_complete">İndirildi</string>
<string name="downloads">İndirilenler</string>
<string name="downloads">İndirmeler</string>
<string name="by_name">Ad</string>
<string name="updated">Güncellendi</string>
<string name="newest">Yeniler</string>
<string name="newest">En yeniler</string>
<string name="by_rating">Puanlama</string>
<string name="filter">Litre</string>
<string name="filter">Filtre</string>
<string name="theme">Tema</string>
<string name="light">ık</string>
<string name="dark">Koyu</string>
<string name="automatic">Takip sistemi</string>
<string name="automatic">Sistemle uyumlu</string>
<string name="pages">Sayfalar</string>
<string name="clear">Temizle</string>
<string name="text_clear_history_prompt">Tüm okuma geçmişi kalıcı olarak silinsin mi\?</string>
@@ -48,12 +48,12 @@
<string name="popular">Popüler</string>
<string name="details">Detaylar</string>
<string name="settings">Ayarlar</string>
<string name="page_saved">Kaydet</string>
<string name="page_saved">Kaydedildi</string>
<string name="error_occurred">Bir hata oluştu</string>
<string name="remote_sources">Manga kaynakları</string>
<string name="search_history_cleared">Temizlendi</string>
<string name="_continue">Devam</string>
<string name="not_available">Müsait değil</string>
<string name="not_available">Mevcut değil</string>
<string name="favourites_category_empty">Boş kategori</string>
<string name="remove_category">Kaldır</string>
<string name="delete">Sil</string>
@@ -64,11 +64,11 @@
<string name="webtoon">Webtoon</string>
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
<string name="reader_settings">Okuyucu ayarları</string>
<string name="volume_buttons">Ses butonları</string>
<string name="volume_buttons">Ses tuşları</string>
<string name="error">Hata</string>
<string name="clear_thumbs_cache">Küçük resim önbelleğini temizle</string>
<string name="gestures_only">Yalnızca hareketler</string>
<string name="domain">Alan adi</string>
<string name="domain">Alan adı</string>
<string name="open_in_browser">Web tarayıcısında aç</string>
<string name="new_chapters">Yeni bölümler</string>
<string name="notifications_settings">Bildirim ayarları</string>
@@ -89,7 +89,7 @@
<string name="search_on_s">%s üzerinde ara</string>
<string name="internal_storage">Dahili depolama</string>
<string name="notifications">Bildirimler</string>
<string name="switch_pages">Sayfaları değiştir</string>
<string name="switch_pages">Sayfalarda ilerleme</string>
<string name="save_manga">Kaydet</string>
<string name="download">İndir</string>
<string name="manga_save_location">İndirilenler klasörü</string>
@@ -100,11 +100,11 @@
<string name="read_later">Sonra oku</string>
<string name="pages_animation">Sayfa animasyonu</string>
<string name="cannot_find_available_storage">Kullanılabilir depolama alanı yok</string>
<string name="text_delete_local_manga">“%s” cihazdan kalıcı olarak silinsin mi\?</string>
<string name="text_delete_local_manga">“%s” cihazdan kalıcı olarak silinsin mi?</string>
<string name="clear_search_history">Arama geçmişini temizle</string>
<string name="text_empty_holder_primary">Burası biraz boş…</string>
<string name="rotate_screen">Ekranı döndür</string>
<string name="scale_mode">Ölçek modu</string>
<string name="scale_mode">Boyutlandırma modu</string>
<string name="zoom_mode_fit_height">Yüksekliğe sığdır</string>
<string name="black_dark_theme">Siyah</string>
<string name="zoom_mode_keep_start">Başlangıçta tut</string>
@@ -136,12 +136,12 @@
<string name="clear_updates_feed">Güncelleme akışını temizle</string>
<string name="feed_will_update_soon">Akış güncellemesi yakında başlayacak</string>
<string name="app_version">Sürüm %s</string>
<string name="check_for_updates">Güncellemeleri denetle</string>
<string name="check_for_updates">Güncellemeleri kontrol et</string>
<string name="zoom_mode_fit_center">Merkeze sığdır</string>
<string name="zoom_mode_fit_width">Genişliğe sığdır</string>
<string name="black_dark_theme_summary">AMOLED ekranlarda daha az güç kullanır</string>
<string name="backup_restore">Yedekle ve geri yükle</string>
<string name="create_backup">Veri yedeği oluştur</string>
<string name="create_backup">Yedek oluştur</string>
<string name="data_restored">Geri yüklendi</string>
<string name="preparing_">Hazırlanıyor…</string>
<string name="yesterday">Dün</string>
@@ -149,8 +149,8 @@
<string name="silent">Sessiz</string>
<string name="captcha_solve">Çöz</string>
<string name="clear_cookies">Çerezleri temizle</string>
<string name="default_s">Öntanımlı: %s</string>
<string name="reverse">Ters</string>
<string name="default_s">Varsayılan: %s</string>
<string name="reverse">Tersten</string>
<string name="password_length_hint">Parola 4 veya daha fazla karakterden oluşmalıdır</string>
<string name="welcome">Hoş geldiniz</string>
<string name="queued">Sıraya alındı</string>
@@ -162,10 +162,10 @@
<string name="enabled_sources">Kullanılan kaynaklar</string>
<string name="available_sources">Kullanılabilir kaynaklar</string>
<string name="exclude_nsfw_from_history">Uygunsuz mangayı geçmişten hariç tut</string>
<string name="show_pages_numbers">Numaralı sayfalar</string>
<string name="show_pages_numbers">Sayfa numaraları</string>
<string name="search_results">Arama sonuçları</string>
<string name="repeat_password">Parolayı tekrarla</string>
<string name="dont_check">Denetleme</string>
<string name="dont_check">Kontrol etme</string>
<string name="wrong_password">Yanlış parola</string>
<string name="backup_information">Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz</string>
<string name="long_ago">Uzun zaman önce</string>
@@ -191,15 +191,15 @@
<string name="text_clear_search_history_prompt">Tüm son arama sorguları kalıcı olarak kaldırılsın mı\?</string>
<string name="backup_saved">Yedek kaydedildi</string>
<string name="genres">Türler</string>
<string name="system_default">Öntanımlı</string>
<string name="system_default">Varsayılan</string>
<string name="auth_not_supported_by">%s üzerinde oturum açma desteklenmiyor</string>
<string name="read_more">Daha fazla oku</string>
<string name="tracker_warning">Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır.</string>
<string name="screenshots_policy">Ekran görüntüsü politikası</string>
<string name="tracker_warning">Bazı cihazların arka plan görevlerini bozabilecek farklı sistem davranışları vardır.</string>
<string name="screenshots_policy">Ekran görüntüleri</string>
<string name="screenshots_block_nsfw">Uygunsuzlarda engelle</string>
<string name="screenshots_block_all">Her zaman engelle</string>
<string name="screenshots_allow">İzin ver</string>
<string name="check_for_new_chapters">Yeni bölümleri denetle</string>
<string name="check_for_new_chapters">Yeni bölümleri kontrol et</string>
<string name="suggestions">Öneriler</string>
<string name="suggestions_enable">Önerileri etkinleştir</string>
<string name="suggestions_summary">Tercihlerinize göre manga önerileri alın</string>
@@ -228,14 +228,14 @@
<string name="text_delete_local_manga_batch">Seçilen ögeler aygıttan kalıcı olarak silinsin mi\?</string>
<string name="removal_completed">Kaldırma tamamlandı</string>
<string name="chapters_will_removed_background">Bölümler arka planda kaldırılacak</string>
<string name="download_slowdown">İndirmeyi yavaşlat</string>
<string name="download_slowdown">İndirme yavaşlatma</string>
<string name="download_slowdown_summary">IP adresinizin engellenmesinden kaçınmanıza yardımcı olur</string>
<string name="local_manga_processing">Kaydedilen manga işleme</string>
<string name="hide">Gizle</string>
<string name="new_sources_text">Yeni manga kaynakları var</string>
<string name="show_notification_new_chapters_off">Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak</string>
<string name="notifications_enable">Bildirimleri etkinleştir</string>
<string name="check_new_chapters_title">Yeni bölümleri denetle ve bildirim gönder</string>
<string name="check_new_chapters_title">Yeni bölümleri kontrol et ve bildirim gönder</string>
<string name="show_notification_new_chapters_on">Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız</string>
<string name="empty_favourite_categories">Favori kategori yok</string>
<string name="name">Ad</string>
@@ -251,9 +251,9 @@
<string name="dns_over_https">HTTPS üzerinden DNS</string>
<string name="detect_reader_mode">Okuyucu modunu otomatik algıla</string>
<string name="detect_reader_mode_summary">Manganın webtoon olup olmadığını otomatik olarak algıla</string>
<string name="default_mode">Öntanımlı mod</string>
<string name="default_mode">Varsayılan mod</string>
<string name="disable_battery_optimization">Pil iyileştirmesini devre dışı bırak</string>
<string name="disable_battery_optimization_summary">Arka planda güncelleme denetimlerine yardımcı olur</string>
<string name="disable_battery_optimization_summary">Arka planda güncelleme kontrollerine yardımcı olur</string>
<string name="crash_text">Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin.</string>
<string name="send">Gönder</string>
<string name="disable_all">Tümünü devre dışı bırak</string>
@@ -290,10 +290,10 @@
<string name="history_cleared">Geçmiş temizlendi</string>
<string name="manage">Yönet</string>
<string name="no_bookmarks_yet">Yer işareti yok</string>
<string name="no_bookmarks_summary">Manga okurken yer işareti oluşturabilirsiniz</string>
<string name="no_bookmarks_summary">Manga okurken yer imi oluşturabilirsiniz</string>
<string name="bookmarks_removed">Yer işaretleri kaldırıldı</string>
<string name="no_manga_sources">Manga kaynağı yok</string>
<string name="no_manga_sources_text">Çevrimiçi manga okumak için manga kaynaklarını aktif edin</string>
<string name="no_manga_sources_text">Çevrim içi manga okumak için manga kaynaklarını aktif edin</string>
<string name="random">Rastgele</string>
<string name="empty">Boş</string>
<string name="explore">Keşfet</string>
@@ -331,7 +331,7 @@
<string name="contrast">Kontrast</string>
<string name="reset">Sıfırla</string>
<string name="color_correction_hint">Seçilen renk ayarları bu manga için hatırlanacaktır</string>
<string name="text_unsaved_changes_prompt">Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\?</string>
<string name="text_unsaved_changes_prompt">Kaydedilmeyen değişiklikler kaydedilsin mi?</string>
<string name="discard">Yoksay</string>
<string name="error_no_space_left">Cihazda yer yok</string>
<string name="webtoon_zoom">Webtoon yakınlaştırma</string>
@@ -341,7 +341,7 @@
<string name="different_languages">Farklı diller</string>
<string name="network_unavailable">Ağ kullanılamıyor</string>
<string name="network_unavailable_hint">Çevrim içi manga okumak için Wi-Fi veya mobil ağıın</string>
<string name="server_error">Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin</string>
<string name="server_error">Sunucu hatası (%1$d). Lütfen daha sonra tekrar deneyin</string>
<string name="saved_manga">Kaydedilen mangalar</string>
<string name="history_shortcuts_summary">Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin</string>
<string name="reader_control_ltr_summary">Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir</string>
@@ -357,12 +357,12 @@
<string name="scrobbling_empty_hint">Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin.</string>
<string name="nothing_here">burada hiçbir şey yok</string>
<string name="theme_name_dynamic">Dinamik</string>
<string name="color_theme">renk vurgusu</string>
<string name="color_theme">Renk teması</string>
<string name="show_in_grid_view">Izgara görünümünde göster</string>
<string name="theme_name_mamimi">Mamimi</string>
<string name="theme_name_kanade">Kanade</string>
<string name="user_agent">UserAgent başlığı</string>
<string name="allow_unstable_updates_summary">Kararsız yapılar hakkında bildirimler alın</string>
<string name="allow_unstable_updates_summary">Kararsız versiyonlar hakkında bildirim alın</string>
<string name="allow_unstable_updates">Kararsız güncellemelere izin ver</string>
<string name="download_started">İndirme başladı</string>
<string name="theme_name_miku">Miku</string>
@@ -379,8 +379,8 @@
<string name="clear_network_cache">İnternet geçmişini temizle</string>
<string name="sync_settings">Eşitleme ayarları</string>
<string name="server_address">Sunucu adresi</string>
<string name="sync_host_description">Şirket içinde barındırılan bir eşitleme sunucusu veya varsayılan bir sunucu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin.</string>
<string name="mirror_switching_summary">Aynalar mevcutsa hatalarda manga kaynakları için etki alanlarını otomatik olarak değiştir</string>
<string name="sync_host_description">Kendi eşitleme sunucunuzu veya varsayılan bir sunucuyu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin.</string>
<string name="mirror_switching_summary">Yedek bağlantılar mevcutsa hatalarda manga kaynakları için bağlantıları otomatik olarak değiştir</string>
<string name="downloads_wifi_only_summary">Mobil ağa geçerken indirmeyi durdur</string>
<string name="remove_completed">Bitirilenleri kaldır</string>
<string name="cancel_all">Hepsini iptal et</string>
@@ -401,18 +401,18 @@
<string name="suggestions_notifications_summary">Bazen manga öneri bildirimlerilerini göster</string>
<string name="more">Daha fazla</string>
<string name="cancel_all_downloads_confirm">Tüm aktif indirmeler iptal edilecek, kısmen indirilen veriler kaybolacak</string>
<string name="remove_completed_downloads_confirm">İndirme geçmişin tamamen silinecek</string>
<string name="remove_completed_downloads_confirm">İndirme geçmişiniz tamamen silinecek</string>
<string name="text_downloads_list_holder">Hiçbir indirmeniz yok</string>
<string name="downloads_resumed">İndirmeler devam ettirildi</string>
<string name="downloads_paused">İndirmeler durduruldu</string>
<string name="downloads_removed">İndirmeler silindi</string>
<string name="mirror_switching">Aynayı otomatik olarak seç</string>
<string name="mirror_switching">Yedek bağlantıyı otomatik olarak seç</string>
<string name="downloads_cancelled">İndirmeler iptal edildi</string>
<string name="suggestions_enable_prompt">Kişiselleştirilmiş manga önerileri almak istiyor musunuz\?</string>
<string name="address">Adres</string>
<string name="type">Tür</string>
<string name="manga_branch_title_template">%1$s (%2$s)</string>
<string name="port">Menü</string>
<string name="port">Port</string>
<string name="proxy">Proxy</string>
<string name="invalid_value_message">Geçersiz değer</string>
<string name="invalid_port_number">Geçersiz port numarası</string>
@@ -429,22 +429,22 @@
<string name="webtoon_zoom_summary">Webtoon modunda yakınlaştırma hareketine izin ver</string>
<string name="reader_info_bar_summary">Geçerli saati ve okuma ilerlemesini ekranın üst kısmında gösterin</string>
<string name="show_pages_numbers_summary">Sayfa numaralarını alt köşede göster</string>
<string name="pages_animation_summary">Sayfa Çevirme Animasyonu</string>
<string name="pages_animation_summary">Sayfa değiştirmelerini animasyonla yap</string>
<string name="details_button_tip">Daha fazla seçenek görmek için Oku düğmesini basılı tutun</string>
<string name="languages">Diller</string>
<string name="zoom_in">Yakınlaştır</string>
<string name="captcha_required_summary">Düzgün okunmak için %s captcha gerektiriyor</string>
<string name="download_option_all_unread">Tüm okunmamış bölümler</string>
<string name="progress">İlerleme</string>
<string name="error_corrupted_file">Geçersiz veri döndürülüyor veya dosya bozuk</string>
<string name="error_corrupted_file">Geçersiz veri alındı veya dosya bozuk</string>
<string name="pick_custom_directory">Özel dizini seçin</string>
<string name="related_manga_summary">İlgili mangaların bir listesini göster. Bazı durumlarda yanlış veya eksik olabilir</string>
<string name="reader_zoom_buttons_summary">Sağ alt köşede yakınlaştırma kontrol düğmelerini göster veya gösterme</string>
<string name="tracker_wifi_only_summary">Ölçülü ağ bağlantılarını kullanarak yeni bölümleri kontrol etmeyin</string>
<string name="reader_zoom_buttons_summary">Sağ alt köşede yakınlaştırma kontrol düğmelerini gösterir</string>
<string name="tracker_wifi_only_summary">Tarifeli ağ bağlantılarını kullanarak yeni bölümleri kontrol etmeyin</string>
<string name="order_added">Eklendi</string>
<string name="on_device">Cihazda</string>
<string name="download_option_whole_manga">Bütün manga</string>
<string name="clear_source_cookies_summary">Yalnızca belirtilen etki alanı için çerezleri temizleyin. Çoğu durumda yetkilendirmeyi geçersiz kılar</string>
<string name="clear_source_cookies_summary">Yalnızca belirtilen alan adı için çerezleri temizleyin. Çoğu durumda yetkilendirmeyi geçersiz kılar</string>
<string name="suggest_new_sources">Uygulama güncellemesinden sonra yeni kaynaklar önerin</string>
<string name="moved_to_top">Üste taşındı</string>
<string name="data_not_restored_text">Doğru yedek dosyasını seçtiğinizden emin olun</string>
@@ -452,26 +452,26 @@
<string name="unknown">Bilinmeyen</string>
<string name="in_progress">Devam ediyor</string>
<string name="download_option_manual_selection">Bölümleri elle seç</string>
<string name="enhanced_colors_summary">Bantlanmayı azaltır, ancak performansı etkileyebilir</string>
<string name="enhanced_colors_summary">Çizgileşmeyi azaltır, ancak performansı etkileyebilir</string>
<string name="items_limit_exceeded">Daha fazla öğe eklenemez</string>
<string name="data_not_restored">Veri geri yüklemedi</string>
<string name="directories">Dizinler</string>
<string name="local_manga_directories">Yerel manga dizinleri</string>
<string name="manage_categories">Kategorileri yönet</string>
<string name="color_light">ık</string>
<string name="color_light">ık</string>
<string name="search_hint">Manga başlığı girin, tür veya kaynak adı</string>
<string name="description">ıklama</string>
<string name="reader_zoom_buttons">Yakınlaştırma butonlarını göster</string>
<string name="main_screen_sections">Ana ekran bölümleri</string>
<string name="advanced">Gelişmiş</string>
<string name="download_option_all_unread_b">Tüm okunmamış bölümler (%s)</string>
<string name="color_dark">Karanlık</string>
<string name="color_dark">Koyu</string>
<string name="too_many_requests_message">Çok fazla istek. Daha sonra tekrar deneyin</string>
<string name="related_manga">İlgili manga</string>
<string name="state_abandoned">Bırakıldı</string>
<string name="download_option_first_n_chapters">Önce %s</string>
<string name="keep_screen_on">Ekranıık tut</string>
<string name="suggestions_wifi_only_summary">Ölçülü ağ bağlantılarını kullanarak önerileri güncellemeyin</string>
<string name="suggestions_wifi_only_summary">Tarifeli bağlantılarını kullanarak önerileri güncellemeyin</string>
<string name="custom_directory">Özel dizin</string>
<string name="enhanced_colors">32-bit renk modu</string>
<string name="default_section">Varsayılan bölüm</string>
@@ -486,14 +486,14 @@
<string name="color_white">Beyaz</string>
<string name="to_top">Üste</string>
<string name="show">Göster</string>
<string name="suggest_new_sources_summary">Uygulamayı güncelledikten sonra yeni eklenen kaynakları etkinleştirme istemi</string>
<string name="download_option_all_chapters">Çevirisi %s olan tüm bölümler</string>
<string name="suggest_new_sources_summary">Uygulamayı güncelledikten sonra yeni eklenen kaynakları etkinleştirmeyi bildir</string>
<string name="download_option_all_chapters">%s çevirisi olan tüm bölümler</string>
<string name="color_black">Siyah</string>
<string name="this_month">Bu ay</string>
<string name="categories">Kategoriler</string>
<string name="list_options">Seçenekleri listele</string>
<string name="online_variant">Çevrimiçi varyant</string>
<string name="by_relevance">Alaka düzeyi</string>
<string name="online_variant">Çevrim içi türü</string>
<string name="by_relevance">İlgi düzeyine göre</string>
<string name="frequency_every_day">Her gün</string>
<string name="backup_frequency">Yedek oluşturma sıklığı</string>
<string name="periodic_backups_enable">Zamanlı yedeklemeleri etkinleştirin</string>
@@ -513,7 +513,7 @@
<string name="manage_sources">Kaynakları yönet</string>
<string name="reader_optimize_summary">Daha az bellek kullanımı için ekran dışı sayfaların çözünürlüğünü düşür</string>
<string name="source_enabled">Kaynak etkinleştirildi</string>
<string name="no_manga_sources_catalog_text">Bu bölüm için kullanılabilir kaynak yok ya da hepsi zaten eklenmiş olabilir.
<string name="no_manga_sources_catalog_text">Bu bölümde kullanılabilir kaynak yok ya da hepsi zaten eklenmiş olabilir.
\nTakipte kalın</string>
<string name="state_paused">Durduruldu</string>
<string name="content_type_other">Diğer</string>
@@ -543,4 +543,16 @@
<string name="sync_auth">Eşitleme hesabında oturum aç</string>
<string name="restore">Geri yükle</string>
<string name="backup_date_">Yedekleme tarihi: %s</string>
<string name="state_upcoming">Yakında</string>
<string name="by_name_reverse">Tersten ad</string>
<string name="content_rating">İçerik oylaması</string>
<string name="genres_exclude">Türleri hariç bırak</string>
<string name="rating_safe">Herkese uygun</string>
<string name="rating_adult">Yetişkin</string>
<string name="rating_suggestive">Uygunsuz</string>
<string name="default_tab">Varsayılan sekme</string>
<string name="mark_as_completed">Tamamlandı olarak işaretle</string>
<string name="mark_as_completed_prompt">Seçili mangayı tamamlandı olarak işaretle?
\n
\nUyarı: Şu anki ilerleme kaybolacaktır.</string>
</resources>

View File

@@ -512,7 +512,7 @@
<string name="content_type_hentai">Хентай</string>
<string name="content_type_comics">Комікси</string>
<string name="catalog">Каталог</string>
<string name="manage_sources">Кіравання джерелами</string>
<string name="manage_sources">Керування джерелами</string>
<string name="no_manga_sources_found">За вашим запитом не знайдено доступних джерел манґи</string>
<string name="manual">Вручну</string>
<string name="source_enabled">Джерело включено</string>
@@ -545,4 +545,10 @@
<string name="sync_auth">Увійти до синхронізації</string>
<string name="by_name_reverse">Ім\'я (навпаки)</string>
<string name="state_upcoming">Очікується</string>
<string name="genres_exclude">Виключити жанри</string>
<string name="rating_safe">Безпечний</string>
<string name="rating_adult">Дорослий</string>
<string name="default_tab">Типова вкладка</string>
<string name="content_rating">Рейтинг контенту</string>
<string name="rating_suggestive">З натяками</string>
</resources>

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