Compare commits

...

801 Commits
v0.5 ... v3.2.2

Author SHA1 Message Date
Zakhar Timoshenko
fa150e45ff [Issue template] Update version 2022-05-06 20:15:29 +03:00
Koitharu
de9c1017b3 Update parsers 2022-05-06 15:45:20 +03:00
Koitharu
2709d40fc0 Fix BottomSheet edge-to-edge mode 2022-05-06 13:51:55 +03:00
Koitharu
45b42ad5bd Revert "Fix bottom sheet navbar color"
This reverts commit fdd4f5abca.
2022-05-06 12:57:37 +03:00
Koitharu
b759f8d0a0 Fix pages filename #151 2022-05-05 16:46:44 +03:00
Koitharu
23e7aa2aaa Fix images scale type 2022-05-05 15:57:05 +03:00
Koitharu
fdd4f5abca Fix bottom sheet navbar color 2022-05-05 15:51:30 +03:00
Koitharu
c695468aec Fix cold launch 2022-05-05 15:43:07 +03:00
Koitharu
9166716f2a Update version 2022-05-05 15:21:10 +03:00
Zakhar Timoshenko
3407e74e99 Fix FavouriteCategoriesDialog toolbar in album orientation 2022-05-05 15:16:30 +03:00
Koitharu
4c5314fe59 Update parsers 2022-05-02 14:53:31 +03:00
Koitharu
96be49aa83 Update monochrome launcher icon 2022-05-02 09:39:01 +03:00
Koitharu
28b556121b Show new sources on app startup 2022-05-02 09:35:21 +03:00
Koitharu
558c19e526 Update parsers and version 2022-05-01 09:24:45 +03:00
Luiz-bro
59c2d20311 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (280 of 280 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
Luna Jernberg
fa1f2cbf51 Translated using Weblate (Swedish)
Currently translated at 98.5% (275 of 279 strings)

Co-authored-by: Luna Jernberg <droidbittin@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sv/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
J. Lavoie
de8739f143 Translated using Weblate (Finnish)
Currently translated at 99.6% (279 of 280 strings)

Translated using Weblate (French)

Currently translated at 100.0% (280 of 280 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (280 of 280 strings)

Translated using Weblate (German)

Currently translated at 100.0% (280 of 280 strings)

Translated using Weblate (Finnish)

Currently translated at 99.6% (278 of 279 strings)

Translated using Weblate (French)

Currently translated at 100.0% (279 of 279 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (279 of 279 strings)

Translated using Weblate (German)

Currently translated at 100.0% (279 of 279 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
kuragehime
9aa28f6fd2 Translated using Weblate (Japanese)
Currently translated at 100.0% (280 of 280 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (279 of 279 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
Oğuz Ersen
a2b1699047 Translated using Weblate (Turkish)
Currently translated at 100.0% (280 of 280 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (279 of 279 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
mondstern
2dce65a448 Translated using Weblate (German)
Currently translated at 98.9% (276 of 279 strings)

Co-authored-by: mondstern <mondstern@snopyta.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translation: Kotatsu/Strings
2022-05-01 09:18:16 +03:00
Koitharu
3d68d7c818 Reuse PageLoader in PagesThumbnailsSheet 2022-04-29 12:45:28 +03:00
Koitharu
4987d43042 Fix pages saving #151 2022-04-29 11:41:14 +03:00
Koitharu
684b494edb Fix concurrent manga downloading #154 2022-04-29 10:07:21 +03:00
Koitharu
714b708fa9 Fix npe on getExternalFilesDirs #158 2022-04-29 09:04:41 +03:00
Koitharu
c462c19a8b Option to hide 'All categories' tab from favourites 2022-04-28 16:46:55 +03:00
Koitharu
e34acf010e Update parsers 2022-04-23 19:31:02 +03:00
Koitharu
0fb29174c5 Fix webview useragent 2022-04-23 19:31:01 +03:00
Xtimms
ca45774cdb Merge remote-tracking branch 'origin/devel' into devel 2022-04-23 19:16:46 +03:00
Xtimms
cccc2c4fe4 Create issue template 2022-04-23 19:16:15 +03:00
Koitharu
c73af2d45f Update version 2022-04-23 15:37:16 +03:00
lowak
acf7102d07 Translated using Weblate (Swedish)
Currently translated at 100.0% (274 of 274 strings)

Co-authored-by: lowak <lowak@pm.me>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sv/
Translation: Kotatsu/Strings
2022-04-23 15:33:11 +03:00
Koitharu
75fcd31758 Fix locking app on screen rotation 2022-04-23 15:31:52 +03:00
Koitharu
7bffb5f22d Select source domains using AutoCompleteTextView 2022-04-23 15:20:57 +03:00
Koitharu
c220bd5517 Merge branch 'feature/direct-download' into devel 2022-04-23 13:57:24 +03:00
Koitharu
7c827b45d5 Merge branch 'feature/improve-list' into devel 2022-04-23 13:55:03 +03:00
Koitharu
e91d9ee38e Fix list selection corners 2022-04-23 13:54:48 +03:00
Koitharu
b6a86a6538 Cache and reuse RemoteMangaRepository instances 2022-04-23 10:39:33 +03:00
Koitharu
16b6b6c071 Add dummy manga parser for development 2022-04-23 10:31:10 +03:00
Xtimms
695feef4a6 Improve simple manga list 2022-04-21 20:15:59 +03:00
Koitharu
6bf4e0cf89 Use PageLoader for thumbnails 2022-04-20 12:57:07 +03:00
Koitharu
44d8d0f246 Fix search keyboard #150 2022-04-20 12:17:32 +03:00
Koitharu
e617e8d6d3 Add password toggle to ProtectActivity 2022-04-20 12:06:49 +03:00
Koitharu
1f411b7530 Cleanup temporary files 2022-04-20 11:50:55 +03:00
Koitharu
d64bd9d9d3 Estimate remeaning download time 2022-04-20 11:18:33 +03:00
Koitharu
f33dc8f797 Update feed ui 2022-04-20 09:25:46 +03:00
Koitharu
e63ae12c8c Delete local chapters in a service 2022-04-19 16:04:24 +03:00
Koitharu
cbd3d439cd Support multiple branches in saved manga 2022-04-19 14:35:02 +03:00
Koitharu
83eb0d9f23 Fix isLoading live data 2022-04-19 12:53:45 +03:00
Koitharu
3c739eed8e Fix empty chapters label 2022-04-19 12:43:51 +03:00
Koitharu
d77646adf1 Fix duplicate zip entry error 2022-04-19 11:32:42 +03:00
Koitharu
5b5e6cba57 Fix download error retry 2022-04-19 11:08:55 +03:00
Koitharu
8fc9b27840 Option to slowdown downloads and configure parallelism 2022-04-19 10:28:05 +03:00
Koitharu
fa536220eb Search and parallelism in LocalMangaRepository.getList 2022-04-19 09:25:12 +03:00
Koitharu
98f16774c4 Delete whole manga if all chapters are removed 2022-04-19 08:22:54 +03:00
Koitharu
ce8f57c3ca Disable update checking if not supported #147 2022-04-18 20:11:23 +03:00
Koitharu
be66106336 Removing selected chapters from local storage 2022-04-18 20:00:43 +03:00
Koitharu
16c8641a07 Fix concurrent downloading #146 2022-04-18 16:46:35 +03:00
Koitharu
d3e9ce874a Download manga to cbz directly 2022-04-18 16:42:37 +03:00
Koitharu
aaf9c6a0bf Update parsers 2022-04-18 09:26:48 +03:00
Koitharu
c2276eb2cb Fix cover size changes in details 2022-04-17 10:24:49 +03:00
Koitharu
5fbae1256b Fix branch detection #143 2022-04-17 09:58:52 +03:00
Koitharu
d61ba80bf6 Add additional checks to download task #50 2022-04-17 09:47:21 +03:00
Koitharu
74c9fa9488 Option to save manga from history and favourites lists 2022-04-17 09:15:16 +03:00
Koitharu
ce732ccca0 Merge branch 'weblate-kotatsu-strings' into devel 2022-04-16 10:05:37 +03:00
Sergio Varela
6b99e360e0 Added translation using Weblate (Basque)
Added translation using Weblate (Basque)

Co-authored-by: Sergio Varela <sergitroll9@gmail.com>
2022-04-16 09:46:16 +03:00
lowak
1c73d54a94 Translated using Weblate (Swedish)
Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Swedish)

Currently translated at 41.6% (114 of 274 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Swedish)

Added translation using Weblate (Swedish)

Co-authored-by: lowak <lowak@pm.me>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/sv/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sv/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Luiz-bro
36e21caf96 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (274 of 274 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Santiago José Gutiérrez Llanos
f7f9c53466 Translated using Weblate (Spanish)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (274 of 274 strings)

Co-authored-by: Santiago José Gutiérrez Llanos <gutierrezapata17@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Allan Nordhøy
3f2ee2a925 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Norwegian Bokmål)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/nb_NO/
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
J. Lavoie
b1c069f62f Translated using Weblate (Italian)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (German)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (French)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Finnish)

Currently translated at 99.2% (272 of 274 strings)

Translated using Weblate (French)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (German)

Currently translated at 100.0% (274 of 274 strings)

Added translation using Weblate (Italian)

Added translation using Weblate (German)

Added translation using Weblate (French)

Translated using Weblate (Finnish)

Currently translated at 99.6% (270 of 271 strings)

Translated using Weblate (French)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (German)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (French)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (German)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Belarusian)

Currently translated at 98.8% (266 of 269 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Luiz-bro
22d48fce8f Added translation using Weblate (Portuguese (Brazil))
Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (268 of 269 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2022-04-16 09:46:16 +03:00
kuragehime
6b2666c701 Translated using Weblate (Japanese)
Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Japanese)

Translated using Weblate (Japanese)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (269 of 269 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/ja/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Oğuz Ersen
414f438762 Translated using Weblate (Turkish)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (274 of 274 strings)

Added translation using Weblate (Turkish)

Translated using Weblate (Turkish)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (269 of 269 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/tr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-16 09:46:16 +03:00
Aliaksiej Razumaŭ
54f60040b5 Translated using Weblate (Belarusian)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Aliaksiej Razumaŭ <belarusaed@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translation: Kotatsu/Strings
2022-04-16 09:46:16 +03:00
Koitharu
b0515033da Increase version 2022-04-16 09:40:50 +03:00
Koitharu
d37eb07301 Fix startForeground for DownloadService 2022-04-16 09:19:10 +03:00
Sergio Varela
c2fa27712c Added translation using Weblate (Basque)
Added translation using Weblate (Basque)

Co-authored-by: Sergio Varela <sergitroll9@gmail.com>
2022-04-15 12:57:32 +02:00
lowak
10a2589c10 Translated using Weblate (Swedish)
Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Swedish)

Currently translated at 41.6% (114 of 274 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Swedish)

Added translation using Weblate (Swedish)

Co-authored-by: lowak <lowak@pm.me>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/sv/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/sv/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:31 +02:00
Luiz-bro
05eb96e7c0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (274 of 274 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:31 +02:00
Santiago José Gutiérrez Llanos
15a08ad6ae Translated using Weblate (Spanish)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (274 of 274 strings)

Co-authored-by: Santiago José Gutiérrez Llanos <gutierrezapata17@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:31 +02:00
Allan Nordhøy
3e437c2ecb Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Norwegian Bokmål)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/nb_NO/
Translation: Kotatsu/plurals
2022-04-15 12:57:30 +02:00
J. Lavoie
fea667b87c Translated using Weblate (Italian)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (German)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (French)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Finnish)

Currently translated at 99.2% (272 of 274 strings)

Translated using Weblate (French)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (German)

Currently translated at 100.0% (274 of 274 strings)

Added translation using Weblate (Italian)

Added translation using Weblate (German)

Added translation using Weblate (French)

Translated using Weblate (Finnish)

Currently translated at 99.6% (270 of 271 strings)

Translated using Weblate (French)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (German)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (French)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (German)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (269 of 269 strings)

Translated using Weblate (Belarusian)

Currently translated at 98.8% (266 of 269 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:30 +02:00
Luiz-bro
93eaaac084 Added translation using Weblate (Portuguese (Brazil))
Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (268 of 269 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2022-04-15 12:57:29 +02:00
kuragehime
a60df582a2 Translated using Weblate (Japanese)
Currently translated at 100.0% (8 of 8 strings)

Added translation using Weblate (Japanese)

Translated using Weblate (Japanese)

Currently translated at 100.0% (274 of 274 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (269 of 269 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/ja/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:29 +02:00
Oğuz Ersen
aec1d4e0d6 Translated using Weblate (Turkish)
Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (274 of 274 strings)

Added translation using Weblate (Turkish)

Translated using Weblate (Turkish)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (269 of 269 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/tr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-04-15 12:57:28 +02:00
Aliaksiej Razumaŭ
507f2e883c Translated using Weblate (Belarusian)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Aliaksiej Razumaŭ <belarusaed@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translation: Kotatsu/Strings
2022-04-15 12:57:28 +02:00
Koitharu
5e82c75893 Cleanup extensions 2022-04-15 09:09:40 +03:00
Koitharu
9c9a389aa5 Rethrow CancellationException 2022-04-14 08:07:57 +03:00
Koitharu
1b3af70690 Add WindowInsetHolder view 2022-04-14 08:06:16 +03:00
Koitharu
2e17efe82b Update parsers 2022-04-11 18:43:52 +03:00
Koitharu
5bed854b9c Refactor entity mapping 2022-04-10 11:00:05 +03:00
Koitharu
7262b403f0 Hide reading fab if history is empty 2022-04-10 10:25:11 +03:00
Koitharu
a6fcbefc7b Update strings 2022-04-09 18:47:25 +03:00
Koitharu
7f9ea0efa0 Merge branch 'feature/multiselect' into devel 2022-04-09 18:39:25 +03:00
Koitharu
934861322e Migrate to ExtendedFloatingActionButton 2022-04-09 18:35:07 +03:00
Koitharu
e008fbab9b Merge branch 'devel' into feature/multiselect 2022-04-09 08:29:57 +03:00
Koitharu
2cd9ea19fd Update dependencies 2022-04-09 08:28:01 +03:00
Koitharu
699a249620 Merge branch 'documentation-update' of https://github.com/grrrrr/Kotatsu into devel 2022-04-09 07:35:16 +03:00
Koitharu
6c87d5b0bc Add check to avoid TransactionTooLargeException 2022-04-08 18:15:04 +03:00
Koitharu
c92bdae842 Add tags blacklist option for suggestions 2022-04-08 14:56:45 +03:00
Koitharu
6ca9608a80 Remove CurlLoggingInterceptor 2022-04-07 17:23:59 +03:00
Koitharu
8f9c0cbff1 Fix tags suggestion 2022-04-07 17:20:02 +03:00
Koitharu
cc6b114e4d Improve suggestions worker 2022-04-07 17:04:11 +03:00
grrrrr
3d5c2123d4 Update full_description.txt
- Remove HTML code so displaying on sites such as f-droid does not create a lot of wasted space
2022-04-06 19:13:43 +00:00
grrrrr
36b4e16b7c Update full_description.txt
- Remote HTML code so displaying on sites such as f-droid does not create a lot of wasted space
- add additional features taken from updated README.md
2022-04-06 19:12:15 +00:00
grrrrr
3ebd074e93 Update README.md
change feature "localized in" to "available in
2022-04-06 19:10:23 +00:00
grrrrr
e9b2b545a4 Update README.md
- Add additional features (password protection and localization) to list.
- Add details on how to contribute to translation
2022-04-06 19:05:33 +00:00
Koitharu
cca6d5fa04 Migrate to expedited jobs 2022-04-06 18:38:37 +03:00
Koitharu
36a7a3ebbc Fix DownloadService foreground notification #50 2022-04-06 17:24:10 +03:00
Koitharu
48ec9a1ea9 Merge branch 'feature/settings' into devel 2022-04-06 17:23:08 +03:00
Koitharu
76a9a0d1ab ActionMode selection in manga lists 2022-04-06 17:21:09 +03:00
Koitharu
f2175b40c0 Improve android AutoBackup support 2022-04-05 07:40:00 +03:00
Koitharu
85b992ca32 Remove SimpleSettingsActivity 2022-04-04 10:02:20 +03:00
Koitharu
41fb351fe0 Use master-detals pattern for settings 2022-04-04 09:41:57 +03:00
Koitharu
b916d4016e Fix toolbar icons color 2022-04-03 20:00:13 +03:00
Koitharu
abfd7f281d Fix toolbar icons color 2022-04-03 19:50:58 +03:00
Koitharu
515d6ab2c9 Fix widget size 2022-04-03 11:12:29 +03:00
Koitharu
8ee0dd9930 Fix local pages uri 2022-04-03 11:01:15 +03:00
Koitharu
6b9fad493c Update legacy launcher icon 2022-04-03 10:47:16 +03:00
Koitharu
a21297d209 Fix page saving 2022-04-03 10:05:05 +03:00
Koitharu
db3183c6e2 Fix strings 2022-03-31 19:31:19 +03:00
Koitharu
9eaaf96abe Update translations 2022-03-31 17:39:56 +03:00
Aliaksiej Razumaŭ
365b6a410a Translated using Weblate (Belarusian)
Currently translated at 99.2% (268 of 270 strings)

Co-authored-by: Aliaksiej Razumaŭ <belarusaed@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
Allan Nordhøy
a6a601c365 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
J. Lavoie
6ae52df8f8 Translated using Weblate (Finnish)
Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (French)

Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (German)

Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (Spanish)

Currently translated at 99.6% (269 of 270 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
Anupam Malhotra
993c139715 Translated using Weblate (Spanish)
Currently translated at 99.6% (269 of 270 strings)

Translated using Weblate (Spanish)

Currently translated at 99.6% (266 of 267 strings)

Co-authored-by: Anupam Malhotra <anpm.malhotra@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
J. Lavoie
78ca36af11 Translated using Weblate (French)
Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (German)

Currently translated at 100.0% (267 of 267 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
Luiz-bro
078d0c9cf9 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (267 of 267 strings)

Added translation using Weblate (Portuguese (Brazil))

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
kuragehime
40602272da Translated using Weblate (Japanese)
Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (267 of 267 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
Oğuz Ersen
570d488bb3 Translated using Weblate (Turkish)
Currently translated at 100.0% (270 of 270 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (269 of 269 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-31 17:35:43 +03:00
Koitharu
de46cfe7ee Fix manga downloading 2022-03-31 16:18:53 +03:00
Koitharu
8b5a985842 Remove AsyncLayoutInflater; fixes 2022-03-29 20:43:06 +03:00
Koitharu
b57e4c520b Add monochrome icon 2022-03-29 18:45:24 +03:00
Koitharu
ec6b8224ae Update favourite bottom sheet 2022-03-29 08:23:15 +03:00
Koitharu
c48cf83343 Fix default branch selection 2022-03-29 08:13:18 +03:00
Koitharu
0c1ec2b0fc Fixes for api<23 2022-03-28 18:58:32 +03:00
Koitharu
5d2c046d53 Update screenshots 2022-03-27 15:03:49 +03:00
Koitharu
b0f221e5a7 Fixes 2022-03-26 09:07:15 +02:00
Koitharu
85b8bc5d07 Optimize drawables 2022-03-24 06:58:53 +02:00
Koitharu
ae0aa370b2 Update dependencies and fix some warnings 2022-03-24 06:58:53 +02:00
Koitharu
d3e9dc2ea4 Search in chapters #133 2022-03-24 06:58:53 +02:00
Koitharu
d5c7d8997f Update FUNDING.yml 2022-03-20 17:45:20 +02:00
Koitharu
da797741f9 Fix some settings, fix m3 switches 2022-03-20 17:36:29 +02:00
Koitharu
626d84eea3 Fix VersionId test 2022-03-20 17:27:48 +02:00
Koitharu
4d2f32a082 Update ru translations 2022-03-20 17:18:06 +02:00
Koitharu
c7cbe18afd Cleanup resources 2022-03-20 17:15:11 +02:00
Aliaksiej Razumaŭ
d1eb76d960 Translated using Weblate (Belarusian)
Currently translated at 98.8% (265 of 268 strings)

Co-authored-by: Aliaksiej Razumaŭ <belarusaed@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
J. Lavoie
4b49f7d7c1 Translated using Weblate (Finnish)
Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (French)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (German)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Spanish)

Currently translated at 99.6% (266 of 267 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (French)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (German)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (Spanish)

Currently translated at 98.4% (262 of 266 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
kuragehime
fce73f6457 Translated using Weblate (Japanese)
Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
Oğuz Ersen
8d958329b9 Translated using Weblate (Turkish)
Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
Luiz-bro
70006b3cf4 Translated using Weblate (Portuguese)
Currently translated at 100.0% (266 of 266 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
Allan Nordhøy
fbdac9a7c0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (265 of 265 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-03-20 17:04:35 +02:00
Koitharu
8a08d58ed7 Merge branch 'feature/m3' into devel 2022-03-20 17:04:06 +02:00
Zakhar Timoshenko
6dc8ee5cf0 Return backgroundTint to FAB 2022-03-20 11:53:54 +03:00
Koitharu
b646cc00a3 Fix redundant fragments in DetailsActivity 2022-03-19 16:34:48 +02:00
Zakhar Timoshenko
7d2e70da7e Minor UI fixes 2022-03-19 13:55:32 +03:00
Zakhar Timoshenko
83cc3d60c8 Use new M3 switches 2022-03-19 13:54:20 +03:00
Koitharu
15ee102db4 Adjust ui to m3 style 2022-03-19 08:41:50 +02:00
Koitharu
ff25162834 Fixes 2022-03-17 16:51:10 +02:00
Koitharu
4913332444 Remember search mode 2022-03-17 15:32:32 +02:00
Koitharu
996f8f0f2e Fixes 2022-03-17 15:14:46 +02:00
Koitharu
4851139ba5 Improve performance 2022-03-17 11:24:15 +02:00
Koitharu
f0380d7eff Fix non-parcelable extras 2022-03-17 07:28:56 +02:00
Koitharu
11356484b2 Enhance tablet ui (#127)
* Enhance tablet ui

* Some adjustments

* Fix MainActivity insets

* Improve details activity layout

* Fix dialogs width

* Improve thumbnails bs

* Adjust margins in manga details screen

Co-authored-by: Zakhar Timoshenko <vp1984tanki@gmail.com>
2022-03-16 18:49:13 +02:00
Koitharu
e6cd6617ba Fix release build 2022-03-16 18:46:53 +02:00
Koitharu
de176ec040 Merge branch 'feature/desktop-ui' into devel 2022-03-16 18:08:50 +02:00
Koitharu
8a365250d9 Improve sources settings 2022-03-16 18:07:07 +02:00
Koitharu
9bd47e0410 Fix MangaRepository instantiation 2022-03-15 07:26:53 +02:00
Koitharu
02c15f896b Move parsers out of project 2022-03-15 07:06:32 +02:00
Koitharu
150699f64d Improve thumbnails bs 2022-03-13 18:37:50 +02:00
Koitharu
05ffc145be Merge branch 'devel' into feature/desktop-ui 2022-03-13 17:57:10 +02:00
Koitharu
25d52c5a61 Enhance manga search suggestion 2022-03-13 17:53:43 +02:00
Koitharu
abc2fb0e40 Hide FAB on search suggestions 2022-03-13 17:53:43 +02:00
Koitharu
54dfc32455 Make SearchView clearable 2022-03-13 17:53:43 +02:00
Koitharu
3802bc146f Suggest tags on search 2022-03-13 17:53:43 +02:00
Koitharu
8b295f6a93 Fix dialogs width 2022-03-13 17:50:49 +02:00
Koitharu
c115bcc163 Improve details activity layout 2022-03-13 17:10:34 +02:00
Koitharu
88a3589f1d Fix MainActivity insets 2022-03-13 09:54:12 +02:00
Zakhar Timoshenko
52dbd70c2f Some adjustments 2022-03-11 21:50:49 +03:00
Koitharu
0b07e83e3c Enhance tablet ui 2022-03-11 19:30:20 +02:00
Koitharu
445ff89392 Enhance nsfw detection and indication 2022-03-11 19:24:10 +02:00
Koitharu
a8a65e953f Support authorization for MangaLib and HentaiLib #122 2022-03-10 19:52:43 +02:00
Koitharu
755f1e5747 Fix filter 2022-03-10 19:52:43 +02:00
Zakhar Timoshenko
d5d19c37d8 Add referer in TrackWorker 2022-03-10 10:45:34 +03:00
Koitharu
6f85afb841 Merge branch 'weblate-kotatsu-strings' of https://github.com/weblate/Kotatsu into weblate-weblate-kotatsu-strings 2022-03-10 08:45:56 +02:00
Koitharu
3aed24fb49 Fix some authorization issues 2022-03-10 08:22:34 +02:00
Koitharu
2947cd3038 Add NudeMoon manga parser 2022-03-10 08:22:34 +02:00
Koitharu
2849ac58cb Support links in description 2022-03-10 08:22:34 +02:00
Koitharu
a3ef1766a1 Add ComicKFun manga parser 2022-03-10 08:22:34 +02:00
Allan Nordhøy
852bcbbb24 Translated using Weblate (English)
Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translation: Kotatsu/Strings
2022-03-09 01:05:30 +01:00
J. Lavoie
7438b6ce05 Translated using Weblate (Finnish)
Currently translated at 100.0% (265 of 265 strings)

Translated using Weblate (French)

Currently translated at 100.0% (265 of 265 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (265 of 265 strings)

Translated using Weblate (German)

Currently translated at 100.0% (265 of 265 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-03-09 01:05:30 +01:00
kuragehime
fcb301260c Translated using Weblate (Japanese)
Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-03-09 01:05:29 +01:00
Oğuz Ersen
fc4dccb4e9 Translated using Weblate (Turkish)
Currently translated at 100.0% (265 of 265 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-09 01:05:29 +01:00
Zakhar Timoshenko
1f1fcf281d Revert "Use circle mask for thumb in new updates notification"
This reverts commit 8ff4eb26
2022-03-08 22:13:50 +03:00
Koitharu
a0c5b75bba Fix webtoon scroll #20 2022-03-08 19:25:10 +02:00
Koitharu
ccf4e4d285 Migrate to TransitionManager from custom animations 2022-03-08 19:18:02 +02:00
Koitharu
15c570979b Merge branch 'feature/page-preload' into devel 2022-03-08 19:00:13 +02:00
Koitharu
57f3715128 Cleanup resources and code 2022-03-08 18:58:15 +02:00
Koitharu
148986b454 Quick search across genres in filter 2022-03-08 17:28:00 +02:00
Koitharu
179b08b96a Add action for empty list state 2022-03-08 16:06:51 +02:00
Koitharu
d7f60fa95a Fix Batoto empty results 2022-03-08 14:25:46 +02:00
Koitharu
564f052a2f Add Bato.To manga source #77 2022-03-08 14:04:44 +02:00
Zakhar Timoshenko
8ff4eb2602 Use circle mask for thumb in new updates notification 2022-03-08 01:54:03 +03:00
Koitharu
6e5197a3f5 Specify page max progress explicitly 2022-03-07 13:10:09 +02:00
Koitharu
2b8c713169 Merge branch 'devel' into feature/page-preload 2022-03-07 12:55:15 +02:00
J. Lavoie
6a40a388b3 Translated using Weblate (Finnish)
Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (French)

Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (German)

Currently translated at 100.0% (264 of 264 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
mondstern
f52794e93c Translated using Weblate (Russian)
Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (264 of 264 strings)

Co-authored-by: mondstern <mondstern@snopyta.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
kuragehime
26e32ab584 Translated using Weblate (Japanese)
Currently translated at 100.0% (264 of 264 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
Allan Nordhøy
5c3baa8575 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.2% (262 of 264 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
Oğuz Ersen
ff4fe14f89 Translated using Weblate (Turkish)
Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Turkish)

Currently translated at 99.6% (263 of 264 strings)

Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
Luiz-bro
afc9682d53 Translated using Weblate (Portuguese)
Currently translated at 100.0% (264 of 264 strings)

Translated using Weblate (Portuguese)

Currently translated at 98.4% (260 of 264 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
2022-03-07 12:52:44 +02:00
Koitharu
9686ad6f00 Show page progress on ProgressIndicator 2022-03-07 12:42:22 +02:00
Zakhar Timoshenko
ff21d1c4ec Fix incorrect arrow direction symbol 2022-03-06 23:55:15 +03:00
Koitharu
e1285fe738 Option to control pages preloading 2022-03-06 19:56:11 +02:00
Koitharu
889eea9c89 Show page loading progress 2022-03-06 15:14:28 +02:00
Koitharu
4a88ecc549 Show WebView loading progress 2022-03-05 09:01:35 +02:00
Koitharu
6eca4028ec Dont recreate WebView on configuration changed #119 2022-03-05 08:49:10 +02:00
Koitharu
5158f4bd89 Replace chapters dialog with bottom sheet 2022-03-04 20:10:29 +02:00
Koitharu
eb7e255430 Small ui fixes 2022-03-04 19:09:58 +02:00
Koitharu
f6a70dc7ac Fix build 2022-03-04 18:41:03 +02:00
Koitharu
4d447f9f01 Merge branch 'devel' of github.com:nv95/Kotatsu into devel 2022-03-04 18:39:12 +02:00
Oğuz Ersen
6fa8406636 Translated using Weblate (Turkish)
Currently translated at 100.0% (255 of 255 strings)

Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-04 18:37:08 +02:00
Luiz-bro
6d409168e3 Translated using Weblate (Portuguese)
Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.2% (253 of 255 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
2022-03-04 18:37:08 +02:00
Allan Nordhøy
5c10dae028 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.8% (252 of 255 strings)

Translated using Weblate (English)

Currently translated at 100.0% (255 of 255 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-03-04 18:37:08 +02:00
Koitharu
6a965ddb28 Merge branch 'feature/bs-filter' into devel 2022-03-04 18:35:57 +02:00
Koitharu
9b86052624 Merge branch 'feature/suggestions' into devel 2022-03-04 18:34:15 +02:00
Koitharu
3c64d6675e Handle filter loading errors 2022-03-04 08:16:36 +02:00
Koitharu
9588ac8cbd Preload pages 2022-03-03 21:01:16 +02:00
Koitharu
5c05aaeacf Open filter from list header 2022-03-03 18:39:23 +02:00
Koitharu
238bc89be9 Move filter into bottom sheet 2022-03-02 21:05:57 +02:00
Koitharu
28a4d4164e Merge branch 'weblate-kotatsu-strings' of https://github.com/weblate/Kotatsu into weblate-weblate-kotatsu-strings 2022-03-02 19:38:25 +02:00
Koitharu
19fe2e0eb5 Fix strings 2022-03-02 19:26:45 +02:00
Koitharu
862fb3c2e6 Fix badges position 2022-03-02 19:22:51 +02:00
Koitharu
df34e921f3 Fix scrollbars 2022-03-02 19:16:57 +02:00
Koitharu
44c1b5ebb4 Update feed ui 2022-03-02 19:10:39 +02:00
Koitharu
a9454a1455 Suggestions update action 2022-03-02 18:11:56 +02:00
kuragehime
e9e419399c Translated using Weblate (Japanese)
Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (251 of 251 strings)

Co-authored-by: kuragehime <kuragehime641@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
Translation: Kotatsu/Strings
2022-03-02 12:28:40 +01:00
Oğuz Ersen
09db484d5e Translated using Weblate (Turkish)
Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (251 of 251 strings)

Co-authored-by: Oğuz Ersen <oguzersen@protonmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-03-02 12:28:40 +01:00
J. Lavoie
192737bab9 Translated using Weblate (Finnish)
Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (French)

Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (German)

Currently translated at 100.0% (255 of 255 strings)

Translated using Weblate (French)

Currently translated at 100.0% (251 of 251 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (251 of 251 strings)

Translated using Weblate (German)

Currently translated at 100.0% (251 of 251 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-03-02 12:28:40 +01:00
Allan Nordhøy
bb68f7b442 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.6% (250 of 251 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-03-02 12:28:40 +01:00
Zakhar Timoshenko
f46a9c5f3a Fix crash on tablets when clicking on cover 2022-03-02 14:28:28 +03:00
Koitharu
27658eea20 Fix tags case 2022-03-01 07:59:15 +02:00
Zakhar Timoshenko
eec21fc5c1 Adjust manga grid item 2022-02-28 20:25:01 +03:00
Koitharu
5d26743c8f Fix tags for suggestions 2022-02-28 19:08:16 +02:00
Koitharu
3afa782e91 Merge branch 'devel' into feature/suggestions 2022-02-28 18:46:33 +02:00
Koitharu
cfdc3a15c5 Merge branch 'feature/counters' into devel 2022-02-28 18:33:30 +02:00
Koitharu
a2a7c26a42 Block screenshots on password activities #114 2022-02-28 18:28:26 +02:00
Zakhar Timoshenko
7fb67be1b6 Some UI changes 2022-02-28 01:24:21 +03:00
Zakhar Timoshenko
e8a225f97a Update material components dependency 2022-02-28 01:18:59 +03:00
Koitharu
54a914097d Option to block screenshots in reader #114 2022-02-27 20:28:55 +02:00
Koitharu
245e32237e Update widgets from background 2022-02-27 19:22:59 +02:00
Koitharu
29df122369 Move workers initialization to background 2022-02-27 18:47:47 +02:00
Sertinel
894900e955 Translated using Weblate (Turkish)
Currently translated at 47.8% (120 of 251 strings)

Co-authored-by: Sertinel <cankalenderr@yandex.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-02-27 18:26:58 +02:00
Koitharu
632715e6c9 Suggestions settings 2022-02-27 18:25:18 +02:00
Koitharu
97c0fcf022 Merge branch 'devel' of github.com:nv95/Kotatsu into feature/suggestions 2022-02-27 16:32:32 +02:00
Koitharu
b3781abdeb New chapters counters in lists 2022-02-27 09:28:25 +02:00
Koitharu
1f7252fd12 Update feed ui 2022-02-26 18:14:15 +02:00
Koitharu
3c0c4ce9c0 Fix local manga size 2022-02-26 15:42:48 +02:00
Koitharu
ed4c470bdc Support batch manga import 2022-02-26 13:56:21 +02:00
Koitharu
70db9ba94a Update fast scroll 2022-02-26 13:10:34 +02:00
Hosted Weblate
3235141b2e Update translation files
Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
Luiz-bro
2f9364561d Translated using Weblate (Portuguese)
Currently translated at 100.0% (248 of 248 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
Anonymous
8444188616 Translated using Weblate (Russian)
Currently translated at 100.0% (248 of 248 strings)

Translated using Weblate (Turkish)

Currently translated at 22.9% (57 of 248 strings)

Translated using Weblate (Persian)

Currently translated at 2.8% (7 of 248 strings)

Translated using Weblate (Finnish)

Currently translated at 97.9% (243 of 248 strings)

Translated using Weblate (Sinhala)

Currently translated at 2.8% (7 of 248 strings)

Translated using Weblate (Italian)

Currently translated at 99.1% (246 of 248 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fa/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/si/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
J. Lavoie
2d38733822 Translated using Weblate (Finnish)
Currently translated at 97.9% (243 of 248 strings)

Translated using Weblate (French)

Currently translated at 100.0% (248 of 248 strings)

Translated using Weblate (Italian)

Currently translated at 99.1% (246 of 248 strings)

Translated using Weblate (German)

Currently translated at 100.0% (248 of 248 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
Allan Nordhøy
e6b574d13f Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (248 of 248 strings)

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
Anonymous
2e26204a4e Translated using Weblate (Spanish)
Currently translated at 100.0% (248 of 248 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (248 of 248 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
Translation: Kotatsu/Strings
2022-02-26 12:21:41 +02:00
Hosted Weblate
a932fd2cd9 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Update translation files

Updated by "Remove blank strings" hook in Weblate.

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/
Translation: Kotatsu/Strings
2022-02-26 12:06:20 +02:00
Koitharu
a2d3b88c08 Fix non-translatable strings 2022-02-26 12:06:19 +02:00
Koitharu
62a177fcb3 Remove empty non-translated strings 2022-02-26 11:43:59 +02:00
Koitharu
19c751d349 Small ui updates 2022-02-26 11:39:50 +02:00
Koitharu
def2d5f494 Refactor and deprecations fixes 2022-02-26 10:14:40 +02:00
Koitharu
94e9fa35e2 Remove preferences delegates 2022-02-25 19:48:11 +02:00
Zakhar Timoshenko
14be8d4936 Merge remote-tracking branch 'origin/devel' into devel 2022-02-24 22:14:16 +03:00
Zakhar Timoshenko
38b550ecbb Add Discord link in about 2022-02-24 22:12:56 +03:00
Zakhar Timoshenko
b8ecfb5455 Add link to discord badge 2022-02-24 17:22:53 +03:00
Zakhar Timoshenko
f4c9d67178 Add discord badge to README 2022-02-24 17:20:57 +03:00
Koitharu
ad4c65369d Merge pull request #104 from weblate/weblate-kotatsu-strings
Translations update from Hosted Weblate
2022-02-23 18:56:02 +02:00
kuragehime
db6a53de84 Translated using Weblate (Japanese)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
2022-02-23 17:55:15 +01:00
Koitharu
fd25bd5934 Merge pull request #103 from weblate/weblate-kotatsu-strings
Translations update from Hosted Weblate
2022-02-22 20:03:00 +02:00
Anonymous
33b2ec7ab1 Translated using Weblate (Japanese)
Currently translated at 64.5% (162 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
2022-02-22 18:57:48 +01:00
Anonymous
cfb4c8d66a Translated using Weblate (Turkish (Ottoman))
Currently translated at 0.7% (2 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ota/
2022-02-22 18:57:47 +01:00
Anonymous
0797f1809a Translated using Weblate (Turkish)
Currently translated at 23.5% (59 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
2022-02-22 18:57:43 +01:00
Anonymous
e8e1ab6637 Translated using Weblate (Persian)
Currently translated at 2.7% (7 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fa/
2022-02-22 18:57:40 +01:00
Anonymous
1cb5e8134e Translated using Weblate (Arabic)
Currently translated at 0.7% (2 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ar/
2022-02-22 18:57:36 +01:00
Anonymous
246e3ee7d6 Translated using Weblate (Finnish)
Currently translated at 65.3% (164 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
2022-02-22 18:57:31 +01:00
Anonymous
35e782884d Translated using Weblate (Sinhala)
Currently translated at 3.1% (8 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/si/
2022-02-22 18:57:31 +01:00
Anonymous
e5e45fa40f Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-02-22 18:57:28 +01:00
Anonymous
f24aa5af06 Translated using Weblate (Portuguese)
Currently translated at 99.6% (250 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-02-22 18:57:26 +01:00
Anonymous
25ebde1f0a Translated using Weblate (Italian)
Currently translated at 65.7% (165 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2022-02-22 18:57:25 +01:00
Anonymous
120f45a6c5 Translated using Weblate (German)
Currently translated at 74.5% (187 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-02-22 18:57:24 +01:00
Anonymous
fa8ae112ad Translated using Weblate (Norwegian Bokmål)
Currently translated at 93.2% (234 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-02-22 18:57:23 +01:00
Anonymous
c53d7f953d Translated using Weblate (Russian)
Currently translated at 99.2% (249 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2022-02-22 18:57:22 +01:00
Anonymous
9881f9031f Translated using Weblate (Spanish)
Currently translated at 86.0% (216 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-02-22 18:57:19 +01:00
Anonymous
bd11827d8b Translated using Weblate (Belarusian)
Currently translated at 66.5% (167 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2022-02-22 18:57:17 +01:00
Koitharu
40f2713234 Merge remote-tracking branch 'weblate/devel' into devel 2022-02-22 19:50:47 +02:00
Weblate (bot)
b8e564a8d0 Translations update from Hosted Weblate (#96)
* Translated using Weblate (Spanish)

Currently translated at 68.2% (170 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/

* Translated using Weblate (Russian)

Currently translated at 80.3% (200 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.7% (216 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/

* Translated using Weblate (Portuguese)

Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/

* Translated using Weblate (French)

Currently translated at 75.5% (188 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/

* Translated using Weblate (Russian)

Currently translated at 99.5% (248 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/

* Translated using Weblate (German)

Currently translated at 68.9% (173 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/

* Translated using Weblate (Portuguese)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/

* Translated using Weblate (French)

Currently translated at 82.0% (206 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/

* Translated using Weblate (Spanish)

Currently translated at 75.2% (189 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/

* Translated using Weblate (French)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/

* Translated using Weblate (Spanish)

Currently translated at 86.0% (216 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 93.2% (234 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/

* Translated using Weblate (Portuguese)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/

* Added translation using Weblate (Turkish)

* Added translation using Weblate (Turkish (Ottoman))

* Translated using Weblate (Portuguese)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/

* Translated using Weblate (Turkish)

Currently translated at 23.5% (59 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/

* Translated using Weblate (English)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 93.2% (234 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/

* Translated using Weblate (German)

Currently translated at 74.5% (187 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/

* Translated using Weblate (French)

Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/

* Translated using Weblate (Belarusian)

Currently translated at 66.5% (167 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/

* Added translation using Weblate (Japanese)

* Translated using Weblate (Japanese)

Currently translated at 29.0% (73 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/

* Translated using Weblate (Japanese)

Currently translated at 64.5% (162 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Co-authored-by: Zakhar Timoshenko <vp1984tanki@gmail.com>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: mondstern <mondstern@snopyta.org>
Co-authored-by: nzgha <nzgha.hw@runbox.com>
Co-authored-by: Jakob Holkestad Molnes <Jakob.Holkestad.Molnes@gmail.com>
Co-authored-by: Sertinel <cankalenderr@yandex.com>
Co-authored-by: Aliaksiej Razumaŭ <belarusaed@gmail.com>
Co-authored-by: kuragehime <kuragehime641@gmail.com>
2022-02-22 19:47:08 +02:00
Koitharu
9cbca0329a Merge branch 'master' into devel 2022-02-22 19:43:09 +02:00
kuragehime
c376662939 Translated using Weblate (Japanese)
Currently translated at 64.5% (162 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
2022-02-22 18:42:46 +01:00
kuragehime
6f79bf198d Translated using Weblate (Japanese)
Currently translated at 29.0% (73 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/
2022-02-22 18:42:46 +01:00
kuragehime
542deac705 Added translation using Weblate (Japanese) 2022-02-22 18:42:46 +01:00
Aliaksiej Razumaŭ
a905806232 Translated using Weblate (Belarusian)
Currently translated at 66.5% (167 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2022-02-22 18:42:46 +01:00
J. Lavoie
7aeb691427 Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-02-22 18:42:46 +01:00
J. Lavoie
b7922d9096 Translated using Weblate (German)
Currently translated at 74.5% (187 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-02-22 18:42:46 +01:00
Allan Nordhøy
be2d335a5b Translated using Weblate (Norwegian Bokmål)
Currently translated at 93.2% (234 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-02-22 18:42:46 +01:00
Allan Nordhøy
8de5c1fc3d Translated using Weblate (English)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
2022-02-22 18:42:46 +01:00
Sertinel
aac4d1218d Translated using Weblate (Turkish)
Currently translated at 23.5% (59 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
2022-02-22 18:42:46 +01:00
Luiz-bro
ba6474c7bb Translated using Weblate (Portuguese)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-02-22 18:42:45 +01:00
Sertinel
236c0edaaf Added translation using Weblate (Turkish (Ottoman)) 2022-02-22 18:42:45 +01:00
Sertinel
02dc6965d1 Added translation using Weblate (Turkish) 2022-02-22 18:42:45 +01:00
Luiz-bro
735bf66593 Translated using Weblate (Portuguese)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-02-22 18:42:45 +01:00
Jakob Holkestad Molnes
dcc180eea5 Translated using Weblate (Norwegian Bokmål)
Currently translated at 93.2% (234 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-02-22 18:42:45 +01:00
nzgha
694dc7a807 Translated using Weblate (Spanish)
Currently translated at 86.0% (216 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-02-22 18:42:45 +01:00
J. Lavoie
b2b8a62a57 Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-02-22 18:42:45 +01:00
nzgha
f964dd8267 Translated using Weblate (Spanish)
Currently translated at 75.2% (189 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-02-22 18:42:45 +01:00
J. Lavoie
5260295079 Translated using Weblate (French)
Currently translated at 82.0% (206 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-02-22 18:42:45 +01:00
Luiz-bro
6d6f881367 Translated using Weblate (Portuguese)
Currently translated at 100.0% (251 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-02-22 18:42:45 +01:00
mondstern
eae0709c09 Translated using Weblate (German)
Currently translated at 68.9% (173 of 251 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-02-22 18:42:45 +01:00
Zakhar Timoshenko
0c83329e59 Translated using Weblate (Russian)
Currently translated at 99.5% (248 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2022-02-22 18:42:45 +01:00
J. Lavoie
9de5024930 Translated using Weblate (French)
Currently translated at 75.5% (188 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-02-22 18:42:45 +01:00
Luiz-bro
c813677041 Translated using Weblate (Portuguese)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-02-22 18:42:45 +01:00
Allan Nordhøy
d7541a115e Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.7% (216 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-02-22 18:42:45 +01:00
Zakhar Timoshenko
4c911e666e Translated using Weblate (Russian)
Currently translated at 80.3% (200 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2022-02-22 18:42:45 +01:00
Luiz-bro
4e059c4ee3 Translated using Weblate (Spanish)
Currently translated at 68.2% (170 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-02-22 18:42:45 +01:00
Koitharu
15d0addb7b Fix Remanga chapters parsing 2022-02-22 19:34:00 +02:00
Koitharu
1713efb51f Increase version 2022-02-20 18:43:12 +02:00
Koitharu
9089555320 Fix internal storage sharing #98 2022-02-20 18:41:38 +02:00
Koitharu
2f3b1f397c Fix Remanga source and check for paid chapters #101 2022-02-20 18:40:47 +02:00
Koitharu
7ebb98ce06 Allow overwrite non-empty download directory #99 2022-02-20 18:13:54 +02:00
Koitharu
805044fcf1 Add .editorconfig file 2022-02-20 18:12:04 +02:00
Koitharu
51d6a073e0 Refactor local storage manager 2022-02-13 10:21:37 +02:00
Koitharu
02980ea1e6 Allow overwrite non-empty download directory #99 2022-02-13 08:50:41 +02:00
Koitharu
920ea6959c Merge branch 'devel' into feature/suggestions 2022-02-13 08:31:44 +02:00
Koitharu
c7aaa22eab Merge branch 'master' into devel 2022-02-13 07:07:27 +02:00
Koitharu
c218ae0baa Merge branch 'release/2.1.4' 2022-02-12 20:37:41 +02:00
Koitharu
5820b2f511 Fix saved page sharing 2022-02-12 20:31:30 +02:00
Koitharu
79c2bf17fd Quick search across manga sources 2022-02-12 15:16:30 +02:00
Koitharu
78aa4d76db Show favicons in sources list 2022-02-12 15:16:11 +02:00
Koitharu
e2f3ba19b8 Update dependencies minor versions 2022-02-12 15:05:58 +02:00
Koitharu
41045686fc Increase version 2022-02-12 14:58:03 +02:00
Koitharu
8b0b375dfe Fix ActivityNotFoundException 2022-02-12 14:57:27 +02:00
Koitharu
c7c23b9768 Fix ItemTouchHelper leak 2022-02-12 14:57:16 +02:00
Koitharu
33190ae3ea Fix DownloadBinder leak 2022-02-12 14:57:10 +02:00
Koitharu
03590f4b82 Fix widgets context leak 2022-02-12 14:57:03 +02:00
Koitharu
cbcf98e1d4 Fix blocking calls in coroutines 2022-02-12 14:56:30 +02:00
Koitharu
4098f06995 Update material components 2022-02-12 14:07:06 +02:00
Koitharu
98f723200b Fix ActivityNotFoundException 2022-02-12 10:31:26 +02:00
Koitharu
07634d01f3 Fix some settings ui 2022-02-12 10:30:16 +02:00
Koitharu
3bd67e2098 Move LeakCanary to settings 2022-02-11 20:13:43 +02:00
Koitharu
427ce5fd07 Fix ItemTouchHelper leak 2022-02-11 19:41:49 +02:00
Koitharu
6bf927bb2c Fix DownloadBinder leak 2022-02-11 19:32:38 +02:00
Koitharu
da17c3495a Fix widgets context leak 2022-02-11 19:23:41 +02:00
Koitharu
e739e3f9e0 Update dependencies 2022-02-11 19:18:35 +02:00
Koitharu
10ec72047c Update dependencies 2022-02-04 08:18:01 +02:00
Koitharu
4be514b754 Migrate to MaterialDividerItemDecoration 2022-02-03 08:58:12 +02:00
Koitharu
add72c0be3 Fix settings ui 2022-01-28 19:31:28 +02:00
Koitharu
5758eed77b Update chapters list, show already downloaded chapters #95 2022-01-28 19:16:33 +02:00
Koitharu
c7dc05be5a Merge pull request #84 from ztimms73/m3
Material 3
2022-01-28 17:44:20 +02:00
Koitharu
355933c742 Fix blocking calls in coroutines 2022-01-26 19:24:27 +02:00
Zakhar Timoshenko
f2bbf5855b Merge branch 'devel' into m3 2022-01-26 15:24:52 +03:00
Luiz-bro
970200aa40 Translated using Weblate (Portuguese)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-01-26 08:36:43 +02:00
Mohammad
67306734fa Translated using Weblate (Persian)
Currently translated at 3.6% (9 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fa/
2022-01-26 08:36:43 +02:00
Aliaksiej Razumaŭ
b14d629a45 Translated using Weblate (Belarusian)
Currently translated at 99.5% (248 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2022-01-26 08:36:43 +02:00
Mohammad
1fb9eb3e3b Added translation using Weblate (Persian) 2022-01-26 08:36:43 +02:00
b0ywearngtights
1404a83c10 Translated using Weblate (Portuguese)
Currently translated at 45.3% (113 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt/
2022-01-26 08:36:43 +02:00
b0ywearngtights
e18f911b1b Translated using Weblate (Spanish)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-01-26 08:36:43 +02:00
Koitharu
c3f0644b46 Merge branch 'comradekingu-patch-1' into devel 2022-01-26 08:31:58 +02:00
Koitharu
733889f238 Merge branch 'patch-1' of https://github.com/comradekingu/Kotatsu into comradekingu-patch-1 2022-01-26 08:31:20 +02:00
Koitharu
e280aa4963 Quick search across manga sources 2022-01-26 08:22:41 +02:00
Zakhar Timoshenko
254b0ab488 Some cleanup 2022-01-26 01:07:12 +03:00
Zakhar Timoshenko
1253ca07cc Allow Samsung devices on Android 12+ to use dynamic theme 2022-01-26 00:50:38 +03:00
Zakhar Timoshenko
e8bb4bac66 Implement dynamic theme option 2022-01-26 00:45:59 +03:00
Koitharu
2ac6b84f87 Show favicons in sources list 2022-01-25 19:56:37 +02:00
Koitharu
e3a80b5a6d Enhance download cancellation in blocking io tasks #90 2022-01-23 10:31:50 +02:00
Koitharu
66dc5a9597 Fix MangaTown licensed chapters 2022-01-23 10:31:50 +02:00
Koitharu
cb6bf91dd3 Fix missing fragment crash #91 2022-01-23 10:31:50 +02:00
Koitharu
fb815abad0 Fix widgets #86 2022-01-23 10:31:50 +02:00
Koitharu
8ef7580097 Fix MangaRead parse #87 2022-01-23 10:31:50 +02:00
Koitharu
5f5a98e351 Merge branch 'release/2.1.3' into devel 2022-01-23 10:31:13 +02:00
Koitharu
2535739c2b Enhance download cancellation in blocking io tasks #90 2022-01-23 10:13:32 +02:00
Koitharu
b6e13de73f Fix MangaTown licensed chapters 2022-01-23 09:46:26 +02:00
Koitharu
fc3efbabbd Fix missing fragment crash #91 2022-01-23 08:14:56 +02:00
Koitharu
2a7761dbc3 Fix widgets #86 2022-01-23 08:05:07 +02:00
Koitharu
852f31574f Fix MangaRead parse #87 2022-01-23 07:49:03 +02:00
Zakhar Timoshenko
ee79c23fdf Use animation to hide/show fab 2022-01-17 09:40:41 +03:00
Zakhar Timoshenko
097e040dd6 Fix AlertDialogs 2022-01-17 09:26:54 +03:00
Koitharu
722b6d1e59 Cleanup MangaSource fields 2022-01-16 20:14:41 +02:00
Zakhar Timoshenko
eed8ef7010 Initial Material 3 theming 2022-01-16 17:53:03 +03:00
Koitharu
ba30690d26 Add static icons for manga sources in drawer 2022-01-15 18:40:14 +02:00
Koitharu
4da6a4d450 Update dependencies 2022-01-15 18:29:51 +02:00
Koitharu
197393fbd1 Fix webtoon scroll 2022-01-15 17:21:03 +02:00
J. Lavoie
51ef6e3c78 Translated using Weblate (French)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-01-15 08:37:11 +02:00
J. Lavoie
663277fe6f Translated using Weblate (Italian)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2022-01-15 08:37:11 +02:00
J. Lavoie
332a38d674 Translated using Weblate (German)
Currently translated at 100.0% (249 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-01-15 08:37:11 +02:00
Zakhar Timoshenko
e9410a2f54 [MangaOwl] Fix missing pages 2022-01-15 08:20:17 +02:00
Koitharu
b5fa2bd660 Fix MangaDex pages extraction 2022-01-14 08:50:04 +02:00
Koitharu
e56c61d834 Update manga parsers 2022-01-10 18:36:52 +02:00
Allan Nordhøy
7cb51f552a Suggested changes made
Co-authored-by: Koitharu <nvasya95@gmail.com>
2022-01-10 13:32:29 +01:00
Koitharu
677f71dd84 Increase version 2022-01-10 08:53:54 +02:00
Allan Nordhøy
3f90f88600 Translated using Weblate (Norwegian Bokmål)
Currently translated at 87.9% (219 of 249 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-01-10 08:03:16 +02:00
Allan Nordhøy
c7348f7438 Merge branch 'devel' into patch-1 2022-01-07 23:54:56 +01:00
Allan Nordhøy
22ac13c140 Suggested changes made 2022-01-07 20:28:22 +00:00
Koitharu
229a7c70d9 Implement new manga sources settings list screen #78 2022-01-07 19:04:59 +02:00
Koitharu
a2dbec98f9 Fix Ninemanga filter 2022-01-06 17:46:46 +02:00
Koitharu
3a02f8090e Fix pages numbers 2022-01-06 17:31:49 +02:00
Koitharu
17519db44e Refactor sources settings list 2022-01-06 17:26:16 +02:00
Koitharu
99186bf269 Show pages numbers in reader 2022-01-06 09:58:20 +02:00
Koitharu
9a65e40be1 Update page flip animation 2022-01-05 15:46:22 +02:00
Koitharu
f0add59f99 Fix smooth cover loading in details 2022-01-05 15:04:14 +02:00
Koitharu
f18c182a6a Refactor filters 2022-01-05 14:49:18 +02:00
Koitharu
68e9588f24 Fix AniBel endpoint 2022-01-05 11:49:56 +02:00
Koitharu
eea427216d Fullscreen cover view activity 2022-01-05 11:42:03 +02:00
Koitharu
8e9b89f6f0 Fix GroupLe sources covers 2022-01-05 10:51:36 +02:00
Koitharu
4f3281be99 MangaDex source 2022-01-05 10:43:32 +02:00
badlop
eb56a82702 Translated using Weblate (Spanish)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-01-04 12:37:53 +02:00
nzgha
089ccc9d15 Translated using Weblate (Spanish)
Currently translated at 99.1% (244 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2022-01-04 12:37:53 +02:00
J. Lavoie
12c1365513 Translated using Weblate (Finnish)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
2022-01-04 12:37:53 +02:00
J. Lavoie
7ecf9316e3 Translated using Weblate (French)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-01-04 12:37:53 +02:00
J. Lavoie
12e98ec36a Translated using Weblate (Italian)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2022-01-04 12:37:53 +02:00
J. Lavoie
22977fc7bc Translated using Weblate (German)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-01-04 12:37:53 +02:00
Aliaksiej Razumaŭ
b387a49a4e Translated using Weblate (Belarusian)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2022-01-04 12:37:53 +02:00
Allan Nordhøy
dbbb0d0f64 Translated using Weblate (Norwegian Bokmål)
Currently translated at 88.2% (217 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-01-04 12:37:53 +02:00
Allan Nordhøy
0bbf2b752f Translated using Weblate (English)
Currently translated at 100.0% (246 of 246 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
2022-01-04 12:37:53 +02:00
Aliaksiej Razumaŭ
14c1eacffa Translated using Weblate (Belarusian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2022-01-04 12:37:53 +02:00
J. Lavoie
c2a0525bb8 Translated using Weblate (French)
Currently translated at 100.0% (245 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2022-01-04 12:37:53 +02:00
J. Lavoie
4f502e580c Translated using Weblate (Italian)
Currently translated at 100.0% (245 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2022-01-04 12:37:53 +02:00
J. Lavoie
7cb303966a Translated using Weblate (German)
Currently translated at 100.0% (245 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2022-01-04 12:37:53 +02:00
Allan Nordhøy
3f0431f88b Translated using Weblate (Norwegian Bokmål)
Currently translated at 87.3% (214 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2022-01-04 12:37:53 +02:00
Allan Nordhøy
aad5601df1 Translated using Weblate (English)
Currently translated at 100.0% (245 of 245 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
2022-01-04 12:37:53 +02:00
Koitharu
8f2cf8141a Mark HenChan manga as nsfw 2021-12-10 18:10:12 +02:00
Koitharu
eefd1129f7 Update dependencies, setup FragmentStrictMode 2021-12-04 12:09:13 +02:00
Koitharu
5ed0f8b5a6 Check if category name is not empty 2021-12-03 21:11:50 +02:00
Koitharu
9b4aa4fd64 Migrate AniBel parser to graphql 2021-12-03 20:30:20 +02:00
Koitharu
bbb226791b Merge branch 'hotifx/2.0.1' into devel 2021-11-22 08:48:11 +02:00
Koitharu
30ac4435d4 Update version 2021-11-22 08:41:35 +02:00
Koitharu
1b9dfe1901 Temporary change anibel domain 2021-11-21 17:41:32 +02:00
Zakhar Timoshenko
808a6efd8f [Source] [MangaOwl] Fix not loading chapter list 2021-11-21 17:13:39 +02:00
Zakhar Timoshenko
66ed19ed5a [Source] [MangaOwl] Fix not loading chapter list 2021-11-21 17:12:04 +02:00
Koitharu
527a3cbd09 Option to exclude NSFW content from history 2021-11-20 16:49:30 +02:00
Koitharu
f22963b315 Use DownloadManager for pages saving 2021-11-18 20:06:44 +02:00
Koitharu
2ce5cb524f Increase version 2021-11-18 18:43:30 +02:00
Koitharu
4cbc6392fb Update AdapterDelegates library 2021-11-17 19:23:08 +02:00
Koitharu
049f9fa625 Fix cover image in lists 2021-11-17 19:08:13 +02:00
Koitharu
c853fae820 Fix browser activity insets 2021-11-12 20:46:25 +02:00
Koitharu
dd1d84a4fe Remanga authorization support #73 2021-11-12 20:36:01 +02:00
Koitharu
1569aa5dd5 Cleanup data classes 2021-11-12 20:13:49 +02:00
Koitharu
51cd88eded Update dependencies 2021-11-12 20:13:48 +02:00
Aliaksiej Razumaŭ
bf386deef0 Translated using Weblate (Belarusian)
Currently translated at 100.0% (244 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-11-12 20:13:26 +02:00
J. Lavoie
5c80cdee81 Translated using Weblate (Spanish)
Currently translated at 98.7% (241 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-11-12 20:13:26 +02:00
J. Lavoie
b29fbb37cd Translated using Weblate (Finnish)
Currently translated at 100.0% (244 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
2021-11-12 20:13:26 +02:00
J. Lavoie
589831beef Translated using Weblate (French)
Currently translated at 100.0% (244 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-11-12 20:13:26 +02:00
J. Lavoie
0f5d153543 Translated using Weblate (Italian)
Currently translated at 100.0% (244 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-11-12 20:13:26 +02:00
J. Lavoie
ab1c99d132 Translated using Weblate (German)
Currently translated at 100.0% (244 of 244 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-11-12 20:13:26 +02:00
Koitharu
af4870c39c Downscale phone screenshots in metadata 2021-10-25 20:34:27 +03:00
Koitharu
9581b3da65 Update tablet screenshots in metadata 2021-10-25 20:31:08 +03:00
Koitharu
358a907b74 Update phone screenshots in metadata 2021-10-25 08:44:44 +03:00
Koitharu
cdb1d8fe12 Fix manga cover in downloads queue 2021-10-24 17:32:45 +03:00
Koitharu
5513382aea Fix pages bottomsheet scrollbars 2021-10-20 19:34:40 +03:00
Koitharu
a7a5c8978d Fix page image saving 2021-10-20 19:07:36 +03:00
Koitharu
b139d5fca5 Fix saved manga index parsing 2021-10-20 18:50:08 +03:00
Koitharu
977da5b1b4 Optimize chapters list 2021-10-20 18:05:12 +03:00
Koitharu
78f2a13761 Chapter date parse optimization 2021-10-20 08:10:54 +03:00
Koitharu
7ded7fd12a Merge branch 'devel' of github.com:nv95/Kotatsu into devel 2021-10-20 07:41:30 +03:00
Koitharu
e50f79a25e VersionId test 2021-10-20 07:40:49 +03:00
Zakhar Timoshenko
904fc572d0 Adjustments 2021-10-20 07:39:32 +03:00
Zakhar Timoshenko
c280af9a5b Fix crash when trying to download a chapter with mobile internet 2021-10-20 07:39:32 +03:00
Zakhar Timoshenko
af6df6dfa2 Minor fixes 2021-10-20 07:39:32 +03:00
Zakhar Timoshenko
2380d69b11 Add chapter description (date, scanlator) 2021-10-20 07:39:32 +03:00
Zakhar Timoshenko
ad76d6d414 Use custom Snackbar for DetailsActivity 2021-10-20 07:39:32 +03:00
abidin toumi
d911ee12f2 Added translation using Weblate (Arabic) 2021-10-17 16:36:32 +03:00
J. Lavoie
e6ce03b516 Translated using Weblate (Finnish)
Currently translated at 100.0% (242 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
2021-10-17 16:36:32 +03:00
J. Lavoie
17d7deef2d Translated using Weblate (Spanish)
Currently translated at 98.7% (239 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-10-17 16:36:32 +03:00
Koitharu
c2222344a2 Fix pagination 2021-10-09 15:56:19 +03:00
Koitharu
0a8d677fe8 Search by author name 2021-10-09 15:44:57 +03:00
Koitharu
a4e1381238 Improve CoverImageView 2021-10-08 18:56:35 +03:00
Aliaksiej Razumaŭ
1b6837d406 Translated using Weblate (Belarusian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-10-08 18:01:44 +03:00
J. Lavoie
2adf8a139c Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-10-08 18:01:44 +03:00
J. Lavoie
efe96a6e05 Translated using Weblate (Italian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-10-08 18:01:44 +03:00
J. Lavoie
0360df999f Translated using Weblate (German)
Currently translated at 100.0% (242 of 242 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-10-08 18:01:44 +03:00
Zakhar Timoshenko
5cb4758b38 Remove unused strings 2021-10-05 18:53:44 +03:00
Zakhar Timoshenko
fce9f543e1 Trust user-added CAs 2021-10-05 18:53:44 +03:00
Zakhar Timoshenko
9e6cb1837e Remove "Unknown" status label due confusion 2021-10-05 18:53:44 +03:00
J. Lavoie
f9e40e17c4 Translated using Weblate (Spanish)
Currently translated at 97.0% (233 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-10-04 16:38:35 +03:00
J. Lavoie
a09d71cb13 Translated using Weblate (Finnish)
Currently translated at 100.0% (240 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
2021-10-04 16:38:35 +03:00
J. Lavoie
de53445ac5 Translated using Weblate (French)
Currently translated at 100.0% (240 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-10-04 16:38:35 +03:00
J. Lavoie
19fdd54dbd Translated using Weblate (Italian)
Currently translated at 100.0% (240 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-10-04 16:38:35 +03:00
J. Lavoie
1c644188cd Translated using Weblate (German)
Currently translated at 100.0% (240 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-10-04 16:38:35 +03:00
J. Lavoie
a50943ed01 Translated using Weblate (Russian)
Currently translated at 99.5% (239 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2021-10-04 16:38:35 +03:00
J. Lavoie
1888aba335 Translated using Weblate (Spanish)
Currently translated at 96.6% (232 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-10-04 16:38:35 +03:00
Zakhar Timoshenko
b390fd49ca Translated using Weblate (Belarusian)
Currently translated at 100.0% (240 of 240 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-10-04 16:38:35 +03:00
J. Lavoie
33f0eb9f38 Added translation using Weblate (Finnish) 2021-10-04 16:38:35 +03:00
J. Lavoie
db91458abc Translated using Weblate (Spanish)
Currently translated at 97.4% (230 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-10-04 16:38:35 +03:00
Aliaksiej Razumaŭ
ee2ed0159d Translated using Weblate (Belarusian)
Currently translated at 100.0% (236 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-10-04 16:38:35 +03:00
Zakhar Timoshenko
0bdc3e024e MangaOwl adjustments 2021-10-04 16:38:13 +03:00
Zakhar Timoshenko
4aab4e636d Fix display of the snackbar in details activity 2021-10-04 16:38:13 +03:00
Zakhar Timoshenko
af114d74df Add new source: MangaOwl 2021-10-04 16:38:13 +03:00
Zakhar Timoshenko
c5921f8a62 Minor interface adjustments 2021-10-04 16:38:13 +03:00
Zakhar Timoshenko
be0c8f2c96 Add manga status label to details screen 2021-10-04 16:38:13 +03:00
Zakhar Timoshenko
bb685751cd Change Readmanga domain + set User-Agent 2021-10-04 16:38:13 +03:00
Koitharu
22eebe89e7 Merge branch 'devel' into feature/suggestions 2021-09-26 17:37:59 +03:00
Koitharu
fd9737aa9c Update version 2021-09-26 17:20:43 +03:00
Koitharu
1dcb479d62 Add transition to search view 2021-09-23 19:36:01 +03:00
Zakhar Timoshenko
7618a05162 Fix inability to create a backup 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
174c6649e0 Use more correct detection of dark AMOLED theme 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
203608e9fd Minor fix download item 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
07e0ae884c Fix color when search opened with AMOLED mode 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
cd8e256364 Fixed the toolbar color with a light theme and AMOLED mode enabled 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
93998e460c Fix chopped shadows on thumbnails 2021-09-19 13:57:35 +03:00
Zakhar Timoshenko
71f205ca8b Fix AMOLED theme 2021-09-19 13:57:35 +03:00
Koitharu
f9cee7a8f5 Update gradle and dependencies 2021-09-13 08:36:05 +03:00
Koitharu
675e95da2b Show current filter in list header 2021-09-11 16:01:15 +03:00
Koitharu
c1b6cef362 Multiple tags support in (almost) all sources #19 2021-09-11 13:54:56 +03:00
Koitharu
4977464e69 ExHentai manga source 2021-09-11 11:40:37 +03:00
Koitharu
593624fdb9 Manga repository authorization support 2021-09-08 07:27:25 +03:00
Koitharu
c4585c81e1 Merge branch 'devel' into feature/multitag 2021-09-05 16:16:17 +03:00
Koitharu
27293f1bf8 Remove some findViewById 2021-09-05 16:00:15 +03:00
Zakhar Timoshenko
d1fd31701d Use measured height instead of magic numbers 2021-09-05 15:48:52 +03:00
Zakhar Timoshenko
d30c7e6e9c Made UI more like Google apps 2021-09-05 15:48:52 +03:00
Koitharu
0355b61e69 Base support for multiple tags in repositories 2021-09-05 15:48:12 +03:00
XeroOl
5d5ec719b7 Update MangareadRepository.kt 2021-09-01 19:53:03 +03:00
Koitharu
6596dca291 Fix cbz cover fetcher closing, update Kotlin and other small fixes 2021-08-24 18:04:02 +03:00
Koitharu
a296c98602 Update dependencies 2021-08-22 12:31:02 +03:00
Zakhar Timoshenko
be0718acf4 Fix app crash on the first use 2021-08-22 12:17:25 +03:00
Zakhar Timoshenko
c42d913d4c Translated using Weblate (Belarusian)
Currently translated at 100.0% (236 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-08-18 08:11:14 +03:00
J. Lavoie
446649b2bb Translated using Weblate (French)
Currently translated at 100.0% (236 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-08-18 08:11:14 +03:00
J. Lavoie
9f145557ea Translated using Weblate (Italian)
Currently translated at 100.0% (236 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-08-18 08:11:14 +03:00
J. Lavoie
ae856fca74 Translated using Weblate (German)
Currently translated at 100.0% (236 of 236 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-08-18 08:11:14 +03:00
Zakhar Timoshenko
6dc8a4ffb5 Use some animations in sheet toolbar 2021-08-18 08:10:59 +03:00
Zakhar Timoshenko
73498964a8 View close icon if thumbnails sheet is expanded 2021-08-18 08:10:59 +03:00
Zakhar Timoshenko
256f88cc60 Forgot to remove the layout behavior again, wow 2021-08-18 08:10:59 +03:00
Zakhar Timoshenko
16cc6fb117 Set horizontal margin to 32dp 2021-08-18 08:10:59 +03:00
Zakhar Timoshenko
7bb809f227 Improve thumbnail sheet 2021-08-18 08:10:59 +03:00
Zakhar Timoshenko
57111f628d Minor tweaks 2021-08-18 08:10:59 +03:00
Koitharu
0129e9e092 Merge branch 'weblate-kotatsu-strings' of https://github.com/weblate/Kotatsu into weblate-weblate-kotatsu-strings 2021-08-04 08:50:48 +03:00
Zakhar Timoshenko
d6c6132a04 Fixes 2021-08-04 08:46:23 +03:00
Zakhar Timoshenko
eb5976a796 Some changes in about section, fix links 2021-08-04 08:46:23 +03:00
Zakhar Timoshenko
253f4abba1 Minor fix 2021-08-04 08:46:23 +03:00
Zakhar Timoshenko
3a442817ce Add about section to settings, add some info stuff 2021-08-04 08:46:23 +03:00
Zakhar Timoshenko
594c359f1c Added information about the app to a separate activity 2021-08-04 08:46:23 +03:00
Zakhar Timoshenko
cc28d4fe54 Translated using Weblate (Russian)
Currently translated at 99.5% (224 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2021-08-04 07:41:41 +02:00
Zakhar Timoshenko
95708367a1 Translated using Weblate (Belarusian)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-08-04 07:41:41 +02:00
J. Lavoie
89b915b206 Translated using Weblate (French)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-08-04 07:41:41 +02:00
J. Lavoie
e4da0a126c Translated using Weblate (Italian)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-08-04 07:41:41 +02:00
J. Lavoie
56f9cc2c88 Translated using Weblate (German)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-08-04 07:41:41 +02:00
Zakhar Timoshenko
6037c66a2d Translated using Weblate (Russian)
Currently translated at 99.5% (224 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2021-08-04 07:41:41 +02:00
Koitharu
d25837b40b Merge branch 'devel' of https://github.com/nv95/Kotatsu into devel 2021-08-04 08:41:27 +03:00
Koitharu
fbd0f25b8f #8 Configure sort order for each favourites category 2021-08-04 08:40:32 +03:00
Allan Nordhøy
9c55fd166e Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.6% (195 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2021-07-28 08:20:18 +03:00
Allan Nordhøy
2ac1828a0c Translated using Weblate (English)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/en/
2021-07-28 08:20:18 +03:00
J. Lavoie
45e1502c9b Translated using Weblate (French)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-07-28 08:20:18 +03:00
J. Lavoie
e2608cf85a Translated using Weblate (Italian)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-07-28 08:20:18 +03:00
J. Lavoie
05bbfe77b2 Translated using Weblate (German)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-07-28 08:20:18 +03:00
Zakhar Timoshenko
34ad0a7c68 Translated using Weblate (Russian)
Currently translated at 99.5% (224 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/
2021-07-28 08:20:18 +03:00
J. Lavoie
c67ce38350 Translated using Weblate (Spanish)
Currently translated at 93.3% (210 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/
2021-07-28 08:20:18 +03:00
Zakhar Timoshenko
ad79ff2739 Translated using Weblate (Belarusian)
Currently translated at 100.0% (225 of 225 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-07-28 08:20:18 +03:00
J. Lavoie
2e5afc73e7 Translated using Weblate (Italian)
Currently translated at 100.0% (221 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-07-28 08:20:18 +03:00
J. Lavoie
73efe6fd83 Translated using Weblate (German)
Currently translated at 100.0% (221 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-07-28 08:20:18 +03:00
HelaBasa
c59e3165b6 Translated using Weblate (Sinhala)
Currently translated at 4.0% (9 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/si/
2021-07-28 08:20:18 +03:00
J. Lavoie
ec8c5e0fd4 Translated using Weblate (French)
Currently translated at 100.0% (221 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-07-28 08:20:18 +03:00
J. Lavoie
149ac9280c Translated using Weblate (Italian)
Currently translated at 90.9% (201 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-07-28 08:20:18 +03:00
J. Lavoie
af20f65468 Translated using Weblate (German)
Currently translated at 88.6% (196 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-07-28 08:20:18 +03:00
Koitharu
6f7efa9e26 Optimize layout 2021-07-28 08:03:16 +03:00
Koitharu
7f5ef227eb Show not downloaded chapters in local manga 2021-07-24 10:51:26 +03:00
Koitharu
e8e95a485b Downloads queue activity 2021-07-23 06:51:01 +03:00
Koitharu
77186d271d Fix list headers 2021-07-21 19:13:30 +03:00
Koitharu
ebeaf9703f Refactor download service 2021-07-21 19:13:29 +03:00
Koitharu
625b2769c6 Improve search ui 2021-07-21 19:13:29 +03:00
Koitharu
52e136ddef Source name in list header 2021-07-21 19:13:29 +03:00
Koitharu
78fe18735b Database migrations test 2021-07-21 19:13:29 +03:00
HelaBasa
2f89c0bb92 Added translation using Weblate (Sinhala) 2021-07-21 07:02:50 +03:00
J. Lavoie
fbac8881ce Translated using Weblate (French)
Currently translated at 100.0% (221 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
2021-07-21 07:02:50 +03:00
J. Lavoie
b51b3460c0 Translated using Weblate (Italian)
Currently translated at 31.6% (70 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
2021-07-21 07:02:50 +03:00
J. Lavoie
aaea4147a4 Translated using Weblate (German)
Currently translated at 37.1% (82 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
2021-07-21 07:02:50 +03:00
Koitharu
d2609c0560 Improve remote repository tests 2021-07-16 07:43:20 +03:00
Koitharu
6a3421df8a Adjust nullability in parsers 2021-07-14 07:01:11 +03:00
Koitharu
86be393335 Update dependencies 2021-07-14 07:00:41 +03:00
Allan Nordhøy
96d6f9d80d Translated using Weblate (Norwegian Bokmål)
Currently translated at 86.8% (192 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nb_NO/
2021-07-12 20:45:18 +03:00
Zakhar Timoshenko
384d0345f5 Translated using Weblate (Belarusian)
Currently translated at 100.0% (221 of 221 strings)

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/
2021-07-12 20:45:18 +03:00
Zakhar Timoshenko
eb780a1449 Added translation using Weblate (French) 2021-07-12 20:45:18 +03:00
Zakhar Timoshenko
15d094a175 Added translation using Weblate (Portuguese) 2021-07-12 20:45:18 +03:00
Zakhar Timoshenko
eba5e484d6 Added translation using Weblate (Italian) 2021-07-12 20:45:18 +03:00
Zakhar Timoshenko
7402e8569a Added translation using Weblate (German) 2021-07-12 20:45:18 +03:00
Allan Nordhøy
8ae7863185 Added translation using Weblate (Norwegian Bokmål) 2021-07-12 20:45:18 +03:00
Hosted Weblate
75b9fd1b7a Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/
2021-07-12 20:45:18 +03:00
Hosted Weblate
dc46657fa6 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Kotatsu/Strings
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/
2021-07-12 20:45:18 +03:00
ztimms73
d77177bbfd Change some colors of dark theme 2021-07-12 20:44:44 +03:00
ztimms73
7c6a97e264 Using Totoro vector icon 2021-07-12 20:44:44 +03:00
Koitharu
23f84c2416 Add Weblate badge to README 2021-07-12 20:43:40 +03:00
Koitharu
550dfa9c9e Update app/src/main/res/values/strings.xml
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2021-07-12 20:29:30 +03:00
Koitharu
e6b6a6bb37 Update app/src/main/res/values/strings.xml
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
2021-07-12 20:29:14 +03:00
Allan Nordhøy
92f9438992 App strings reworked 2021-07-12 12:59:34 +00:00
Koitharu
d41a813e41 Merge branch 'master' into devel 2021-07-12 08:48:34 +03:00
Koitharu
fae958f6ef Remove unused resources 2021-07-07 07:25:31 +03:00
Koitharu
d8db89326f Info about background restrictions 2021-07-07 07:13:02 +03:00
Koitharu
3804896788 Save backup instead of sharing 2021-07-06 20:26:52 +03:00
Koitharu
4aedea7e15 Improve accesibility in reader 2021-07-06 19:20:41 +03:00
Koitharu
ed89d76488 Fix resource shrinking 2021-07-03 16:12:16 +03:00
Koitharu
bbd43b51e3 Increase version 2021-06-28 15:46:13 +03:00
Koitharu
e5448fa8ab Add some widgets 2021-06-28 15:41:39 +03:00
Koitharu
a6a392c7bf Merge pull request #36 from ztimms73/fix-crashes
Fix possible crashes
2021-06-28 15:41:14 +03:00
ztimms73
08f92f9614 Fix possible crashes 2021-06-28 13:59:45 +03:00
Koitharu
c9cf09f4dd Merge pull request #34 from ztimms73/ui-patch
Some UI changes
2021-06-26 16:17:36 +03:00
Koitharu
ab1624c918 Replace ProgressBar with ProgressIndicator 2021-06-26 16:15:21 +03:00
Koitharu
62396111e3 Update dependencies 2021-06-26 15:51:57 +03:00
Koitharu
e37f6f31da Merge branch 'master' into devel 2021-06-26 15:19:50 +03:00
Koitharu
873b41e4f9 Fix default languages selector 2021-06-26 15:15:53 +03:00
Koitharu
f0d4deffd7 Fix Mangaread parser 2021-06-26 14:49:13 +03:00
Koitharu
b6c50d59ed #35 Fix Mangaread parser 2021-06-24 07:27:07 +03:00
Koitharu
9fcc19ef7e Fix filename transliteration 2021-06-23 19:34:10 +03:00
Koitharu
b90ebdabf9 Fix storage dirs enumeration 2021-06-21 17:53:04 +03:00
Koitharu
e08a4cf1b2 Fix crash if title is empty 2021-06-21 17:50:16 +03:00
Koitharu
bd4efcf110 Remove old search option from menu 2021-06-21 17:32:23 +03:00
ztimms73
0b9013e8b2 Use expanded SearchView in Toolbar instead of an menu option 2021-06-21 14:06:08 +03:00
ztimms73
445128f462 Forgot set correct icon 2021-06-20 20:13:19 +03:00
ztimms73
f50a8b3112 Fix toolbars not scrolled when option was enabled 2021-06-20 20:11:17 +03:00
ztimms73
ed65145f83 Change some icons for empty views 2021-06-20 20:07:44 +03:00
ztimms73
49e08eaf2f UI changes 2021-06-20 19:30:29 +03:00
Koitharu
83a9570961 Prompt before search history clear 2021-06-20 16:04:12 +03:00
Koitharu
973a4073f0 Fix crash in history settings 2021-06-20 15:59:24 +03:00
Koitharu
867812b8e3 Update koin 2021-06-20 15:17:48 +03:00
Koitharu
cf7341b065 Update translations 2021-06-20 14:55:22 +03:00
Koitharu
de3c4545e6 Fix statusbar color for actionmode 2021-06-18 07:47:36 +03:00
Koitharu
a483d21120 Merge branch 'redesign' of https://github.com/ztimms73/Kotatsu into devel 2021-06-18 07:35:24 +03:00
ztimms73
665d46b7c4 Some reformat 2021-06-18 03:20:41 +03:00
ztimms73
3d5a1e9b30 Finally update details layouts 2021-06-18 03:17:38 +03:00
ztimms73
e7e9c5fe9f Avoiding overlapping content 2021-06-17 23:35:19 +03:00
ztimms73
c71460fcd8 Minor fixes 2021-06-17 23:33:52 +03:00
Koitharu
8c2bc078e5 Manga languages onboarding 2021-06-17 19:45:36 +03:00
ztimms73
75b1068d46 Little cleanup 2021-06-17 10:06:52 +03:00
ztimms73
4ac406aa2d Reformat and some fixes 2021-06-17 10:03:36 +03:00
ztimms73
f4f367850e Cleanup unused resources 2021-06-17 09:54:28 +03:00
ztimms73
b293e9f370 Minor fixes 2021-06-17 01:57:52 +03:00
ztimms73
4e2350e5fc Two lines of title are better than one 2021-06-17 01:41:31 +03:00
ztimms73
09412719b7 Redesign (#24) 2021-06-17 00:46:27 +03:00
Koitharu
cd7d6d7674 New search suggestion UI 2021-06-03 19:15:57 +03:00
Koitharu
bc0c5ac71a Fix Anibel titles 2021-05-23 17:17:08 +03:00
Koitharu
91619cc259 NineManga sources #14 2021-05-23 16:58:45 +03:00
Koitharu
f0c9c61b49 Fix issues with spanish translation 2021-05-20 08:12:09 +03:00
Koitharu
d65158b7b9 Update Kotlin to 1.5 and dependencies 2021-05-20 08:09:35 +03:00
Koitharu
4e5de1e33e Merge pull request #32 from ztimms73/devel
Fix some problems from issue #23
2021-05-19 06:51:49 +03:00
ztimms73
b009a6423d Fix some problems from issue #23 2021-05-18 11:17:00 +03:00
Koitharu
467d0c8e18 Merge pull request #30 from ztimms73/sources
Fix Remanga sort, new manga source Anibel, UI changes
2021-05-17 19:48:52 +03:00
ztimms73
4d535cef41 Avoid searching for anime on Anibel 2021-05-15 22:51:45 +03:00
ztimms73
98147d0a81 Fix Anibel issues 2021-05-15 22:05:32 +03:00
ztimms73
323c1defaa Fix Remanga (closes #28) 2021-05-15 10:28:23 +03:00
Zakhar Timoshenko
60c5408ae8 Merge branch 'nv95:devel' into devel 2021-05-15 10:11:07 +03:00
ztimms73
51dc2ac046 Added the option to hide or not toolbar when scrolling 2021-05-15 08:56:03 +03:00
ztimms73
24d9a49420 Merge remote-tracking branch 'origin/devel' into devel 2021-05-14 22:45:07 +03:00
ztimms73
46891aa958 Minor UI changes 2021-05-14 22:43:14 +03:00
ztimms73
d1921193f0 Add Anibel source 2021-05-14 22:42:43 +03:00
Koitharu
a8c4c4045c Merge pull request #27 from ztimms73/devel
Belarusian translation and minor fixes in Russian
2021-05-14 07:16:06 +03:00
Zakhar Timoshenko
0559c13dc6 Fix 2021-05-13 20:29:01 +03:00
Xtimms
3fbec046ba Belarusian translation and minor fixes in Russian 2021-05-13 20:26:17 +03:00
Koitharu
f0e56c4b6a Suggestions 2021-05-12 20:10:47 +03:00
Koitharu
4c8fa91af4 Merge pull request #26 from sguinetti/devel
Add spanish translation
2021-05-12 07:05:07 +03:00
sguinetti
1568c09fa2 Add spanish translation 2021-05-09 11:21:03 -05:00
Koitharu
0e74d6e017 Merge branch 'master' into devel 2021-05-03 18:18:55 +03:00
Koitharu
7690a29efb Add f-droid link to readme 2021-05-03 18:16:33 +03:00
Koitharu
b1d6f5debd Fix onApplyWindowInsets infinite call 2021-04-29 08:06:37 +03:00
Koitharu
fbb92005a1 Update database structure 2021-04-29 07:57:43 +03:00
Koitharu
5b9922d509 Remove unused code 2021-04-29 07:24:26 +03:00
Koitharu
49eebdf554 Specify LazyThreadSafetyMode for inject and viewModel delegates 2021-04-27 19:52:20 +03:00
Koitharu
2da941d550 Update dependencies 2021-04-27 19:41:41 +03:00
Koitharu
5a8d7531bf Ui fixes 2021-04-11 12:20:12 +03:00
Koitharu
4d1f5e22d3 #21 Fix cloudflare passing 2021-04-11 11:33:04 +03:00
Koitharu
012416c881 Improve password protection 2021-04-11 11:24:50 +03:00
Koitharu
0f48ad07a3 Support no-fullheight pages in webtoon mode 2021-04-04 11:18:12 +03:00
Koitharu
64752da948 Optimize global search 2021-04-02 15:26:27 +03:00
Koitharu
95148a1071 Add distributionSha256Sum for gradle wrapper 2021-03-30 07:49:10 +03:00
Koitharu
d9d0656ef4 Update dependencies and gradle 2021-03-29 20:00:05 +03:00
Koitharu
b17d8efa5c Update Koin to 3.0 2021-03-29 19:18:08 +03:00
Koitharu
b07fcf5842 Use static version code 2021-03-28 11:34:57 +03:00
Koitharu
f669a1ca0f Update version name 2021-03-25 19:38:50 +02:00
Koitharu
5a921ea862 Update readme 2021-03-25 19:30:28 +02:00
Koitharu
810efde0b0 Add metadata 2021-03-25 19:17:46 +02:00
Koitharu
03510a1f19 Update dependencies 2021-03-25 07:47:43 +02:00
Koitharu
049f32d2f0 Fix smooth page switching 2021-03-21 18:33:13 +02:00
Koitharu
11a9db3cc2 Fix "Unsupported image format" error 2021-03-21 18:18:57 +02:00
Koitharu
57dd5743f0 Fix tabs on landscape 2021-03-21 18:16:38 +02:00
Koitharu
5f37e76c85 Update dialogs 2021-03-19 21:11:36 +02:00
Koitharu
fc51d49505 Fix lists padding 2021-03-19 20:42:14 +02:00
Koitharu
3dde254452 Refresh tabs style 2021-03-19 20:14:08 +02:00
Koitharu
aa21dd9721 Fixes 2021-03-19 19:38:29 +02:00
Koitharu
71f5ee8cb1 Support for multiple manga branches (translations, etc) 2021-03-08 10:30:15 +02:00
Koitharu
40f27ae634 Fix page saving 2021-02-25 20:10:38 +02:00
Koitharu
0dfba47d85 Misc small fixes 2021-02-19 20:21:44 +02:00
Koitharu
69e44b10e9 Fix tags on details screen 2021-02-18 20:25:01 +02:00
Koitharu
4cd0cb04a3 Fix reader state restoration 2021-02-16 20:22:18 +02:00
Koitharu
d9d5595bde Ellipsize chapters in feed 2021-02-16 20:03:25 +02:00
Koitharu
ed70ca4e18 Information toast in reader 2021-02-11 19:29:17 +02:00
Koitharu
a371bb6514 Fix activity leak on Android Q 2021-02-08 20:29:32 +02:00
Koitharu
ee26a3e434 Fix search pagination 2021-02-03 07:14:46 +02:00
Koitharu
5bb6eae673 Use publicUrl instead of url 2021-02-03 07:09:29 +02:00
Koitharu
3357c00578 Add "public url" field to manga 2021-02-02 08:01:46 +02:00
Koitharu
1f2f40f077 Fix DesuMe parser 2021-02-01 20:37:41 +02:00
Koitharu
c25ee93ccb Update source preferences 2021-02-01 20:19:46 +02:00
Koitharu
4aa1b58109 Use relative urls for mangas and change id generation algorythm 2021-01-30 18:57:11 +02:00
Koitharu
c64115a268 Remove REQUEST_IGNORE_BATTERY_OPTIMIZATIONS feature 2021-01-29 07:20:10 +02:00
Koitharu
33296217a4 Fix title in BrowserActivity 2021-01-28 20:33:20 +02:00
Koitharu
0e384c134d Fix some manga sources 2021-01-27 18:24:48 +02:00
Koitharu
7f37c1f99e Option to reverse chapters order 2021-01-25 19:09:01 +02:00
Koitharu
d1aa0f0407 Fix action mode 2021-01-24 17:39:14 +02:00
Koitharu
4d904fe12f Tracker become foreground mode 2021-01-24 10:28:15 +02:00
Koitharu
3df8b8d170 Update preferences 2021-01-24 10:02:17 +02:00
Koitharu
42f0fa9bbf Fix grid spacing 2021-01-24 09:02:17 +02:00
Koitharu
5cbc592d23 Show manga source in details 2021-01-24 08:53:04 +02:00
Koitharu
85c424580a Add Remanga source 2021-01-23 19:44:11 +02:00
Koitharu
0d0e3acd04 Fix MangaLib search 2021-01-22 20:12:33 +02:00
Koitharu
49f9fb0488 Hide unknown rating in list 2021-01-22 19:41:19 +02:00
Koitharu
bbcd96b981 Clear updates feed from options menu 2021-01-22 19:17:49 +02:00
Koitharu
510c5b70c9 Show progress of new chapters checking 2021-01-22 18:26:02 +02:00
Koitharu
951a0db3f2 Fix snackbars in settings 2021-01-22 18:25:29 +02:00
Koitharu
d85f23b320 Replace RequestDraft with plain Url 2021-01-21 08:03:48 +02:00
Koitharu
0c0214a85e Fix MangaLib 2021-01-21 07:32:50 +02:00
Koitharu
9054f5720f Refactor repository creation 2021-01-20 20:27:47 +02:00
Koitharu
bb1dd74277 Support custom headers for page requests 2021-01-20 19:53:11 +02:00
Koitharu
96d437b2a8 Use system CookieManager as CookieJar 2021-01-20 07:50:35 +02:00
Koitharu
8f8d85d172 Fixes and refactor 2021-01-18 19:32:13 +02:00
Koitharu
a242aa6633 Fix backup restore 2021-01-10 11:13:39 +02:00
Koitharu
1a0986212b Support Referer header for image requests 2021-01-07 14:48:35 +02:00
Koitharu
22e7bab879 Fix chapters preloading 2021-01-07 13:18:57 +02:00
Koitharu
9bd7daef65 Shared RecycledViewPool 2021-01-07 10:41:50 +02:00
Koitharu
d1e17c8ec2 Fix favourites categories 2021-01-06 07:57:26 +02:00
Koitharu
e674e0f36f Optimize LiveData from flows 2020-12-28 07:20:21 +02:00
Koitharu
7fd71c13f3 Fixes 2020-12-26 16:23:13 +02:00
Koitharu
9a0b7c4700 Fix tracker duplicates 2020-12-20 17:44:05 +02:00
Koitharu
c54d128c09 Fix page saving 2020-12-20 17:40:25 +02:00
Koitharu
a1545fd889 Fix zoom changing 2020-12-20 16:49:51 +02:00
Koitharu
6e1fdcb19a Fix AlertDialogFragment view lifecycle 2020-12-20 16:37:27 +02:00
Koitharu
72bedfd92e Fix reader animation changes 2020-12-18 07:08:18 +02:00
Koitharu
c132f1d5c4 Fix shortcuts 2020-12-17 19:07:22 +02:00
Koitharu
abc4ab92a9 Fix reader immersive mode 2020-12-17 18:22:22 +02:00
Koitharu
0931e4e0e6 Misc fixes 2020-12-16 17:48:26 +02:00
Koitharu
113cde2f07 Sort favourites by date descending 2020-12-16 15:30:54 +02:00
Koitharu
bf2d82723b Refactor objects to classes 2020-12-16 15:28:58 +02:00
Koitharu
6463023736 Edge-to-edge ui 2020-12-16 13:24:49 +02:00
Koitharu
b8d2fa69c4 Change shortcuts target to reader 2020-12-16 08:32:57 +02:00
Koitharu
904d12f611 Refactor reader 2020-12-16 08:26:01 +02:00
Koitharu
71a5801a0c Some fixes for favourites 2020-12-08 07:26:52 +02:00
Koitharu
6b529f806f Fix default value for some preferences 2020-12-05 18:15:18 +02:00
Koitharu
9b5510ac59 Move list states to adapter delegates 2020-12-05 18:03:34 +02:00
Koitharu
90be936c82 Optimize images loading 2020-12-01 19:49:04 +02:00
Koitharu
29e6eab0e7 Drop Jetifier 2020-12-01 18:30:16 +02:00
Koitharu
75b3ea0bc9 Migrate to ViewBinding 2020-12-01 18:30:11 +02:00
Koitharu
a215d9ebfc Fix search 2020-11-28 17:57:12 +02:00
Koitharu
cef5d91eec Fast scroll in lists 2020-11-28 14:15:31 +02:00
Koitharu
9c20559962 Option to group history by date 2020-11-28 14:02:03 +02:00
Koitharu
b1be45af8b Merge branch 'feature/mvvm' into devel 2020-11-28 11:05:59 +02:00
Koitharu
5ed4d0b6b7 Fully migrate to AdapterDelegates and cleanup code 2020-11-28 11:05:27 +02:00
Koitharu
53e36d23b1 Migrate favourite categories to AdapterDelegates 2020-11-28 08:30:49 +02:00
Koitharu
fa02cfd7e8 Migrate details to AdapterDelegates and mvvm 2020-11-24 07:37:23 +02:00
Koitharu
1b1540b35b Upgrade kotlin 2020-11-23 19:28:16 +02:00
Koitharu
b9f35f34ad Migrate feed to adapter delegates 2020-11-23 19:16:02 +02:00
Koitharu
12c8cdfd70 Remove Related manga tab from details 2020-11-20 20:15:50 +02:00
Koitharu
971f708e45 Fully manga list fragments to AdapterDelegates and mvvm 2020-11-20 20:07:57 +02:00
Koitharu
7e76e10591 Migrate to AdapterDelegates 2020-11-19 20:43:36 +02:00
Koitharu
7d24286c55 Migrate to MVVM 2020-11-18 06:56:12 +02:00
Koitharu
eaac271143 Remove from favourites via popup menu 2020-11-17 07:32:44 +02:00
Koitharu
d135898b49 Backup and restore user data 2020-11-16 19:16:31 +02:00
Koitharu
03dbd86363 Fix some StrictMode warnings 2020-11-09 20:33:53 +02:00
Koitharu
908baebb62 Dark amoled theme 2020-11-09 19:43:01 +02:00
Koitharu
5190ec3e98 Passing CloudFlare checks 2020-11-09 19:17:08 +02:00
Koitharu
17c20b2bf9 Handle CloudFlare protection #13 2020-11-07 17:50:08 +02:00
Koitharu
e2b65f6fb6 Fix Grouple external links 2020-11-07 17:24:11 +02:00
Koitharu
28a9659410 Scale mode option for reader 2020-11-07 15:51:07 +02:00
Koitharu
bdebd0578e Fix crash in settings 2020-11-03 18:06:09 +02:00
Koitharu
53542f3f86 Update crash activity 2020-11-03 17:39:23 +02:00
Koitharu
2772f0b3dd Remove preferences keys from resources 2020-11-03 16:51:31 +02:00
Koitharu
95a4bf41d2 Popup menu on favourite tabs 2020-11-02 19:54:43 +02:00
Koitharu
e497781359 Option to prefer Rtl reader 2020-11-02 19:13:07 +02:00
Koitharu
72fdc7796f Use ArrayDeque in reader 2020-10-28 07:56:16 +02:00
Koitharu
a885709ba9 Reversed reader mode #15 2020-10-25 11:55:15 +02:00
Koitharu
578c1c3825 Ui fixes 2020-10-23 20:44:55 +03:00
Koitharu
a5fba83510 Refactor: Provide manga parsers via DI 2020-10-20 21:45:24 +03:00
Koitharu
6f3ae19345 Checking for updates in settings 2020-10-20 20:52:43 +03:00
Koitharu
2135195f27 MangaRead parser #17 2020-10-19 20:24:58 +03:00
Koitharu
a8c22de601 Reduce memory usage 2020-10-18 20:11:08 +03:00
Koitharu
56e145420c DI refactoring 2020-10-18 19:05:15 +03:00
Koitharu
fb60b26f08 Remove chucker 2020-10-18 15:14:14 +03:00
Koitharu
ff3ebbf1d9 Add NudeMoon parser (broken) 2020-10-18 15:09:42 +03:00
Koitharu
4dc9df0515 Refactor 2020-10-11 17:11:34 +03:00
Koitharu
e9bce8ef15 Password protection 2020-10-11 16:45:29 +03:00
Koitharu
55fc1aeadd Option to configure tracked manga 2020-10-11 13:55:04 +03:00
Koitharu
693f568b8e Refactor BasePresenter 2020-10-11 13:16:38 +03:00
Koitharu
5293a8d209 Update dependencies 2020-10-11 12:50:52 +03:00
Koitharu
1c46fc7f23 Fix manga downloading 2020-09-30 20:36:53 +03:00
Koitharu
b7e4c6b8c0 New cbz write utility 2020-09-26 17:51:47 +03:00
Koitharu
df599e9d50 Fix MangaLib parser 2020-09-25 19:44:18 +03:00
Koitharu
6009f089e7 Update coil version 2020-09-25 19:23:57 +03:00
Koitharu
0a4f2f848e UI fixes 2020-09-20 17:31:33 +03:00
Koitharu
85fc3a024c Fix henchan 2020-09-20 17:08:42 +03:00
Koitharu
eeb536b1ac Fix crash on import 2020-09-19 17:32:22 +03:00
Koitharu
5b8e8d76c0 Update target sdk 2020-09-19 17:27:45 +03:00
Koitharu
73cf2964b2 Option to manually track manga updates 2020-09-19 15:22:18 +03:00
Koitharu
8372f9b5de Update dependencies 2020-09-19 14:21:32 +03:00
Koitharu
d7181e35e7 Update dependencies 2020-09-05 19:37:40 +03:00
Koitharu
55d824bb94 Remove header from drawer 2020-08-31 19:40:58 +03:00
Koitharu
229d9fa2ae Update launcher icon 2020-08-31 19:37:14 +03:00
Koitharu
3eb68e1ff9 Manual screen rotation in reader 2020-08-28 21:01:59 +03:00
Koitharu
b103589bba Fix unsupported image formats in reader 2020-08-27 19:54:53 +03:00
Koitharu
0726c037a4 Update dependencies 2020-08-26 16:14:32 +03:00
Koitharu
0ff64931e0 Close drawer on back pressed 2020-08-09 16:54:00 +03:00
995 changed files with 32954 additions and 15344 deletions

19
.editorconfig Normal file
View File

@@ -0,0 +1,19 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = false
max_line_length = 120
tab_width = 4
# noinspection EditorConfigKeyCorrectness
disabled_rules=no-wildcard-imports,no-unused-imports
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
ij_continuation_indent_size = 4
[{*.kt,*.kts}]
ij_kotlin_allow_trailing_comma = true
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL

2
.github/FUNDING.yml vendored
View File

@@ -1 +1 @@
custom: ["https://money.yandex.ru/to/410012543938752"]
custom: ["https://yoomoney.ru/to/410012543938752"]

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: ⚠️ Source issue
url: https://github.com/nv95/kotatsu-parsers/issues/new
about: Issues and requests for sources should be opened in the kotatsu-parsers repository instead

93
.github/ISSUE_TEMPLATE/report_issue.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: 🐞 Issue report
description: Report an issue in Kotatsu
labels: [bug]
body:
- type: textarea
id: reproduce-steps
attributes:
label: Steps to reproduce
description: Provide an example of the issue.
placeholder: |
Example:
1. First step
2. Second step
3. Issue here
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: Explain what you should expect to happen.
placeholder: |
Example:
"This should happen..."
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual behavior
description: Explain what actually happens.
placeholder: |
Example:
"This happened instead..."
validations:
required: true
- type: input
id: kotatsu-version
attributes:
label: Kotatsu version
description: You can find your Kotatsu version in **Settings → About**.
placeholder: |
Example: "3.2.2"
validations:
required: true
- type: input
id: android-version
attributes:
label: Android version
description: You can find this somewhere in your Android settings.
placeholder: |
Example: "Android 12"
validations:
required: true
- type: input
id: device
attributes:
label: Device
description: List your device and model.
placeholder: |
Example: "LG Nexus 5X"
validations:
required: true
- type: textarea
id: other-details
attributes:
label: Other details
placeholder: |
Additional details and attachments.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options:
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open issue.
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with a source, I should be opening an issue in the [parsers repository](https://github.com/nv95/kotatsu-parsers/issues/new).
required: true
- label: I have updated the app to version **[3.2.2](https://github.com/nv95/Kotatsu/releases/latest)**.
required: true
- label: I will fill out all of the requested information in this form.
required: true

View File

@@ -0,0 +1,39 @@
name: ⭐ Feature request
description: Suggest a feature to improve Kotatsu
labels: [feature request]
body:
- type: textarea
id: feature-description
attributes:
label: Describe your suggested feature
description: How can Kotatsu be improved?
placeholder: |
Example:
"It should work like this..."
validations:
required: true
- type: textarea
id: other-details
attributes:
label: Other details
placeholder: |
Additional details and attachments.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options:
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open issue.
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with a source, I should be opening an issue in the [parsers repository](https://github.com/nv95/kotatsu-parsers/issues/new).
required: true
- label: I have updated the app to version **[3.2.2](https://github.com/nv95/Kotatsu/releases/latest)**.
required: true
- label: I will fill out all of the requested information in this form.
required: true

4
.gitignore vendored
View File

@@ -3,10 +3,14 @@
/local.properties
/.idea/caches
/.idea/libraries
/.idea/dictionaries
/.idea/modules.xml
/.idea/misc.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/kotlinScripting.xml
/.idea/deploymentTargetDropDown.xml
.DS_Store
/build
/captures

View File

@@ -23,6 +23,7 @@
</option>
</AndroidXmlCodeStyleSettings>
<JetCodeStyleSettings>
<option name="ALLOW_TRAILING_COMMA" value="true" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="CMake">

2
.idea/compiler.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
<bytecodeTargetLevel target="11" />
</component>
</project>

View File

@@ -1,14 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="admin">
<words>
<w>chucker</w>
<w>desu</w>
<w>failsafe</w>
<w>koin</w>
<w>kotatsu</w>
<w>manga</w>
<w>upsert</w>
<w>webtoon</w>
</words>
</dictionary>
</component>

6
.idea/gradle.xml generated
View File

@@ -4,18 +4,16 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8" />
<option name="gradleJvm" value="Android Studio default JDK" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>

View File

@@ -1,7 +1,11 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="BooleanLiteralArgument" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="BooleanLiteralArgument" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="Destructure" enabled="true" level="INFO" enabled_by_default="true" />
<inspection_tool class="KeySetIterationMayUseEntrySet" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ReplaceCollectionCountWithSize" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="TrailingComma" enabled="true" level="INFORMATION" enabled_by_default="true" />
<inspection_tool class="ZeroLengthArrayInitialization" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@@ -31,5 +31,15 @@
<option name="name" value="maven2" />
<option name="url" value="https://dl.bintray.com/kotlin/kotlin-eap" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://maven.pkg.github.com/nv95/kotatsu-parsers" />
</remote-repository>
</component>
</project>

7
.idea/ktlint.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KtlintProjectConfiguration">
<androidMode>true</androidMode>
<treatAsErrors>false</treatAsErrors>
</component>
</project>

9
.idea/misc.xml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -1,15 +1,11 @@
language: android
dist: trusty
jdk:
- oraclejdk8
android:
components:
- android-30
- build-tools-30.0.3
- platform-tools-30.0.5
- tools
- platform-tools-29.0.6
- build-tools-29.0.3
- android-29
licenses:
- android-sdk-preview-license-.+
- android-sdk-license-.+
- google-gdk-license-.+
before_install:
- yes | sdkmanager "platforms;android-30"
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug

View File

@@ -2,33 +2,48 @@
Kotatsu is a free and open source manga reader for Android.
![Android 5.0](https://img.shields.io/badge/android-5.0+-brightgreen) ![Kotlin](https://img.shields.io/github/languages/top/nv95/Kotatsu) [![Build Status](https://travis-ci.org/nv95/Kotatsu.svg?branch=master)](https://travis-ci.org/nv95/Kotatsu) ![License](https://img.shields.io/github/license/nv95/Kotatsu) [![4pda](https://img.shields.io/badge/discuss-4pda-2982CC)](http://4pda.ru/forum/index.php?showtopic=697669)
![Android 5.0](https://img.shields.io/badge/android-5.0+-brightgreen) ![Kotlin](https://img.shields.io/github/languages/top/nv95/Kotatsu) [![Build Status](https://travis-ci.org/nv95/Kotatsu.svg?branch=master)](https://travis-ci.org/nv95/Kotatsu) ![License](https://img.shields.io/github/license/nv95/Kotatsu) [![weblate](https://hosted.weblate.org/widgets/kotatsu/-/strings/svg-badge.svg)](https://hosted.weblate.org/engage/kotatsu/) [![4pda](https://img.shields.io/badge/discuss-4pda-2982CC)](http://4pda.ru/forum/index.php?showtopic=697669) [![Discord](https://img.shields.io/discord/898363402467045416?color=5865f2&label=discord)](https://discord.gg/NNJ5RgVBC5)
### Download
Latest release: [get here](https://github.com/nv95/Kotatsu/releases/latest)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/org.koitharu.kotatsu)
Legacy build (Android 4.1+): [available here](https://github.com/nv95/Kotatsu/releases/tag/v0.4-legacy)
Download APK from Github Releases:
- [Latest release](https://github.com/nv95/Kotatsu/releases/latest)
- [Legacy build](https://github.com/nv95/Kotatsu/releases/tag/v0.4-legacy) (with Android 4.1+ support)
### Main Features
* Online manga catalogues
* Search manga by name and genre
* Reading history
* Favourites with custom categories
* Saving manga and reading it offline
* Tablet-optimized modern UI
* Reading third-party comics from CBZ
* Favourites organized by user-defined categories
* Downloading manga and reading it offline. Third-party CBZ archives also supported
* Tablet-optimized material design UI
* Standard and Webtoon-optimized reader
* Notifications about new chapters
* Updates feed
* Global search
* Notifications about new chapters with updates feed
* Available in multiple languages
* Password protect access to the app
### Screenshots
| ![Screenshot_20200226-210337](https://user-images.githubusercontent.com/8948226/80315102-3478db00-87fe-11ea-9ce8-4bbd1c254b2b.png) | ![Screenshot_20200226-210310](https://user-images.githubusercontent.com/8948226/80315110-3f337000-87fe-11ea-95df-944c196b6667.png) | ![Screenshot_20200226-210232](https://user-images.githubusercontent.com/8948226/80315121-49ee0500-87fe-11ea-8d9b-537a041bbf2f.png) |
|---|---|---|
| ![Screenshot_20200226-210405](https://user-images.githubusercontent.com/8948226/80315130-55d9c700-87fe-11ea-8350-2c8452906eb7.png) | ![Screenshot_20200226-210151](https://user-images.githubusercontent.com/8948226/80315135-612cf280-87fe-11ea-984c-aa18567d5bbc.png) | ![Screenshot_20200226-210223](https://user-images.githubusercontent.com/8948226/80315146-6be78780-87fe-11ea-8439-ca1ca578172b.png) |
| ![Screenshot_20200226-210337](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/1.png) | ![](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/2.png) | ![Screenshot_20200226-210232](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/3.png) |
|-----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| ![Screenshot_20200226-210405](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/4.png) | ![Screenshot_20200226-210151](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/5.png) | ![Screenshot_20200226-210223](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/phoneScreenshots/6.png) |
| ![](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/tenInchScreenshots/1.png) | ![](https://github.com/nv95/Kotatsu/raw/devel/metadata/en-US/images/tenInchScreenshots/2.png) |
|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
### Localization
<a href="https://hosted.weblate.org/engage/kotatsu/">
<img src="https://hosted.weblate.org/widgets/kotatsu/-/287x66-white.png" alt="Translation status" />
</a>
Kotatsu is localized in a number of different languages, if you would like to help improve these or add new languages, please head over to the Weblate <a href="https://hosted.weblate.org/engage/kotatsu/">project page</a>
### License
[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html)

View File

@@ -1,22 +1,23 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'kotlin-parcelize'
}
def gitCommits = 'git rev-list --count HEAD'.execute([], rootDir).text.trim().toInteger()
android {
compileSdkVersion 29
buildToolsVersion '29.0.3'
compileSdkVersion 32
buildToolsVersion '32.0.0'
namespace 'org.koitharu.kotatsu'
defaultConfig {
applicationId 'org.koitharu.kotatsu'
minSdkVersion 21
targetSdkVersion 29
versionCode gitCommits
versionName '0.5'
targetSdkVersion 32
versionCode 406
versionName '3.2.2'
generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
kapt {
arguments {
@@ -24,14 +25,6 @@ android {
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
}
buildTypes {
debug {
applicationIdSuffix = '.debug'
@@ -43,61 +36,84 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
disable 'MissingTranslation'
buildFeatures {
viewBinding true
}
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += [
'-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi',
'-opt-in=kotlinx.coroutines.FlowPreview',
'-opt-in=kotlin.contracts.ExperimentalContracts',
]
}
lint {
abortOnError false
disable 'MissingTranslation', 'PrivateResource'
}
testOptions {
unitTests.includeAndroidResources = true
unitTests.returnDefaultValues = true
unitTests.returnDefaultValues = false
}
}
androidExtensions {
experimental = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7'
implementation('com.github.nv95:kotatsu-parsers:b495e5e457') {
exclude group: 'org.json', module: 'json'
}
implementation 'androidx.core:core-ktx:1.5.0-alpha01'
implementation 'androidx.activity:activity-ktx:1.2.0-alpha06'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha06'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha05'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta8'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.activity:activity-ktx:1.4.0'
implementation 'androidx.fragment:fragment-ktx:1.4.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-service:2.4.1'
implementation 'androidx.lifecycle:lifecycle-process:2.4.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha04'
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.work:work-runtime-ktx:2.4.0-rc01'
implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
implementation 'com.google.android.material:material:1.6.0'
//noinspection LifecycleAnnotationProcessorWithJava8
kapt 'androidx.lifecycle:lifecycle-compiler:2.3.0-alpha05'
kapt 'androidx.lifecycle:lifecycle-compiler:2.4.1'
implementation 'androidx.room:room-runtime:2.2.5'
implementation 'androidx.room:room-ktx:2.2.5'
kapt 'androidx.room:room-compiler:2.2.5'
implementation 'androidx.room:room-runtime:2.4.2'
implementation 'androidx.room:room-ktx:2.4.2'
kapt 'androidx.room:room-compiler:2.4.2'
implementation 'com.github.moxy-community:moxy:2.1.2'
implementation 'com.github.moxy-community:moxy-androidx:2.1.2'
implementation 'com.github.moxy-community:moxy-material:2.1.2'
implementation 'com.github.moxy-community:moxy-ktx:2.1.2'
kapt 'com.github.moxy-community:moxy-compiler:2.1.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'com.squareup.okio:okio:3.0.0'
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
implementation 'com.squareup.okio:okio:2.7.0'
implementation 'org.jsoup:jsoup:1.13.1'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2'
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation 'org.koin:koin-android:2.1.5'
implementation 'io.coil-kt:coil:0.11.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
implementation 'com.tomclaw.cache:cache:1.0'
implementation 'io.insert-koin:koin-android:3.1.6'
implementation 'io.coil-kt:coil-base:1.4.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.solkin:disk-lru-cache:1.4'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
debugImplementation 'com.github.ChuckerTeam.Chucker:library:3.2.0'
releaseImplementation 'com.github.ChuckerTeam.Chucker:library-no-op:3.2.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
testImplementation 'junit:junit:4.13'
testImplementation 'org.json:json:20200518'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1'
testImplementation 'io.insert-koin:koin-test-junit4:3.1.5'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test:core-ktx:1.4.0'
androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3'
androidTestImplementation 'androidx.room:room-testing:2.4.2'
}

View File

@@ -1,3 +1,4 @@
-optimizationpasses 8
-dontobfuscate
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
public static void checkExpressionValueIsNotNull(...);
@@ -5,9 +6,8 @@
public static void checkReturnedValueIsNotNull(...);
public static void checkFieldIsNotNull(...);
public static void checkParameterIsNotNull(...);
public static void checkNotNullParameter(...);
}
-keep public class ** extends org.koitharu.kotatsu.base.ui.BaseFragment
-keep class org.koitharu.kotatsu.core.db.entity.* { *; }
-keepclassmembers public class * extends org.koitharu.kotatsu.core.parser.MangaRepository {
public <init>(...);
}
-dontwarn okhttp3.internal.platform.ConscryptPlatform

View File

@@ -0,0 +1,55 @@
package org.koitharu.kotatsu.core.db
import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.koitharu.kotatsu.core.db.migrations.*
import java.io.IOException
@RunWith(AndroidJUnit4::class)
class MangaDatabaseTest {
@get:Rule
val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
MangaDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)
@Test
@Throws(IOException::class)
fun migrateAll() {
helper.createDatabase(TEST_DB, 1).apply {
// TODO execSQL("")
close()
}
for (migration in migrations) {
helper.runMigrationsAndValidate(
TEST_DB,
migration.endVersion,
true,
migration
)
}
}
private companion object {
const val TEST_DB = "test-db"
val migrations = arrayOf(
Migration1To2(),
Migration2To3(),
Migration3To4(),
Migration4To5(),
Migration5To6(),
Migration6To7(),
Migration7To8(),
)
}
}

View File

@@ -0,0 +1,40 @@
package org.koitharu.kotatsu.core.parser
import java.util.*
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.*
/**
* This parser is just for parser development, it should not be used in releases
*/
class DummyParser(override val context: MangaLoaderContext) : MangaParser(MangaSource.DUMMY) {
override val configKeyDomain: ConfigKey.Domain
get() = ConfigKey.Domain("", null)
override val sortOrders: Set<SortOrder>
get() = EnumSet.allOf(SortOrder::class.java)
override suspend fun getDetails(manga: Manga): Manga {
TODO("Not yet implemented")
}
override suspend fun getList(
offset: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder?
): List<Manga> {
TODO("Not yet implemented")
}
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
TODO("Not yet implemented")
}
override suspend fun getTags(): Set<MangaTag> {
TODO("Not yet implemented")
}
}

View File

@@ -0,0 +1,14 @@
package org.koitharu.kotatsu.core.parser
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParser
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.newParser
fun MangaParser(source: MangaSource, loaderContext: MangaLoaderContext): MangaParser {
return if (source == MangaSource.DUMMY) {
DummyParser(loaderContext)
} else {
source.newParser(loaderContext)
}
}

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#E6000A">
<group android:scaleX="0.40188664"
android:scaleY="0.40188664"
android:translateX="32.90095"
android:translateY="18.7272">
<group android:translateY="139.39206">
<path android:pathData="M83.796875,-0L105.6875,-0L60.765625,-55.828125L103.09375,-101L82.078125,-101L32.25,-49.1875L32.25,-101L13.53125,-101L13.53125,-0L32.25,-0L32.25,-25.8125L48.234375,-42.265625L83.796875,-0Z"
android:fillColor="#E6000A"/>
</group>
</group>
</vector>

View File

@@ -4,9 +4,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_list_mode"
android:orderInCategory="20"
android:title="@string/list_mode"
android:id="@id/action_leaks"
android:title="@string/leak_canary_display_activity_label"
app:showAsAction="never" />
</menu>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<bool name="leak_canary_add_launcher_icon" tools:node="replace">false</bool>
</resources>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name" translatable="false">Kotatsu Dev</string>
</resources>

View File

@@ -1,90 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.koitharu.kotatsu">
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name="org.koitharu.kotatsu.KotatsuApp"
android:allowBackup="true"
android:fullBackupContent="@xml/backup_descriptor"
android:backupAgent="org.koitharu.kotatsu.settings.backup.AppBackupAgent"
android:dataExtractionRules="@xml/backup_rules"
android:fullBackupContent="@xml/backup_content"
android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.Kotatsu"
tools:ignore="UnusedAttribute">
<activity android:name=".ui.list.MainActivity">
<activity
android:name="org.koitharu.kotatsu.main.ui.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".ui.search.SearchActivity" />
android:value="org.koitharu.kotatsu.ui.search.SearchActivity" />
</activity>
<activity android:name=".ui.details.MangaDetailsActivity">
<activity
android:name="org.koitharu.kotatsu.details.ui.DetailsActivity"
android:exported="true">
<intent-filter>
<action android:name="${applicationId}.action.VIEW_MANGA" />
</intent-filter>
</activity>
<activity android:name=".ui.reader.ReaderActivity" />
<activity
android:name=".ui.search.SearchActivity"
android:label="@string/search" />
<activity
android:name=".ui.settings.SettingsActivity"
android:label="@string/settings" />
<activity
android:name=".ui.reader.SimpleSettingsActivity"
android:label="@string/settings">
android:name="org.koitharu.kotatsu.reader.ui.ReaderActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="${applicationId}.action.READ_MANGA" />
</intent-filter>
</activity>
<activity android:name=".ui.browser.BrowserActivity" />
<activity
android:name=".ui.utils.CrashActivity"
android:name="org.koitharu.kotatsu.search.ui.SearchActivity"
android:label="@string/search" />
<activity android:name="org.koitharu.kotatsu.search.ui.MangaListActivity"
android:label="@string/search_manga" />
<activity
android:name="org.koitharu.kotatsu.settings.SettingsActivity"
android:label="@string/settings" />
<activity
android:name="org.koitharu.kotatsu.browser.BrowserActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="org.koitharu.kotatsu.core.ui.CrashActivity"
android:label="@string/error_occurred"
android:theme="@android:style/Theme.DeviceDefault.Dialog"
android:theme="@android:style/Theme.DeviceDefault"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name="org.koitharu.kotatsu.ui.list.favourites.categories.CategoriesActivity"
android:name="org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity"
android:label="@string/favourites_categories"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".ui.widget.shelf.ShelfConfigActivity"
android:name="org.koitharu.kotatsu.widget.shelf.ShelfConfigActivity"
android:exported="true"
android:label="@string/manga_shelf">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity android:name=".ui.search.global.GlobalSearchActivity"
<activity
android:name="org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity"
android:label="@string/search" />
<activity
android:name="org.koitharu.kotatsu.main.ui.protect.ProtectActivity"
android:noHistory="true"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="org.koitharu.kotatsu.settings.protect.ProtectSetupActivity"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="org.koitharu.kotatsu.download.ui.DownloadsActivity"
android:launchMode="singleTop"
android:label="@string/downloads" />
<activity android:name="org.koitharu.kotatsu.image.ui.ImageActivity"/>
<service
android:name=".ui.download.DownloadService"
android:name="org.koitharu.kotatsu.download.ui.service.DownloadService"
android:foregroundServiceType="dataSync" />
<service android:name=".ui.settings.AppUpdateService" />
<service android:name="org.koitharu.kotatsu.local.ui.LocalChaptersRemoveService" />
<service
android:name=".ui.widget.shelf.ShelfWidgetService"
android:name="org.koitharu.kotatsu.widget.shelf.ShelfWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<service
android:name=".ui.widget.recent.RecentWidgetService"
android:name="org.koitharu.kotatsu.widget.recent.RecentWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<provider
android:name=".ui.search.MangaSuggestionsProvider"
android:name="org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider"
android:authorities="${applicationId}.MangaSuggestionsProvider"
android:exported="false" />
<provider
@@ -98,7 +125,8 @@
</provider>
<receiver
android:name=".ui.widget.shelf.ShelfWidgetProvider"
android:name="org.koitharu.kotatsu.widget.shelf.ShelfWidgetProvider"
android:exported="true"
android:label="@string/manga_shelf">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@@ -108,7 +136,8 @@
android:resource="@xml/widget_shelf" />
</receiver>
<receiver
android:name=".ui.widget.recent.RecentWidgetProvider"
android:name="org.koitharu.kotatsu.widget.recent.RecentWidgetProvider"
android:exported="true"
android:label="@string/recent_manga">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@@ -118,6 +147,13 @@
android:resource="@xml/widget_recent" />
</receiver>
<meta-data
android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="false" />
<meta-data
android:name="android.webkit.WebView.MetricsOptOut"
android:value="true" />
</application>
</manifest>

View File

@@ -3,141 +3,97 @@ package org.koitharu.kotatsu
import android.app.Application
import android.os.StrictMode
import androidx.appcompat.app.AppCompatDelegate
import androidx.room.Room
import coil.Coil
import coil.ComponentRegistry
import coil.ImageLoaderBuilder
import coil.util.CoilUtils
import com.chuckerteam.chucker.api.ChuckerCollector
import com.chuckerteam.chucker.api.ChuckerInterceptor
import okhttp3.OkHttpClient
import androidx.fragment.app.strictmode.FragmentStrictMode
import org.koin.android.ext.android.get
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin
import org.koin.dsl.module
import org.koitharu.kotatsu.core.db.DatabasePrePopulateCallback
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.migrations.*
import org.koitharu.kotatsu.core.local.CbzFetcher
import org.koitharu.kotatsu.core.local.PagesCache
import org.koitharu.kotatsu.core.local.cookies.PersistentCookieJar
import org.koitharu.kotatsu.core.local.cookies.cache.SetCookieCache
import org.koitharu.kotatsu.core.local.cookies.persistence.SharedPrefsCookiePersistor
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
import org.koitharu.kotatsu.core.parser.UserAgentInterceptor
import org.koitharu.kotatsu.core.db.databaseModule
import org.koitharu.kotatsu.core.github.githubModule
import org.koitharu.kotatsu.core.network.networkModule
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.domain.MangaLoaderContext
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.ui.utils.AppCrashHandler
import org.koitharu.kotatsu.ui.widget.WidgetUpdater
import org.koitharu.kotatsu.utils.CacheUtils
import java.util.concurrent.TimeUnit
import org.koitharu.kotatsu.core.ui.AppCrashHandler
import org.koitharu.kotatsu.core.ui.uiModule
import org.koitharu.kotatsu.details.detailsModule
import org.koitharu.kotatsu.favourites.favouritesModule
import org.koitharu.kotatsu.history.historyModule
import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
import org.koitharu.kotatsu.local.localModule
import org.koitharu.kotatsu.main.mainModule
import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.reader.readerModule
import org.koitharu.kotatsu.remotelist.remoteListModule
import org.koitharu.kotatsu.search.searchModule
import org.koitharu.kotatsu.settings.settingsModule
import org.koitharu.kotatsu.suggestions.suggestionsModule
import org.koitharu.kotatsu.tracker.trackerModule
import org.koitharu.kotatsu.widget.WidgetUpdater
import org.koitharu.kotatsu.widget.appWidgetModule
class KotatsuApp : Application() {
private val cookieJar by lazy {
PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(applicationContext))
}
private val chuckerCollector by lazy(LazyThreadSafetyMode.NONE) {
ChuckerCollector(applicationContext)
}
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
enableStrictMode()
}
initKoin()
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
AppCompatDelegate.setDefaultNightMode(get<AppSettings>().theme)
registerActivityLifecycleCallbacks(get<AppProtectHelper>())
val widgetUpdater = WidgetUpdater(applicationContext)
widgetUpdater.subscribeToFavourites(get())
widgetUpdater.subscribeToHistory(get())
}
private fun initKoin() {
startKoin {
androidContext(this@KotatsuApp)
modules(
networkModule,
databaseModule,
githubModule,
uiModule,
mainModule,
searchModule,
localModule,
favouritesModule,
historyModule,
remoteListModule,
detailsModule,
trackerModule,
settingsModule,
readerModule,
appWidgetModule,
suggestionsModule,
)
}
}
private fun enableStrictMode() {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build())
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
.build()
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectAll()
.setClassInstanceLimit(LocalMangaRepository::class.java, 1)
.setClassInstanceLimit(PagesCache::class.java, 1)
.setClassInstanceLimit(MangaLoaderContext::class.java, 1)
.penaltyLog()
.build())
}
initKoin()
initCoil()
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
if (BuildConfig.DEBUG) {
initErrorHandler()
}
AppCompatDelegate.setDefaultNightMode(AppSettings(this).theme)
val widgetUpdater = WidgetUpdater(applicationContext)
FavouritesRepository.subscribe(widgetUpdater)
HistoryRepository.subscribe(widgetUpdater)
}
private fun initKoin() {
startKoin {
androidLogger()
androidContext(applicationContext)
modules(
module {
factory {
okHttp()
.cache(CacheUtils.createHttpCache(applicationContext))
.build()
}
single {
mangaDb().build()
}
single {
MangaLoaderContext()
}
single {
AppSettings(applicationContext)
}
single {
PagesCache(applicationContext)
}
}
)
}
}
private fun initCoil() {
Coil.setImageLoader(
ImageLoaderBuilder(applicationContext)
.okHttpClient(
okHttp()
.cache(CoilUtils.createDefaultCache(applicationContext))
.build()
).componentRegistry(
ComponentRegistry.Builder()
.add(CbzFetcher())
.build()
)
.build()
)
FragmentStrictMode.defaultPolicy = FragmentStrictMode.Policy.Builder()
.penaltyDeath()
.detectFragmentReuse()
.detectWrongFragmentContainer()
.detectRetainInstanceUsage()
.detectSetUserVisibleHint()
.detectFragmentTagUsage()
.build()
}
private fun initErrorHandler() {
val exceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { t, e ->
chuckerCollector.onError("CRASH", e)
exceptionHandler?.uncaughtException(t, e)
}
}
private fun okHttp() = OkHttpClient.Builder().apply {
connectTimeout(20, TimeUnit.SECONDS)
readTimeout(60, TimeUnit.SECONDS)
writeTimeout(20, TimeUnit.SECONDS)
cookieJar(cookieJar)
addInterceptor(UserAgentInterceptor)
if (BuildConfig.DEBUG) {
addInterceptor(ChuckerInterceptor(applicationContext, collector = chuckerCollector))
}
}
private fun mangaDb() = Room.databaseBuilder(
applicationContext,
MangaDatabase::class.java,
"kotatsu-db"
).addMigrations(Migration1To2, Migration2To3, Migration3To4, Migration4To5, Migration5To6)
.addCallback(DatabasePrePopulateCallback(resources))
}

View File

@@ -0,0 +1,52 @@
package org.koitharu.kotatsu.base.domain
import androidx.room.withTransaction
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.*
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag
class MangaDataRepository(private val db: MangaDatabase) {
suspend fun savePreferences(manga: Manga, mode: ReaderMode) {
val tags = manga.tags.toEntities()
db.withTransaction {
db.tagsDao.upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags)
db.preferencesDao.upsert(
MangaPrefsEntity(
mangaId = manga.id,
mode = mode.id
)
)
}
}
suspend fun getReaderMode(mangaId: Long): ReaderMode? {
return db.preferencesDao.find(mangaId)?.let { ReaderMode.valueOf(it.mode) }
}
suspend fun findMangaById(mangaId: Long): Manga? {
return db.mangaDao.find(mangaId)?.toManga()
}
suspend fun resolveIntent(intent: MangaIntent): Manga? = when {
intent.manga != null -> intent.manga
intent.mangaId != 0L -> findMangaById(intent.mangaId)
else -> null // TODO resolve uri
}
suspend fun storeManga(manga: Manga) {
val tags = manga.tags.toEntities()
db.withTransaction {
db.tagsDao.upsert(tags)
db.mangaDao.upsert(manga.toEntity(), tags)
}
}
suspend fun findTags(source: MangaSource): Set<MangaTag> {
return db.tagsDao.findTags(source.name).toMangaTags()
}
}

View File

@@ -0,0 +1,34 @@
package org.koitharu.kotatsu.base.domain
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.parsers.model.Manga
class MangaIntent private constructor(
val manga: Manga?,
val mangaId: Long,
val uri: Uri?,
) {
constructor(intent: Intent?) : this(
manga = intent?.getParcelableExtra<ParcelableManga>(KEY_MANGA)?.manga,
mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE,
uri = intent?.data
)
constructor(args: Bundle?) : this(
manga = args?.getParcelable<ParcelableManga>(KEY_MANGA)?.manga,
mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE,
uri = null
)
companion object {
const val ID_NONE = 0L
const val KEY_MANGA = "manga"
const val KEY_ID = "id"
}
}

View File

@@ -0,0 +1,81 @@
package org.koitharu.kotatsu.base.domain
import android.graphics.BitmapFactory
import android.net.Uri
import android.util.Size
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.util.await
import org.koitharu.kotatsu.parsers.util.medianOrNull
import java.io.File
import java.io.InputStream
import java.util.zip.ZipFile
object MangaUtils : KoinComponent {
/**
* Automatic determine type of manga by page size
* @return ReaderMode.WEBTOON if page is wide
*/
suspend fun determineMangaIsWebtoon(pages: List<MangaPage>): Boolean? {
try {
val page = pages.medianOrNull() ?: return null
val url = MangaRepository(page.source).getPageUrl(page)
val uri = Uri.parse(url)
val size = if (uri.scheme == "cbz") {
runInterruptible(Dispatchers.IO) {
val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment)
zip.getInputStream(entry).use {
getBitmapSize(it)
}
}
} else {
val request = Request.Builder()
.url(url)
.get()
.header(CommonHeaders.REFERER, page.referer)
.cacheControl(CommonHeaders.CACHE_CONTROL_DISABLED)
.build()
get<OkHttpClient>().newCall(request).await().use {
runInterruptible(Dispatchers.IO) {
getBitmapSize(it.body?.byteStream())
}
}
}
return size.width * 2 < size.height
} catch (e: Exception) {
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
return null
}
}
suspend fun getImageMimeType(file: File): String? = runInterruptible(Dispatchers.IO) {
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeFile(file.path, options)?.recycle()
options.outMimeType
}
private fun getBitmapSize(input: InputStream?): Size {
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeStream(input, null, options)?.recycle()
val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth
check(imageHeight > 0 && imageWidth > 0)
return Size(imageWidth, imageHeight)
}
}

View File

@@ -0,0 +1,45 @@
package org.koitharu.kotatsu.base.ui
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.fragment.app.DialogFragment
import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
abstract class AlertDialogFragment<B : ViewBinding> : DialogFragment() {
private var viewBinding: B? = null
protected val binding: B
get() = checkNotNull(viewBinding)
final override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val binding = onInflateView(layoutInflater, null)
viewBinding = binding
return MaterialAlertDialogBuilder(requireContext(), theme)
.setView(binding.root)
.also(::onBuildDialog)
.create()
}
final override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
) = viewBinding?.root
@CallSuper
override fun onDestroyView() {
viewBinding = null
super.onDestroyView()
}
open fun onBuildDialog(builder: MaterialAlertDialogBuilder) = Unit
protected fun bindingOrNull(): B? = viewBinding
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B
}

View File

@@ -0,0 +1,127 @@
package org.koitharu.kotatsu.base.ui
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.ActionBarContextView
import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.viewbinding.ViewBinding
import org.koin.android.ext.android.get
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.util.ActionModeDelegate
import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.prefs.AppSettings
abstract class BaseActivity<B : ViewBinding> :
AppCompatActivity(),
WindowInsetsDelegate.WindowInsetsListener {
protected lateinit var binding: B
private set
@Suppress("LeakingThis")
protected val exceptionResolver = ExceptionResolver(this)
@Suppress("LeakingThis")
protected val insetsDelegate = WindowInsetsDelegate(this)
val actionModeDelegate = ActionModeDelegate()
override fun onCreate(savedInstanceState: Bundle?) {
val settings = get<AppSettings>()
when {
settings.isAmoledTheme -> setTheme(R.style.ThemeOverlay_Kotatsu_AMOLED)
settings.isDynamicTheme -> setTheme(R.style.Theme_Kotatsu_Monet)
}
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
insetsDelegate.handleImeInsets = true
}
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(layoutResID: Int) {
super.setContentView(layoutResID)
setupToolbar()
}
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(view: View?) {
super.setContentView(view)
setupToolbar()
}
protected fun setContentView(binding: B) {
this.binding = binding
super.setContentView(binding.root)
val toolbar = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)
toolbar?.let(this::setSupportActionBar)
insetsDelegate.onViewCreated(binding.root)
}
override fun onOptionsItemSelected(item: MenuItem) = if (item.itemId == android.R.id.home) {
onBackPressed()
true
} else super.onOptionsItemSelected(item)
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (BuildConfig.DEBUG && keyCode == KeyEvent.KEYCODE_VOLUME_UP) { // TODO remove
ActivityCompat.recreate(this)
return true
}
return super.onKeyDown(keyCode, event)
}
private fun setupToolbar() {
(findViewById<View>(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar)
}
protected fun isDarkAmoledTheme(): Boolean {
val uiMode = resources.configuration.uiMode
val isNight = uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
return isNight && get<AppSettings>().isAmoledTheme
}
@CallSuper
override fun onSupportActionModeStarted(mode: ActionMode) {
super.onSupportActionModeStarted(mode)
actionModeDelegate.onSupportActionModeStarted(mode)
val insets = ViewCompat.getRootWindowInsets(binding.root)
?.getInsets(WindowInsetsCompat.Type.systemBars()) ?: return
val view = findViewById<ActionBarContextView?>(androidx.appcompat.R.id.action_mode_bar)
view?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
@CallSuper
override fun onSupportActionModeFinished(mode: ActionMode) {
super.onSupportActionModeFinished(mode)
actionModeDelegate.onSupportActionModeFinished(mode)
}
override fun onBackPressed() {
if ( // https://issuetracker.google.com/issues/139738913
Build.VERSION.SDK_INT == Build.VERSION_CODES.Q &&
isTaskRoot &&
supportFragmentManager.backStackEntryCount == 0
) {
finishAfterTransition()
} else {
super.onBackPressed()
}
}
}

View File

@@ -0,0 +1,66 @@
package org.koitharu.kotatsu.base.ui
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import androidx.appcompat.app.AppCompatDialog
import androidx.core.view.updateLayoutParams
import androidx.viewbinding.ViewBinding
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.dialog.AppBottomSheetDialog
import com.google.android.material.R as materialR
abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
private var viewBinding: B? = null
protected val binding: B
get() = checkNotNull(viewBinding)
protected val behavior: BottomSheetBehavior<*>?
get() = (dialog as? BottomSheetDialog)?.behavior
final override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = onInflateView(inflater, container)
viewBinding = binding
return binding.root
}
override fun onDestroyView() {
viewBinding = null
super.onDestroyView()
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return if (resources.getBoolean(R.bool.is_tablet)) {
AppCompatDialog(context, R.style.Theme_Kotatsu_Dialog)
} else {
AppBottomSheetDialog(requireContext(), theme)
}
}
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B
protected fun setExpanded(isExpanded: Boolean, isLocked: Boolean) {
val b = behavior ?: return
if (isExpanded) {
b.state = BottomSheetBehavior.STATE_EXPANDED
}
b.isFitToContents = !isExpanded
val rootView = dialog?.findViewById<View>(materialR.id.design_bottom_sheet)
rootView?.updateLayoutParams {
height = if (isExpanded) LayoutParams.MATCH_PARENT else LayoutParams.WRAP_CONTENT
}
b.isDraggable = !isLocked
}
}

View File

@@ -0,0 +1,55 @@
package org.koitharu.kotatsu.base.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import org.koitharu.kotatsu.base.ui.util.ActionModeDelegate
import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
abstract class BaseFragment<B : ViewBinding> :
Fragment(),
WindowInsetsDelegate.WindowInsetsListener {
private var viewBinding: B? = null
protected val binding: B
get() = checkNotNull(viewBinding)
@Suppress("LeakingThis")
protected val exceptionResolver = ExceptionResolver(this)
@Suppress("LeakingThis")
protected val insetsDelegate = WindowInsetsDelegate(this)
protected val actionModeDelegate: ActionModeDelegate
get() = (requireActivity() as BaseActivity<*>).actionModeDelegate
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = onInflateView(inflater, container)
viewBinding = binding
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
insetsDelegate.onViewCreated(view)
}
override fun onDestroyView() {
viewBinding = null
insetsDelegate.onDestroyView()
super.onDestroyView()
}
protected fun bindingOrNull() = viewBinding
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B
}

View File

@@ -0,0 +1,53 @@
package org.koitharu.kotatsu.base.ui
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import androidx.viewbinding.ViewBinding
private const val SYSTEM_UI_FLAGS_SHOWN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
private const val SYSTEM_UI_FLAGS_HIDDEN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
abstract class BaseFullscreenActivity<B : ViewBinding> : BaseActivity<B>(),
View.OnSystemUiVisibilityChangeListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
with(window) {
statusBarColor = Color.TRANSPARENT
navigationBarColor = Color.TRANSPARENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
decorView.setOnSystemUiVisibilityChangeListener(this@BaseFullscreenActivity)
}
showSystemUI()
}
@Deprecated("Deprecated in Java")
final override fun onSystemUiVisibilityChange(visibility: Int) {
onSystemUiVisibilityChanged(visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0)
}
// TODO WindowInsetsControllerCompat works incorrect
protected fun hideSystemUI() {
window.decorView.systemUiVisibility = SYSTEM_UI_FLAGS_HIDDEN
}
protected fun showSystemUI() {
window.decorView.systemUiVisibility = SYSTEM_UI_FLAGS_SHOWN
}
protected open fun onSystemUiVisibilityChanged(isVisible: Boolean) = Unit
}

View File

@@ -0,0 +1,62 @@
package org.koitharu.kotatsu.base.ui
import android.os.Bundle
import android.view.View
import androidx.annotation.CallSuper
import androidx.annotation.StringRes
import androidx.core.graphics.Insets
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceFragmentCompat
import androidx.recyclerview.widget.RecyclerView
import org.koin.android.ext.android.inject
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.settings.SettingsActivity
import org.koitharu.kotatsu.settings.SettingsHeadersFragment
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
PreferenceFragmentCompat(),
WindowInsetsDelegate.WindowInsetsListener,
RecyclerViewOwner {
protected val settings by inject<AppSettings>(mode = LazyThreadSafetyMode.NONE)
@Suppress("LeakingThis")
protected val insetsDelegate = WindowInsetsDelegate(this)
override val recyclerView: RecyclerView
get() = listView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.clipToPadding = false
insetsDelegate.onViewCreated(view)
}
override fun onDestroyView() {
insetsDelegate.onDestroyView()
super.onDestroyView()
}
override fun onResume() {
super.onResume()
if (titleId != 0) {
setTitle(getString(titleId))
}
}
@CallSuper
override fun onWindowInsetsChanged(insets: Insets) {
listView.updatePadding(
bottom = insets.bottom
)
}
@Suppress("UsePropertyAccessSyntax")
protected fun setTitle(title: CharSequence) {
(parentFragment as? SettingsHeadersFragment)?.setTitle(title)
?: activity?.setTitle(title)
}
}

View File

@@ -0,0 +1,5 @@
package org.koitharu.kotatsu.base.ui
import androidx.lifecycle.LifecycleService
abstract class BaseService : LifecycleService()

View File

@@ -0,0 +1,44 @@
package org.koitharu.kotatsu.base.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.*
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.base.ui.util.CountedBooleanLiveData
import org.koitharu.kotatsu.utils.SingleLiveEvent
abstract class BaseViewModel : ViewModel() {
val onError = SingleLiveEvent<Throwable>()
val isLoading = CountedBooleanLiveData()
protected fun launchJob(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job = viewModelScope.launch(context + createErrorHandler(), start, block)
protected fun launchLoadingJob(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job = viewModelScope.launch(context + createErrorHandler(), start) {
isLoading.postValue(true)
try {
block()
} finally {
isLoading.postValue(false)
}
}
private fun createErrorHandler() = CoroutineExceptionHandler { _, throwable ->
if (BuildConfig.DEBUG) {
throwable.printStackTrace()
}
if (throwable !is CancellationException) {
onError.postCall(throwable)
}
}
}

View File

@@ -0,0 +1,37 @@
package org.koitharu.kotatsu.base.ui
import android.app.Service
import android.content.Intent
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
abstract class CoroutineIntentService : BaseService() {
private val mutex = Mutex()
protected open val dispatcher: CoroutineDispatcher = Dispatchers.Default
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
launchCoroutine(intent, startId)
return Service.START_REDELIVER_INTENT
}
private fun launchCoroutine(intent: Intent?, startId: Int) = lifecycleScope.launch {
mutex.withLock {
try {
withContext(dispatcher) {
processIntent(intent)
}
} finally {
stopSelf(startId)
}
}
}
protected abstract suspend fun processIntent(intent: Intent?)
}

View File

@@ -0,0 +1,29 @@
package org.koitharu.kotatsu.base.ui.dialog
import android.content.Context
import android.graphics.Color
import android.view.View
import com.google.android.material.bottomsheet.BottomSheetDialog
class AppBottomSheetDialog(context: Context, theme: Int) : BottomSheetDialog(context, theme) {
/**
* https://github.com/material-components/material-components-android/issues/2582
*/
@Suppress("DEPRECATION")
override fun onAttachedToWindow() {
val window = window
val initialSystemUiVisibility = window?.decorView?.systemUiVisibility ?: 0
super.onAttachedToWindow()
if (window != null) {
// If the navigation bar is translucent at all, the BottomSheet should be edge to edge
val drawEdgeToEdge = edgeToEdgeEnabled && Color.alpha(window.navigationBarColor) < 0xFF
if (drawEdgeToEdge) {
// Copied from super.onAttachedToWindow:
val edgeToEdgeFlags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
// Fix super-class's window flag bug by respecting the intial system UI visibility:
window.decorView.systemUiVisibility = edgeToEdgeFlags or initialSystemUiVisibility
}
}
}
}

View File

@@ -1,15 +1,13 @@
package org.koitharu.kotatsu.ui.common.dialog
package org.koitharu.kotatsu.base.ui.dialog
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.view.LayoutInflater
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import com.google.android.material.checkbox.MaterialCheckBox
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.databinding.DialogCheckboxBinding
class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog) :
DialogInterface by delegate {
@@ -18,13 +16,10 @@ class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog)
class Builder(context: Context) {
@SuppressLint("InflateParams")
private val view = LayoutInflater.from(context)
.inflate(R.layout.dialog_checkbox, null, false)
private val checkBox = view.findViewById<MaterialCheckBox>(android.R.id.checkbox)
private val binding = DialogCheckboxBinding.inflate(LayoutInflater.from(context))
private val delegate = MaterialAlertDialogBuilder(context)
.setView(view)
.setView(binding.root)
fun setTitle(@StringRes titleResId: Int): Builder {
delegate.setTitle(titleResId)
@@ -47,12 +42,12 @@ class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog)
}
fun setCheckBoxText(@StringRes textId: Int): Builder {
checkBox.setText(textId)
binding.checkbox.setText(textId)
return this
}
fun setCheckBoxChecked(isChecked: Boolean): Builder {
checkBox.isChecked = isChecked
binding.checkbox.isChecked = isChecked
return this
}
@@ -66,7 +61,7 @@ class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog)
listener: (DialogInterface, Boolean) -> Unit
): Builder {
delegate.setPositiveButton(textId) { dialog, _ ->
listener(dialog, checkBox.isChecked)
listener(dialog, binding.checkbox.isChecked)
}
return this
}

View File

@@ -1,19 +1,18 @@
package org.koitharu.kotatsu.ui.common.dialog
package org.koitharu.kotatsu.base.ui.dialog
import android.content.Context
import android.content.DialogInterface
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.android.synthetic.main.item_storage.view.*
import kotlinx.coroutines.runBlocking
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
import org.koitharu.kotatsu.utils.ext.getStorageName
import org.koitharu.kotatsu.utils.ext.inflate
import org.koitharu.kotatsu.utils.ext.longHashCode
import org.koitharu.kotatsu.databinding.ItemStorageBinding
import org.koitharu.kotatsu.local.data.LocalStorageManager
import java.io.File
class StorageSelectDialog private constructor(private val delegate: AlertDialog) :
@@ -21,19 +20,22 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog)
fun show() = delegate.show()
class Builder(context: Context, defaultValue: File?, listener: OnStorageSelectListener) {
class Builder(context: Context, storageManager: LocalStorageManager, listener: OnStorageSelectListener) {
private val adapter = VolumesAdapter(context)
private val adapter = VolumesAdapter(storageManager)
private val delegate = MaterialAlertDialogBuilder(context)
init {
if (adapter.isEmpty) {
delegate.setMessage(R.string.cannot_find_available_storage)
} else {
val checked = adapter.volumes.indexOfFirst {
val defaultValue = runBlocking {
storageManager.getDefaultWriteableDir()
}
adapter.selectedItemPosition = adapter.volumes.indexOfFirst {
it.first.canonicalPath == defaultValue?.canonicalPath
}
delegate.setSingleChoiceItems(adapter, checked) { d, i ->
delegate.setAdapter(adapter) { d, i ->
listener.onStorageSelected(adapter.getItem(i).first)
d.dismiss()
}
@@ -58,38 +60,42 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog)
fun create() = StorageSelectDialog(delegate.create())
}
private class VolumesAdapter(context: Context) : BaseAdapter() {
private class VolumesAdapter(storageManager: LocalStorageManager) : BaseAdapter() {
val volumes = getAvailableVolumes(context)
var selectedItemPosition: Int = -1
val volumes = getAvailableVolumes(storageManager)
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: parent.inflate(R.layout.item_storage)
val view = convertView ?: LayoutInflater.from(parent.context).inflate(R.layout.item_storage, parent, false)
val binding = (view.tag as? ItemStorageBinding) ?: ItemStorageBinding.bind(view).also {
view.tag = it
}
val item = volumes[position]
view.textView_title.text = item.second
view.textView_subtitle.text = item.first.path
binding.imageViewIndicator.isChecked = selectedItemPosition == position
binding.textViewTitle.text = item.second
binding.textViewSubtitle.text = item.first.path
return view
}
override fun getItem(position: Int): Pair<File, String> = volumes[position]
override fun getItemId(position: Int) = volumes[position].first.absolutePath.longHashCode()
override fun getItemId(position: Int) = position.toLong()
override fun getCount() = volumes.size
}
override fun hasStableIds() = true
interface OnStorageSelectListener {
fun onStorageSelected(file: File)
}
private companion object {
@JvmStatic
fun getAvailableVolumes(context: Context): List<Pair<File, String>> {
return LocalMangaRepository.getAvailableStorageDirs(context).map {
it to it.getStorageName(context)
private fun getAvailableVolumes(storageManager: LocalStorageManager): List<Pair<File, String>> {
return runBlocking {
storageManager.getWriteableDirs().map {
it to storageManager.getStorageDisplayName(it)
}
}
}
}
fun interface OnStorageSelectListener {
fun onStorageSelected(file: File)
}
}

View File

@@ -1,6 +1,5 @@
package org.koitharu.kotatsu.ui.common.dialog
package org.koitharu.kotatsu.base.ui.dialog
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.text.InputFilter
@@ -8,21 +7,20 @@ import android.view.LayoutInflater
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.android.synthetic.main.dialog_input.view.*
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.databinding.DialogInputBinding
class TextInputDialog private constructor(private val delegate: AlertDialog) :
DialogInterface by delegate {
class TextInputDialog private constructor(
private val delegate: AlertDialog,
) : DialogInterface by delegate {
fun show() = delegate.show()
class Builder(context: Context) {
@SuppressLint("InflateParams")
private val view = LayoutInflater.from(context).inflate(R.layout.dialog_input, null, false)
private val binding = DialogInputBinding.inflate(LayoutInflater.from(context))
private val delegate = MaterialAlertDialogBuilder(context)
.setView(view)
.setView(binding.root)
fun setTitle(@StringRes titleResId: Int): Builder {
delegate.setTitle(titleResId)
@@ -35,44 +33,55 @@ class TextInputDialog private constructor(private val delegate: AlertDialog) :
}
fun setHint(@StringRes hintResId: Int): Builder {
view.inputLayout.hint = view.context.getString(hintResId)
binding.inputEdit.hint = binding.root.context.getString(hintResId)
return this
}
fun setMaxLength(maxLength: Int, strict: Boolean): Builder {
with(view.inputLayout) {
with(binding.inputLayout) {
counterMaxLength = maxLength
isCounterEnabled = maxLength > 0
}
if (strict && maxLength > 0) {
view.inputEdit.filters += InputFilter.LengthFilter(maxLength)
binding.inputEdit.filters += InputFilter.LengthFilter(maxLength)
}
return this
}
fun setInputType(inputType: Int): Builder {
view.inputEdit.inputType = inputType
binding.inputEdit.inputType = inputType
return this
}
fun setText(text: String): Builder {
view.inputEdit.setText(text)
view.inputEdit.setSelection(text.length)
binding.inputEdit.setText(text)
binding.inputEdit.setSelection(text.length)
return this
}
fun setPositiveButton(@StringRes textId: Int, listener: (DialogInterface, String) -> Unit): Builder {
fun setPositiveButton(
@StringRes textId: Int,
listener: (DialogInterface, String) -> Unit
): Builder {
delegate.setPositiveButton(textId) { dialog, _ ->
listener(dialog, view.inputEdit.text?.toString().orEmpty())
listener(dialog, binding.inputEdit.text?.toString().orEmpty())
}
return this
}
fun setNegativeButton(@StringRes textId: Int, listener: DialogInterface.OnClickListener? = null): Builder {
fun setNegativeButton(
@StringRes textId: Int,
listener: DialogInterface.OnClickListener? = null
): Builder {
delegate.setNegativeButton(textId, listener)
return this
}
fun setOnCancelListener(listener: DialogInterface.OnCancelListener): Builder {
delegate.setOnCancelListener(listener)
return this
}
fun create() =
TextInputDialog(delegate.create())

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.ui.common.list
package org.koitharu.kotatsu.base.ui.list
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

View File

@@ -0,0 +1,37 @@
package org.koitharu.kotatsu.base.ui.list
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
class FitHeightGridLayoutManager : GridLayoutManager {
constructor(context: Context?, spanCount: Int) : super(context, spanCount)
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int,
) : super(context, attrs, defStyleAttr, defStyleRes)
constructor(
context: Context?,
spanCount: Int,
orientation: Int,
reverseLayout: Boolean,
) : super(context, spanCount, orientation, reverseLayout)
override fun layoutDecoratedWithMargins(child: View, left: Int, top: Int, right: Int, bottom: Int) {
if (orientation == RecyclerView.VERTICAL && child.layoutParams.height == LayoutParams.MATCH_PARENT) {
val parentBottom = height - paddingBottom
val offset = parentBottom - bottom
super.layoutDecoratedWithMargins(child, left, top + offset, right, bottom + offset)
} else {
super.layoutDecoratedWithMargins(child, left, top, right, bottom)
}
}
}

View File

@@ -0,0 +1,37 @@
package org.koitharu.kotatsu.base.ui.list
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.annotation.AttrRes
import androidx.annotation.StyleRes
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutParams
class FitHeightLinearLayoutManager : LinearLayoutManager {
constructor(context: Context) : super(context)
constructor(
context: Context,
@RecyclerView.Orientation orientation: Int,
reverseLayout: Boolean,
) : super(context, orientation, reverseLayout)
constructor(
context: Context,
attrs: AttributeSet?,
@AttrRes defStyleAttr: Int,
@StyleRes defStyleRes: Int,
) : super(context, attrs, defStyleAttr, defStyleRes)
override fun layoutDecoratedWithMargins(child: View, left: Int, top: Int, right: Int, bottom: Int) {
if (orientation == RecyclerView.VERTICAL && child.layoutParams.height == LayoutParams.MATCH_PARENT) {
val parentBottom = height - paddingBottom
val offset = parentBottom - bottom
super.layoutDecoratedWithMargins(child, left, top + offset, right, bottom + offset)
} else {
super.layoutDecoratedWithMargins(child, left, top, right, bottom)
}
}
}

View File

@@ -0,0 +1,10 @@
package org.koitharu.kotatsu.base.ui.list
import android.view.View
interface OnListItemClickListener<I> {
fun onItemClick(item: I, view: View)
fun onItemLongClick(item: I, view: View) = false
}

View File

@@ -0,0 +1,18 @@
package org.koitharu.kotatsu.base.ui.list
import androidx.recyclerview.widget.RecyclerView
class PaginationScrollListener(offset: Int, private val callback: Callback) :
BoundsScrollListener(0, offset) {
override fun onScrolledToStart(recyclerView: RecyclerView) = Unit
override fun onScrolledToEnd(recyclerView: RecyclerView) {
callback.onScrolledToEnd()
}
interface Callback {
fun onScrolledToEnd()
}
}

View File

@@ -0,0 +1,87 @@
package org.koitharu.kotatsu.base.ui.list.decor
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.view.View
import androidx.core.content.res.getColorOrThrow
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.R as materialR
@SuppressLint("PrivateResource")
abstract class AbstractDividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() {
private val bounds = Rect()
private val thickness: Int
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
init {
paint.style = Paint.Style.FILL
val ta = context.obtainStyledAttributes(
null,
materialR.styleable.MaterialDivider,
materialR.attr.materialDividerStyle,
materialR.style.Widget_Material3_MaterialDivider,
)
paint.color = ta.getColorOrThrow(materialR.styleable.MaterialDivider_dividerColor)
thickness = ta.getDimensionPixelSize(
materialR.styleable.MaterialDivider_dividerThickness,
context.resources.getDimensionPixelSize(materialR.dimen.material_divider_thickness),
)
ta.recycle()
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State,
) {
outRect.set(0, thickness, 0, 0)
}
// TODO implement for horizontal lists on demand
override fun onDraw(canvas: Canvas, parent: RecyclerView, s: RecyclerView.State) {
if (parent.layoutManager == null || thickness == 0) {
return
}
canvas.save()
val left: Float
val right: Float
if (parent.clipToPadding) {
left = parent.paddingLeft.toFloat()
right = (parent.width - parent.paddingRight).toFloat()
canvas.clipRect(
left,
parent.paddingTop.toFloat(),
right,
(parent.height - parent.paddingBottom).toFloat()
)
} else {
left = 0f
right = parent.width.toFloat()
}
var previous: RecyclerView.ViewHolder? = null
for (child in parent.children) {
val holder = parent.getChildViewHolder(child)
if (previous != null && shouldDrawDivider(previous, holder)) {
parent.getDecoratedBoundsWithMargins(child, bounds)
val top: Float = bounds.top + child.translationY
val bottom: Float = top + thickness
canvas.drawRect(left, top, right, bottom, paint)
}
previous = holder
}
canvas.restore()
}
protected abstract fun shouldDrawDivider(
above: RecyclerView.ViewHolder,
below: RecyclerView.ViewHolder,
): Boolean
}

View File

@@ -0,0 +1,111 @@
package org.koitharu.kotatsu.base.ui.list.decor
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.RectF
import android.view.View
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.NO_ID
abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() {
private val bounds = Rect()
private val boundsF = RectF()
private val selection = HashSet<Long>()
protected var hasBackground: Boolean = true
protected var hasForeground: Boolean = false
protected var isIncludeDecorAndMargins: Boolean = true
val checkedItemsCount: Int
get() = selection.size
val checkedItemsIds: Set<Long>
get() = selection
fun toggleItemChecked(id: Long) {
if (!selection.remove(id)) {
selection.add(id)
}
}
fun setItemIsChecked(id: Long, isChecked: Boolean) {
if (isChecked) {
selection.add(id)
} else {
selection.remove(id)
}
}
fun checkAll(ids: Collection<Long>) {
selection.addAll(ids)
}
fun clearSelection() {
selection.clear()
}
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (hasBackground) {
doDraw(canvas, parent, state, false)
} else {
super.onDraw(canvas, parent, state)
}
}
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (hasForeground) {
doDraw(canvas, parent, state, true)
} else {
super.onDrawOver(canvas, parent, state)
}
}
private fun doDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State, isOver: Boolean) {
val checkpoint = canvas.save()
if (parent.clipToPadding) {
canvas.clipRect(
parent.paddingLeft, parent.paddingTop, parent.width - parent.paddingRight,
parent.height - parent.paddingBottom
)
}
for (child in parent.children) {
val itemId = getItemId(parent, child)
if (itemId != NO_ID && itemId in selection) {
if (isIncludeDecorAndMargins) {
parent.getDecoratedBoundsWithMargins(child, bounds)
} else {
bounds.set(child.left, child.top, child.right, child.bottom)
}
boundsF.set(bounds)
boundsF.offset(child.translationX, child.translationY)
if (isOver) {
onDrawForeground(canvas, parent, child, boundsF, state)
} else {
onDrawBackground(canvas, parent, child, boundsF, state)
}
}
}
canvas.restoreToCount(checkpoint)
}
protected open fun getItemId(parent: RecyclerView, child: View) = parent.getChildItemId(child)
protected open fun onDrawBackground(
canvas: Canvas,
parent: RecyclerView,
child: View,
bounds: RectF,
state: RecyclerView.State,
) = Unit
protected open fun onDrawForeground(
canvas: Canvas,
parent: RecyclerView,
child: View,
bounds: RectF,
state: RecyclerView.State,
) = Unit
}

View File

@@ -0,0 +1,18 @@
package org.koitharu.kotatsu.base.ui.list.decor
import android.graphics.Rect
import android.view.View
import androidx.annotation.Px
import androidx.recyclerview.widget.RecyclerView
class SpacingItemDecoration(@Px private val spacing: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
outRect.set(spacing, spacing, spacing, spacing)
}
}

View File

@@ -0,0 +1,35 @@
package org.koitharu.kotatsu.base.ui.list.decor
import android.graphics.Rect
import android.util.SparseIntArray
import android.view.View
import androidx.core.util.getOrDefault
import androidx.core.util.set
import androidx.recyclerview.widget.RecyclerView
class TypedSpacingItemDecoration(
vararg spacingMapping: Pair<Int, Int>,
private val fallbackSpacing: Int = 0,
) : RecyclerView.ItemDecoration() {
private val mapping = SparseIntArray(spacingMapping.size)
init {
spacingMapping.forEach { (k, v) -> mapping[k] = v }
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val itemType = parent.getChildViewHolder(view)?.itemViewType
val spacing = if (itemType == null) {
fallbackSpacing
} else {
mapping.getOrDefault(itemType, fallbackSpacing)
}
outRect.set(spacing, spacing, spacing, spacing)
}
}

View File

@@ -0,0 +1,50 @@
package org.koitharu.kotatsu.base.ui.util
import androidx.appcompat.view.ActionMode
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
class ActionModeDelegate {
private var activeActionMode: ActionMode? = null
private var listeners: MutableList<ActionModeListener>? = null
val isActionModeStarted: Boolean
get() = activeActionMode != null
fun onSupportActionModeStarted(mode: ActionMode) {
activeActionMode = mode
listeners?.forEach { it.onActionModeStarted(mode) }
}
fun onSupportActionModeFinished(mode: ActionMode) {
activeActionMode = null
listeners?.forEach { it.onActionModeFinished(mode) }
}
fun addListener(listener: ActionModeListener) {
if (listeners == null) {
listeners = ArrayList()
}
checkNotNull(listeners).add(listener)
}
fun removeListener(listener: ActionModeListener) {
listeners?.remove(listener)
}
fun addListener(listener: ActionModeListener, owner: LifecycleOwner) {
addListener(listener)
owner.lifecycle.addObserver(ListenerLifecycleObserver(listener))
}
private inner class ListenerLifecycleObserver(
private val listener: ActionModeListener,
) : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
removeListener(listener)
}
}
}

View File

@@ -0,0 +1,10 @@
package org.koitharu.kotatsu.base.ui.util
import androidx.appcompat.view.ActionMode
interface ActionModeListener {
fun onActionModeStarted(mode: ActionMode)
fun onActionModeFinished(mode: ActionMode)
}

View File

@@ -0,0 +1,20 @@
package org.koitharu.kotatsu.base.ui.util
import androidx.lifecycle.MutableLiveData
class CountedBooleanLiveData : MutableLiveData<Boolean>(false) {
private var counter = 0
override fun setValue(value: Boolean) {
if (value) {
counter++
} else {
counter--
}
val newValue = counter > 0
if (newValue != this.value) {
super.setValue(newValue)
}
}
}

View File

@@ -0,0 +1,8 @@
package org.koitharu.kotatsu.base.ui.util
import androidx.recyclerview.widget.RecyclerView
interface RecyclerViewOwner {
val recyclerView: RecyclerView
}

View File

@@ -0,0 +1,48 @@
package org.koitharu.kotatsu.base.ui.util
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior
import androidx.core.view.ViewCompat
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
class ShrinkOnScrollBehavior : Behavior<ExtendedFloatingActionButton> {
@Suppress("unused") constructor() : super()
@Suppress("unused") constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: ExtendedFloatingActionButton,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}
override fun onNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: ExtendedFloatingActionButton,
target: View,
dxConsumed: Int,
dyConsumed: Int,
dxUnconsumed: Int,
dyUnconsumed: Int,
type: Int,
consumed: IntArray
) {
if (dyConsumed > 0) {
if (child.isExtended) {
child.shrink()
}
} else if (dyConsumed < 0) {
if (!child.isExtended) {
child.extend()
}
}
}
}

View File

@@ -0,0 +1,69 @@
package org.koitharu.kotatsu.base.ui.util
import android.view.View
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
class WindowInsetsDelegate(
private val listener: WindowInsetsListener,
) : OnApplyWindowInsetsListener, View.OnLayoutChangeListener {
var handleImeInsets: Boolean = false
var interceptingWindowInsetsListener: OnApplyWindowInsetsListener? = null
private var lastInsets: Insets? = null
override fun onApplyWindowInsets(v: View?, insets: WindowInsetsCompat?): WindowInsetsCompat? {
if (insets == null) {
return null
}
val handledInsets = interceptingWindowInsetsListener?.onApplyWindowInsets(v, insets) ?: insets
val newInsets = if (handleImeInsets) {
Insets.max(
handledInsets.getInsets(WindowInsetsCompat.Type.systemBars()),
handledInsets.getInsets(WindowInsetsCompat.Type.ime()),
)
} else {
handledInsets.getInsets(WindowInsetsCompat.Type.systemBars())
}
if (newInsets != lastInsets) {
listener.onWindowInsetsChanged(newInsets)
lastInsets = newInsets
}
return handledInsets
}
override fun onLayoutChange(
view: View,
left: Int,
top: Int,
right: Int,
bottom: Int,
oldLeft: Int,
oldTop: Int,
oldRight: Int,
oldBottom: Int,
) {
view.removeOnLayoutChangeListener(this)
if (lastInsets == null) { // Listener may not be called
onApplyWindowInsets(view, ViewCompat.getRootWindowInsets(view))
}
}
fun onViewCreated(view: View) {
ViewCompat.setOnApplyWindowInsetsListener(view, this)
view.addOnLayoutChangeListener(this)
}
fun onDestroyView() {
lastInsets = null
}
interface WindowInsetsListener {
fun onWindowInsetsChanged(insets: Insets)
}
}

View File

@@ -0,0 +1,42 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.AttrRes
import androidx.annotation.IdRes
import androidx.core.view.children
import com.google.android.material.button.MaterialButton
class CheckableButtonGroup @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
) : LinearLayout(context, attrs, defStyleAttr), View.OnClickListener {
var onCheckedChangeListener: OnCheckedChangeListener? = null
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
if (child is MaterialButton) {
child.setOnClickListener(this)
}
super.addView(child, index, params)
}
override fun onClick(v: View) {
setCheckedId(v.id)
}
fun setCheckedId(@IdRes viewRes: Int) {
children.forEach {
(it as? MaterialButton)?.isChecked = it.id == viewRes
}
onCheckedChangeListener?.onCheckedChanged(this, viewRes)
}
fun interface OnCheckedChangeListener {
fun onCheckedChanged(group: CheckableButtonGroup, checkedId: Int)
}
}

View File

@@ -0,0 +1,102 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import android.util.AttributeSet
import android.view.View
import android.widget.Checkable
import androidx.annotation.AttrRes
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.os.ParcelCompat
class CheckableImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
) : AppCompatImageView(context, attrs, defStyleAttr), Checkable {
private var isCheckedInternal = false
private var isBroadcasting = false
var onCheckedChangeListener: OnCheckedChangeListener? = null
override fun isChecked() = isCheckedInternal
override fun toggle() {
isChecked = !isCheckedInternal
}
override fun setChecked(checked: Boolean) {
if (checked != isCheckedInternal) {
isCheckedInternal = checked
refreshDrawableState()
if (!isBroadcasting) {
isBroadcasting = true
onCheckedChangeListener?.onCheckedChanged(this, checked)
isBroadcasting = false
}
}
}
override fun onCreateDrawableState(extraSpace: Int): IntArray {
val state = super.onCreateDrawableState(extraSpace + 1)
if (isCheckedInternal) {
mergeDrawableStates(state, intArrayOf(android.R.attr.state_checked))
}
return state
}
override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState() ?: return null
return SavedState(superState, isChecked)
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state is SavedState) {
super.onRestoreInstanceState(state.superState)
isChecked = state.isChecked
} else {
super.onRestoreInstanceState(state)
}
}
class ToggleOnClickListener : OnClickListener {
override fun onClick(view: View) {
(view as? Checkable)?.toggle()
}
}
fun interface OnCheckedChangeListener {
fun onCheckedChanged(view: CheckableImageView, isChecked: Boolean)
}
private class SavedState : BaseSavedState {
val isChecked: Boolean
constructor(superState: Parcelable, checked: Boolean) : super(superState) {
isChecked = checked
}
constructor(source: Parcel) : super(source) {
isChecked = ParcelCompat.readBoolean(source)
}
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
ParcelCompat.writeBoolean(out, isChecked)
}
companion object {
@JvmField
val CREATOR: Creator<SavedState> = object : Creator<SavedState> {
override fun createFromParcel(`in`: Parcel) = SavedState(`in`)
override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size)
}
}
}
}

View File

@@ -0,0 +1,134 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.View.OnClickListener
import androidx.annotation.DrawableRes
import androidx.core.view.children
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.google.android.material.chip.ChipGroup
import org.koitharu.kotatsu.R
class ChipsView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = com.google.android.material.R.attr.chipGroupStyle
) : ChipGroup(context, attrs, defStyleAttr) {
private var isLayoutSuppressedCompat = false
private var isLayoutCalledOnSuppressed = false
private var chipOnClickListener = OnClickListener {
onChipClickListener?.onChipClick(it as Chip, it.tag)
}
private var chipOnCloseListener = OnClickListener {
onChipCloseClickListener?.onChipCloseClick(it as Chip, it.tag)
}
var onChipClickListener: OnChipClickListener? = null
set(value) {
field = value
val isChipClickable = value != null
children.forEach { it.isClickable = isChipClickable }
}
var onChipCloseClickListener: OnChipCloseClickListener? = null
set(value) {
field = value
val isCloseIconVisible = value != null
children.forEach { (it as? Chip)?.isCloseIconVisible = isCloseIconVisible }
}
override fun requestLayout() {
if (isLayoutSuppressedCompat) {
isLayoutCalledOnSuppressed = true
} else {
super.requestLayout()
}
}
fun setChips(items: Collection<ChipModel>) {
suppressLayoutCompat(true)
try {
for ((i, model) in items.withIndex()) {
val chip = getChildAt(i) as Chip? ?: addChip()
bindChip(chip, model)
}
if (childCount > items.size) {
removeViews(items.size, childCount - items.size)
}
} finally {
suppressLayoutCompat(false)
}
}
private fun bindChip(chip: Chip, model: ChipModel) {
chip.text = model.title
if (model.icon == 0) {
chip.isChipIconVisible = false
} else {
chip.isCheckedIconVisible = true
chip.setChipIconResource(model.icon)
}
chip.isClickable = onChipClickListener != null
chip.tag = model.data
}
private fun addChip(): Chip {
val chip = Chip(context)
val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_Kotatsu_Chip)
chip.setChipDrawable(drawable)
chip.isCloseIconVisible = onChipCloseClickListener != null
chip.setOnCloseIconClickListener(chipOnCloseListener)
chip.setEnsureMinTouchTargetSize(false)
chip.setOnClickListener(chipOnClickListener)
chip.isCheckable = false
addView(chip)
return chip
}
private fun suppressLayoutCompat(suppress: Boolean) {
isLayoutSuppressedCompat = suppress
if (!suppress) {
if (isLayoutCalledOnSuppressed) {
requestLayout()
isLayoutCalledOnSuppressed = false
}
}
}
class ChipModel(
@DrawableRes val icon: Int,
val title: CharSequence,
val data: Any? = null
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ChipModel
if (icon != other.icon) return false
if (title != other.title) return false
if (data != other.data) return false
return true
}
override fun hashCode(): Int {
var result = icon
result = 31 * result + title.hashCode()
result = 31 * result + data.hashCode()
return result
}
}
fun interface OnChipClickListener {
fun onChipClick(chip: Chip, data: Any?)
}
fun interface OnChipCloseClickListener {
fun onChipCloseClick(chip: Chip, data: Any?)
}
}

View File

@@ -0,0 +1,43 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout.HORIZONTAL
import android.widget.LinearLayout.VERTICAL
import androidx.annotation.AttrRes
import androidx.core.content.withStyledAttributes
import com.google.android.material.imageview.ShapeableImageView
import org.koitharu.kotatsu.R
import kotlin.math.roundToInt
private const val ASPECT_RATIO_HEIGHT = 18f
private const val ASPECT_RATIO_WIDTH = 13f
class CoverImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
) : ShapeableImageView(context, attrs, defStyleAttr) {
private var orientation: Int = HORIZONTAL
init {
context.withStyledAttributes(attrs, R.styleable.CoverImageView, defStyleAttr) {
orientation = getInt(R.styleable.CoverImageView_android_orientation, orientation)
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val desiredWidth: Int
val desiredHeight: Int
if (orientation == VERTICAL) {
desiredHeight = measuredHeight
desiredWidth = (desiredHeight * ASPECT_RATIO_WIDTH / ASPECT_RATIO_HEIGHT).roundToInt()
} else {
desiredWidth = measuredWidth
desiredHeight = (desiredWidth * ASPECT_RATIO_HEIGHT / ASPECT_RATIO_WIDTH).roundToInt()
}
setMeasuredDimension(desiredWidth, desiredHeight)
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.Button
import android.widget.FrameLayout
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.core.view.postDelayed
import org.koitharu.kotatsu.R
private const val ENTER_DURATION = 300L
private const val EXIT_DURATION = 200L
private const val SHORT_DURATION = 1_500L
private const val LONG_DURATION = 2_750L
/**
* A custom snackbar implementation allowing more control over placement and entry/exit animations.
*
* Xtimms: Well, my sufferings over the Snackbar in [DetailsActivity] will go away forever... Thanks, Google.
*
* https://github.com/google/iosched/blob/main/mobile/src/main/java/com/google/samples/apps/iosched/widget/FadingSnackbar.kt
*/
class FadingSnackbar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private val message: TextView
private val action: Button
init {
val view = LayoutInflater.from(context).inflate(R.layout.fading_snackbar_layout, this, true)
message = view.findViewById(R.id.snackbar_text)
action = view.findViewById(R.id.snackbar_action)
}
fun dismiss() {
if (visibility == VISIBLE && alpha == 1f) {
animate()
.alpha(0f)
.withEndAction { visibility = GONE }
.duration = EXIT_DURATION
}
}
fun show(
messageText: CharSequence? = null,
@StringRes actionId: Int? = null,
longDuration: Boolean = true,
actionClick: () -> Unit = { dismiss() },
dismissListener: () -> Unit = { }
) {
message.text = messageText
if (actionId != null) {
action.run {
visibility = VISIBLE
text = context.getString(actionId)
setOnClickListener {
actionClick()
}
}
} else {
action.visibility = GONE
}
alpha = 0f
visibility = VISIBLE
animate()
.alpha(1f)
.duration = ENTER_DURATION
val showDuration = ENTER_DURATION + if (longDuration) LONG_DURATION else SHORT_DURATION
postDelayed(showDuration) {
dismiss()
dismissListener()
}
}
}

View File

@@ -0,0 +1,125 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.content.res.TypedArray
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import android.graphics.drawable.RippleDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RectShape
import android.util.AttributeSet
import androidx.annotation.AttrRes
import androidx.appcompat.widget.AppCompatCheckedTextView
import androidx.core.content.withStyledAttributes
import com.google.android.material.ripple.RippleUtils
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.ext.getThemeColorStateList
@SuppressLint("RestrictedApi")
class ListItemTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = R.attr.listItemTextViewStyle,
) : AppCompatCheckedTextView(context, attrs, defStyleAttr) {
private var checkedDrawableStart: Drawable? = null
private var checkedDrawableEnd: Drawable? = null
private var isInitialized = false
private var isCheckDrawablesVisible: Boolean = false
private var defaultPaddingStart: Int = 0
private var defaultPaddingEnd: Int = 0
init {
context.withStyledAttributes(attrs, R.styleable.ListItemTextView, defStyleAttr) {
val itemRippleColor = getColorStateList(R.styleable.ListItemTextView_rippleColor)
?: getRippleColorFallback(context)
val shape = createShapeDrawable(this)
background = RippleDrawable(
RippleUtils.sanitizeRippleDrawableColor(itemRippleColor),
shape,
ShapeDrawable(RectShape()),
)
checkedDrawableStart = getDrawable(R.styleable.ListItemTextView_checkedDrawableStart)
checkedDrawableEnd = getDrawable(R.styleable.ListItemTextView_checkedDrawableEnd)
}
checkedDrawableStart?.setTintList(textColors)
checkedDrawableEnd?.setTintList(textColors)
defaultPaddingStart = paddingStart
defaultPaddingEnd = paddingEnd
isInitialized = true
adjustCheckDrawables()
}
override fun refreshDrawableState() {
super.refreshDrawableState()
adjustCheckDrawables()
}
override fun setTextColor(colors: ColorStateList?) {
checkedDrawableStart?.setTintList(colors)
checkedDrawableEnd?.setTintList(colors)
super.setTextColor(colors)
}
override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
defaultPaddingStart = start
defaultPaddingEnd = end
super.setPaddingRelative(start, top, end, bottom)
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
defaultPaddingStart = if (isRtl) right else left
defaultPaddingEnd = if (isRtl) left else right
super.setPadding(left, top, right, bottom)
}
private fun adjustCheckDrawables() {
if (isInitialized && isCheckDrawablesVisible != isChecked) {
setCompoundDrawablesRelativeWithIntrinsicBounds(
if (isChecked) checkedDrawableStart else null,
null,
if (isChecked) checkedDrawableEnd else null,
null,
)
super.setPaddingRelative(
if (isChecked && checkedDrawableStart != null) {
defaultPaddingStart + compoundDrawablePadding
} else defaultPaddingStart,
paddingTop,
if (isChecked && checkedDrawableEnd != null) {
defaultPaddingEnd + compoundDrawablePadding
} else defaultPaddingEnd,
paddingBottom,
)
isCheckDrawablesVisible = isChecked
}
}
private fun createShapeDrawable(ta: TypedArray): InsetDrawable {
val shapeAppearance = ShapeAppearanceModel.builder(
context,
ta.getResourceId(R.styleable.ListItemTextView_shapeAppearance, 0),
ta.getResourceId(R.styleable.ListItemTextView_shapeAppearanceOverlay, 0),
).build()
val shapeDrawable = MaterialShapeDrawable(shapeAppearance)
shapeDrawable.fillColor = ta.getColorStateList(R.styleable.ListItemTextView_backgroundTint)
return InsetDrawable(
shapeDrawable,
ta.getDimensionPixelOffset(R.styleable.ListItemTextView_android_insetLeft, 0),
ta.getDimensionPixelOffset(R.styleable.ListItemTextView_android_insetTop, 0),
ta.getDimensionPixelOffset(R.styleable.ListItemTextView_android_insetRight, 0),
ta.getDimensionPixelOffset(R.styleable.ListItemTextView_android_insetBottom, 0),
)
}
private fun getRippleColorFallback(context: Context): ColorStateList {
return context.getThemeColorStateList(android.R.attr.colorControlHighlight)
?: ColorStateList.valueOf(Color.TRANSPARENT)
}
}

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.ui.common.widgets
package org.koitharu.kotatsu.base.ui.widgets
import android.content.Context
import android.util.AttributeSet

View File

@@ -0,0 +1,72 @@
package org.koitharu.kotatsu.base.ui.widgets
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.WindowInsets
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.annotation.AttrRes
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.WindowInsetsCompat
class WindowInsetHolder @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) {
private var desiredHeight = 0
private var desiredWidth = 0
@SuppressLint("RtlHardcoded")
override fun dispatchApplyWindowInsets(insets: WindowInsets): WindowInsets {
val barsInsets = WindowInsetsCompat.toWindowInsetsCompat(insets, this)
.getInsets(WindowInsetsCompat.Type.systemBars())
val gravity = getLayoutGravity()
val newWidth = when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
Gravity.LEFT -> barsInsets.left
Gravity.RIGHT -> barsInsets.right
else -> 0
}
val newHeight = when (gravity and Gravity.VERTICAL_GRAVITY_MASK) {
Gravity.TOP -> barsInsets.top
Gravity.BOTTOM -> barsInsets.bottom
else -> 0
}
if (newWidth != desiredWidth || newHeight != desiredHeight) {
desiredWidth = newWidth
desiredHeight = newHeight
requestLayout()
}
return super.dispatchApplyWindowInsets(insets)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
val heightMode = MeasureSpec.getMode(heightMeasureSpec)
super.onMeasure(
if (desiredWidth == 0 || widthMode == MeasureSpec.EXACTLY) {
widthMeasureSpec
} else {
MeasureSpec.makeMeasureSpec(desiredWidth, widthMode)
},
if (desiredHeight == 0 || heightMode == MeasureSpec.EXACTLY) {
heightMeasureSpec
} else {
MeasureSpec.makeMeasureSpec(desiredHeight, heightMode)
},
)
}
private fun getLayoutGravity(): Int {
return when (val lp = layoutParams) {
is FrameLayout.LayoutParams -> lp.gravity
is LinearLayout.LayoutParams -> lp.gravity
is CoordinatorLayout.LayoutParams -> lp.gravity
else -> Gravity.NO_GRAVITY
}
}
}

View File

@@ -0,0 +1,139 @@
package org.koitharu.kotatsu.browser
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.core.graphics.Insets
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.google.android.material.R as materialR
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.core.network.UserAgentInterceptor
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
@SuppressLint("SetJavaScriptEnabled")
class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityBrowserBinding.inflate(layoutInflater))
supportActionBar?.run {
setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
}
with(binding.webView.settings) {
javaScriptEnabled = true
userAgentString = UserAgentInterceptor.userAgent
}
binding.webView.webViewClient = BrowserClient(this)
binding.webView.webChromeClient = ProgressChromeClient(binding.progressBar)
if (savedInstanceState != null) {
return
}
val url = intent?.dataString
if (url.isNullOrEmpty()) {
finishAfterTransition()
} else {
onTitleChanged(
intent?.getStringExtra(EXTRA_TITLE) ?: getString(R.string.loading_),
url
)
binding.webView.loadUrl(url)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
binding.webView.saveState(outState)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
binding.webView.restoreState(savedInstanceState)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.opt_browser, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> {
binding.webView.stopLoading()
finishAfterTransition()
true
}
R.id.action_browser -> {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(binding.webView.url)
try {
startActivity(Intent.createChooser(intent, item.title))
} catch (_: ActivityNotFoundException) {
}
true
}
else -> super.onOptionsItemSelected(item)
}
override fun onBackPressed() {
if (binding.webView.canGoBack()) {
binding.webView.goBack()
} else {
super.onBackPressed()
}
}
override fun onPause() {
binding.webView.onPause()
super.onPause()
}
override fun onResume() {
super.onResume()
binding.webView.onResume()
}
override fun onDestroy() {
super.onDestroy()
binding.webView.destroy()
}
override fun onLoadingStateChanged(isLoading: Boolean) {
binding.progressBar.isVisible = isLoading
}
override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) {
this.title = title
supportActionBar?.subtitle = subtitle
}
override fun onWindowInsetsChanged(insets: Insets) {
binding.appbar.updatePadding(
top = insets.top,
left = insets.left,
right = insets.right,
)
binding.root.updatePadding(
left = insets.left,
right = insets.right,
bottom = insets.bottom,
)
}
companion object {
private const val EXTRA_TITLE = "title"
fun newIntent(context: Context, url: String, title: String?): Intent {
return Intent(context, BrowserActivity::class.java)
.setData(Uri.parse(url))
.putExtra(EXTRA_TITLE, title)
}
}
}

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.ui.browser
package org.koitharu.kotatsu.browser
interface BrowserCallback {

View File

@@ -0,0 +1,24 @@
package org.koitharu.kotatsu.browser
import android.graphics.Bitmap
import android.webkit.WebView
import org.koin.core.component.KoinComponent
import org.koitharu.kotatsu.core.network.WebViewClientCompat
class BrowserClient(private val callback: BrowserCallback) : WebViewClientCompat(), KoinComponent {
override fun onPageFinished(webView: WebView, url: String) {
super.onPageFinished(webView, url)
callback.onLoadingStateChanged(isLoading = false)
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
callback.onLoadingStateChanged(isLoading = true)
}
override fun onPageCommitVisible(view: WebView, url: String?) {
super.onPageCommitVisible(view, url)
callback.onTitleChanged(view.title.orEmpty(), url)
}
}

View File

@@ -0,0 +1,30 @@
package org.koitharu.kotatsu.browser
import android.webkit.WebChromeClient
import android.webkit.WebView
import androidx.core.view.isVisible
import com.google.android.material.progressindicator.BaseProgressIndicator
private const val PROGRESS_MAX = 100
class ProgressChromeClient(
private val progressIndicator: BaseProgressIndicator<*>,
) : WebChromeClient() {
init {
progressIndicator.max = PROGRESS_MAX
}
override fun onProgressChanged(view: WebView?, newProgress: Int) {
super.onProgressChanged(view, newProgress)
if (!progressIndicator.isVisible) {
return
}
if (newProgress in 1 until PROGRESS_MAX) {
progressIndicator.isIndeterminate = false
progressIndicator.setProgressCompat(newProgress.coerceAtMost(PROGRESS_MAX), true)
} else {
progressIndicator.setIndeterminate(true)
}
}
}

View File

@@ -0,0 +1,8 @@
package org.koitharu.kotatsu.browser.cloudflare
interface CloudFlareCallback {
fun onPageLoaded()
fun onCheckPassed()
}

View File

@@ -0,0 +1,45 @@
package org.koitharu.kotatsu.browser.cloudflare
import android.graphics.Bitmap
import android.webkit.WebView
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.koitharu.kotatsu.core.network.AndroidCookieJar
import org.koitharu.kotatsu.core.network.WebViewClientCompat
private const val CF_CLEARANCE = "cf_clearance"
class CloudFlareClient(
private val cookieJar: AndroidCookieJar,
private val callback: CloudFlareCallback,
private val targetUrl: String
) : WebViewClientCompat() {
private val oldClearance = getCookieValue(CF_CLEARANCE)
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
checkClearance()
}
override fun onPageCommitVisible(view: WebView?, url: String?) {
super.onPageCommitVisible(view, url)
callback.onPageLoaded()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
callback.onPageLoaded()
}
private fun checkClearance() {
val clearance = getCookieValue(CF_CLEARANCE)
if (clearance != null && clearance != oldClearance) {
callback.onCheckPassed()
}
}
private fun getCookieValue(name: String): String? {
return cookieJar.loadForRequest(targetUrl.toHttpUrl())
.find { it.name == name }?.value
}
}

View File

@@ -0,0 +1,93 @@
package org.koitharu.kotatsu.browser.cloudflare
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.CookieManager
import android.webkit.WebSettings
import androidx.core.view.isInvisible
import androidx.fragment.app.setFragmentResult
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koin.android.ext.android.get
import org.koitharu.kotatsu.base.ui.AlertDialogFragment
import org.koitharu.kotatsu.core.network.UserAgentInterceptor
import org.koitharu.kotatsu.databinding.FragmentCloudflareBinding
import org.koitharu.kotatsu.utils.ext.stringArgument
import org.koitharu.kotatsu.utils.ext.withArgs
class CloudFlareDialog : AlertDialogFragment<FragmentCloudflareBinding>(), CloudFlareCallback {
private val url by stringArgument(ARG_URL)
private val pendingResult = Bundle(1)
override fun onInflateView(
inflater: LayoutInflater,
container: ViewGroup?
) = FragmentCloudflareBinding.inflate(inflater, container, false)
@SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
with(binding.webView.settings) {
javaScriptEnabled = true
cacheMode = WebSettings.LOAD_DEFAULT
domStorageEnabled = true
databaseEnabled = true
userAgentString = UserAgentInterceptor.userAgent
}
binding.webView.webViewClient = CloudFlareClient(get(), this, url.orEmpty())
CookieManager.getInstance().setAcceptThirdPartyCookies(binding.webView, true)
if (url.isNullOrEmpty()) {
dismissAllowingStateLoss()
} else {
binding.webView.loadUrl(url.orEmpty())
}
}
override fun onDestroyView() {
binding.webView.stopLoading()
super.onDestroyView()
}
override fun onBuildDialog(builder: MaterialAlertDialogBuilder) {
builder.setNegativeButton(android.R.string.cancel, null)
}
override fun onResume() {
super.onResume()
binding.webView.onResume()
}
override fun onPause() {
binding.webView.onPause()
super.onPause()
}
override fun onDismiss(dialog: DialogInterface) {
setFragmentResult(TAG, pendingResult)
super.onDismiss(dialog)
}
override fun onPageLoaded() {
bindingOrNull()?.progressBar?.isInvisible = true
}
override fun onCheckPassed() {
pendingResult.putBoolean(EXTRA_RESULT, true)
dismiss()
}
companion object {
const val TAG = "CloudFlareDialog"
const val EXTRA_RESULT = "result"
private const val ARG_URL = "url"
fun newInstance(url: String) = CloudFlareDialog().withArgs(1) {
putString(ARG_URL, url)
}
}
}

View File

@@ -0,0 +1,17 @@
package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
class BackupEntry(
val name: String,
val data: JSONArray
) {
companion object Names {
const val INDEX = "index"
const val HISTORY = "history"
const val CATEGORIES = "categories"
const val FAVOURITES = "favourites"
}
}

View File

@@ -0,0 +1,134 @@
package org.koitharu.kotatsu.core.backup
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
import org.koitharu.kotatsu.history.data.HistoryEntity
private const val PAGE_SIZE = 10
class BackupRepository(private val db: MangaDatabase) {
suspend fun dumpHistory(): BackupEntry {
var offset = 0
val entry = BackupEntry(BackupEntry.HISTORY, JSONArray())
while (true) {
val history = db.historyDao.findAll(offset, PAGE_SIZE)
if (history.isEmpty()) {
break
}
offset += history.size
for (item in history) {
val manga = item.manga.toJson()
val tags = JSONArray()
item.tags.forEach { tags.put(it.toJson()) }
manga.put("tags", tags)
val json = item.history.toJson()
json.put("manga", manga)
entry.data.put(json)
}
}
return entry
}
suspend fun dumpCategories(): BackupEntry {
val entry = BackupEntry(BackupEntry.CATEGORIES, JSONArray())
val categories = db.favouriteCategoriesDao.findAll()
for (item in categories) {
entry.data.put(item.toJson())
}
return entry
}
suspend fun dumpFavourites(): BackupEntry {
var offset = 0
val entry = BackupEntry(BackupEntry.FAVOURITES, JSONArray())
while (true) {
val favourites = db.favouritesDao.findAll(offset, PAGE_SIZE)
if (favourites.isEmpty()) {
break
}
offset += favourites.size
for (item in favourites) {
val manga = item.manga.toJson()
val tags = JSONArray()
item.tags.forEach { tags.put(it.toJson()) }
manga.put("tags", tags)
val json = item.favourite.toJson()
json.put("manga", manga)
entry.data.put(json)
}
}
return entry
}
fun createIndex(): BackupEntry {
val entry = BackupEntry(BackupEntry.INDEX, JSONArray())
val json = JSONObject()
json.put("app_id", BuildConfig.APPLICATION_ID)
json.put("app_version", BuildConfig.VERSION_CODE)
json.put("created_at", System.currentTimeMillis())
entry.data.put(json)
return entry
}
private fun MangaEntity.toJson(): JSONObject {
val jo = JSONObject()
jo.put("id", id)
jo.put("title", title)
jo.put("alt_title", altTitle)
jo.put("url", url)
jo.put("public_url", publicUrl)
jo.put("rating", rating)
jo.put("nsfw", isNsfw)
jo.put("cover_url", coverUrl)
jo.put("large_cover_url", largeCoverUrl)
jo.put("state", state)
jo.put("author", author)
jo.put("source", source)
return jo
}
private fun TagEntity.toJson(): JSONObject {
val jo = JSONObject()
jo.put("id", id)
jo.put("title", title)
jo.put("key", key)
jo.put("source", source)
return jo
}
private fun HistoryEntity.toJson(): JSONObject {
val jo = JSONObject()
jo.put("manga_id", mangaId)
jo.put("created_at", createdAt)
jo.put("updated_at", updatedAt)
jo.put("chapter_id", chapterId)
jo.put("page", page)
jo.put("scroll", scroll)
return jo
}
private fun FavouriteCategoryEntity.toJson(): JSONObject {
val jo = JSONObject()
jo.put("category_id", categoryId)
jo.put("created_at", createdAt)
jo.put("sort_key", sortKey)
jo.put("title", title)
jo.put("order", order)
return jo
}
private fun FavouriteEntity.toJson(): JSONObject {
val jo = JSONObject()
jo.put("manga_id", mangaId)
jo.put("category_id", categoryId)
jo.put("created_at", createdAt)
return jo
}
}

View File

@@ -0,0 +1,25 @@
package org.koitharu.kotatsu.core.backup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okio.Closeable
import org.json.JSONArray
import java.io.File
import java.util.zip.ZipFile
class BackupZipInput(val file: File) : Closeable {
private val zipFile = ZipFile(file)
suspend fun getEntry(name: String): BackupEntry = runInterruptible(Dispatchers.IO) {
val entry = zipFile.getEntry(name)
val json = zipFile.getInputStream(entry).use {
JSONArray(it.bufferedReader().readText())
}
BackupEntry(name, json)
}
override fun close() {
zipFile.close()
}
}

View File

@@ -0,0 +1,45 @@
package org.koitharu.kotatsu.core.backup
import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import okio.Closeable
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.zip.ZipOutput
import org.koitharu.kotatsu.utils.ext.format
import java.io.File
import java.util.*
import java.util.zip.Deflater
class BackupZipOutput(val file: File) : Closeable {
private val output = ZipOutput(file, Deflater.BEST_COMPRESSION)
suspend fun put(entry: BackupEntry) {
output.put(entry.name, entry.data.toString(2))
}
suspend fun finish() {
output.finish()
}
override fun close() {
output.close()
}
}
private const val DIR_BACKUPS = "backups"
suspend fun BackupZipOutput(context: Context): BackupZipOutput = runInterruptible(Dispatchers.IO) {
val dir = context.run {
getExternalFilesDir(DIR_BACKUPS) ?: File(filesDir, DIR_BACKUPS)
}
dir.mkdirs()
val filename = buildString {
append(context.getString(R.string.app_name).replace(' ', '_').lowercase(Locale.ROOT))
append('_')
append(Date().format("ddMMyyyy"))
append(".bk.zip")
}
BackupZipOutput(File(dir, filename))
}

View File

@@ -0,0 +1,39 @@
package org.koitharu.kotatsu.core.backup
class CompositeResult {
private var successCount: Int = 0
private val errors = ArrayList<Throwable?>()
val size: Int
get() = successCount + errors.size
val failures: List<Throwable>
get() = errors.filterNotNull()
val isAllSuccess: Boolean
get() = errors.none { it != null }
val isAllFailed: Boolean
get() = successCount == 0 && errors.isNotEmpty()
operator fun plusAssign(result: Result<*>) {
when {
result.isSuccess -> successCount++
result.isFailure -> errors.add(result.exceptionOrNull())
}
}
operator fun plusAssign(other: CompositeResult) {
this.successCount += other.successCount
this.errors += other.errors
}
operator fun plus(other: CompositeResult): CompositeResult {
val result = CompositeResult()
result.successCount = this.successCount + other.successCount
result.errors.addAll(this.errors)
result.errors.addAll(other.errors)
return result
}
}

View File

@@ -0,0 +1,114 @@
package org.koitharu.kotatsu.core.backup
import androidx.room.withTransaction
import org.json.JSONObject
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
import org.koitharu.kotatsu.history.data.HistoryEntity
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.util.json.JSONIterator
import org.koitharu.kotatsu.parsers.util.json.getBooleanOrDefault
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSON
class RestoreRepository(private val db: MangaDatabase) {
suspend fun upsertHistory(entry: BackupEntry): CompositeResult {
val result = CompositeResult()
for (item in entry.data.JSONIterator()) {
val mangaJson = item.getJSONObject("manga")
val manga = parseManga(mangaJson)
val tags = mangaJson.getJSONArray("tags").mapJSON {
parseTag(it)
}
val history = parseHistory(item)
result += runCatching {
db.withTransaction {
db.tagsDao.upsert(tags)
db.mangaDao.upsert(manga, tags)
db.historyDao.upsert(history)
}
}
}
return result
}
suspend fun upsertCategories(entry: BackupEntry): CompositeResult {
val result = CompositeResult()
for (item in entry.data.JSONIterator()) {
val category = parseCategory(item)
result += runCatching {
db.favouriteCategoriesDao.upsert(category)
}
}
return result
}
suspend fun upsertFavourites(entry: BackupEntry): CompositeResult {
val result = CompositeResult()
for (item in entry.data.JSONIterator()) {
val mangaJson = item.getJSONObject("manga")
val manga = parseManga(mangaJson)
val tags = mangaJson.getJSONArray("tags").mapJSON {
parseTag(it)
}
val favourite = parseFavourite(item)
result += runCatching {
db.withTransaction {
db.tagsDao.upsert(tags)
db.mangaDao.upsert(manga, tags)
db.favouritesDao.upsert(favourite)
}
}
}
return result
}
private fun parseManga(json: JSONObject) = MangaEntity(
id = json.getLong("id"),
title = json.getString("title"),
altTitle = json.getStringOrNull("alt_title"),
url = json.getString("url"),
publicUrl = json.getStringOrNull("public_url").orEmpty(),
rating = json.getDouble("rating").toFloat(),
isNsfw = json.getBooleanOrDefault("nsfw", false),
coverUrl = json.getString("cover_url"),
largeCoverUrl = json.getStringOrNull("large_cover_url"),
state = json.getStringOrNull("state"),
author = json.getStringOrNull("author"),
source = json.getString("source")
)
private fun parseTag(json: JSONObject) = TagEntity(
id = json.getLong("id"),
title = json.getString("title"),
key = json.getString("key"),
source = json.getString("source")
)
private fun parseHistory(json: JSONObject) = HistoryEntity(
mangaId = json.getLong("manga_id"),
createdAt = json.getLong("created_at"),
updatedAt = json.getLong("updated_at"),
chapterId = json.getLong("chapter_id"),
page = json.getInt("page"),
scroll = json.getDouble("scroll").toFloat()
)
private fun parseCategory(json: JSONObject) = FavouriteCategoryEntity(
categoryId = json.getInt("category_id"),
createdAt = json.getLong("created_at"),
sortKey = json.getInt("sort_key"),
title = json.getString("title"),
order = json.getStringOrNull("order") ?: SortOrder.NEWEST.name,
)
private fun parseFavourite(json: JSONObject) = FavouriteEntity(
mangaId = json.getLong("manga_id"),
categoryId = json.getLong("category_id"),
createdAt = json.getLong("created_at")
)
}

View File

@@ -0,0 +1,9 @@
package org.koitharu.kotatsu.core.db
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val databaseModule
get() = module {
single { MangaDatabase.create(androidContext()) }
}

View File

@@ -4,13 +4,14 @@ import android.content.res.Resources
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.parsers.model.SortOrder
class DatabasePrePopulateCallback(private val resources: Resources) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
db.execSQL(
"INSERT INTO favourite_categories (created_at, sort_key, title) VALUES (?,?,?)",
arrayOf(System.currentTimeMillis(), 1, resources.getString(R.string.read_later))
"INSERT INTO favourite_categories (created_at, sort_key, title, `order`) VALUES (?,?,?,?)",
arrayOf(System.currentTimeMillis(), 1, resources.getString(R.string.read_later), SortOrder.NEWEST.name)
)
}
}

View File

@@ -1,33 +0,0 @@
package org.koitharu.kotatsu.core.db
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import org.koitharu.kotatsu.core.db.entity.FavouriteCategoryEntity
@Dao
abstract class FavouriteCategoriesDao {
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
abstract suspend fun findAll(): List<FavouriteCategoryEntity>
@Insert(onConflict = OnConflictStrategy.ABORT)
abstract suspend fun insert(category: FavouriteCategoryEntity): Long
@Query("DELETE FROM favourite_categories WHERE category_id = :id")
abstract suspend fun delete(id: Long)
@Query("UPDATE favourite_categories SET title = :title WHERE category_id = :id")
abstract suspend fun update(id: Long, title: String)
@Query("UPDATE favourite_categories SET sort_key = :sortKey WHERE category_id = :id")
abstract suspend fun update(id: Long, sortKey: Int)
@Query("SELECT MAX(sort_key) FROM favourite_categories")
protected abstract suspend fun getMaxSortKey(): Int?
suspend fun getNextSortKey(): Int {
return (getMaxSortKey() ?: 0) + 1
}
}

View File

@@ -1,39 +0,0 @@
package org.koitharu.kotatsu.core.db
import androidx.room.*
import org.koitharu.kotatsu.core.db.entity.FavouriteEntity
import org.koitharu.kotatsu.core.db.entity.FavouriteManga
import org.koitharu.kotatsu.core.db.entity.MangaEntity
@Dao
abstract class FavouritesDao {
@Transaction
@Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at")
abstract suspend fun findAll(): List<FavouriteManga>
@Transaction
@Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at LIMIT :limit OFFSET :offset")
abstract suspend fun findAll(offset: Int, limit: Int): List<FavouriteManga>
@Transaction
@Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at")
abstract suspend fun findAll(categoryId: Long): List<FavouriteManga>
@Transaction
@Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at LIMIT :limit OFFSET :offset")
abstract suspend fun findAll(categoryId: Long, offset: Int, limit: Int): List<FavouriteManga>
@Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM favourites)")
abstract suspend fun findAllManga(): List<MangaEntity>
@Transaction
@Query("SELECT * FROM favourites WHERE manga_id = :id GROUP BY manga_id")
abstract suspend fun find(id: Long): FavouriteManga?
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract suspend fun add(favourite: FavouriteEntity)
@Query("DELETE FROM favourites WHERE manga_id = :mangaId AND category_id = :categoryId")
abstract suspend fun delete(categoryId: Long, mangaId: Long)
}

View File

@@ -1,47 +0,0 @@
package org.koitharu.kotatsu.core.db
import androidx.room.*
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
import org.koitharu.kotatsu.core.db.entity.HistoryWithManga
import org.koitharu.kotatsu.core.db.entity.MangaEntity
@Dao
abstract class HistoryDao {
/**
* @hide
*/
@Transaction
@Query("SELECT * FROM history ORDER BY updated_at DESC LIMIT :limit OFFSET :offset")
abstract suspend fun findAll(offset: Int, limit: Int): List<HistoryWithManga>
@Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history)")
abstract suspend fun findAllManga(): List<MangaEntity>
@Query("SELECT * FROM history WHERE manga_id = :id")
abstract suspend fun find(id: Long): HistoryEntity?
@Query("DELETE FROM history")
abstract suspend fun clear()
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract suspend fun insert(entity: HistoryEntity): Long
@Query("UPDATE history SET page = :page, chapter_id = :chapterId, scroll = :scroll, updated_at = :updatedAt WHERE manga_id = :mangaId")
abstract suspend fun update(mangaId: Long, page: Int, chapterId: Long, scroll: Float, updatedAt: Long): Int
@Query("DELETE FROM history WHERE manga_id = :mangaId")
abstract suspend fun delete(mangaId: Long)
suspend fun update(entity: HistoryEntity) = update(entity.mangaId, entity.page, entity.chapterId, entity.scroll, entity.updatedAt)
@Transaction
open suspend fun upsert(entity: HistoryEntity): Boolean {
return if (update(entity) == 0) {
insert(entity)
true
} else false
}
}

View File

@@ -1,15 +1,28 @@
package org.koitharu.kotatsu.core.db
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import org.koitharu.kotatsu.core.db.dao.*
import org.koitharu.kotatsu.core.db.entity.*
import org.koitharu.kotatsu.core.db.migrations.*
import org.koitharu.kotatsu.favourites.data.FavouriteCategoriesDao
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
import org.koitharu.kotatsu.favourites.data.FavouritesDao
import org.koitharu.kotatsu.history.data.HistoryDao
import org.koitharu.kotatsu.history.data.HistoryEntity
import org.koitharu.kotatsu.suggestions.data.SuggestionDao
import org.koitharu.kotatsu.suggestions.data.SuggestionEntity
@Database(
entities = [
MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class,
FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class,
TrackEntity::class, TrackLogEntity::class
], version = 6
TrackEntity::class, TrackLogEntity::class, SuggestionEntity::class
],
version = 9
)
abstract class MangaDatabase : RoomDatabase() {
@@ -28,4 +41,26 @@ abstract class MangaDatabase : RoomDatabase() {
abstract val tracksDao: TracksDao
abstract val trackLogsDao: TrackLogsDao
abstract val suggestionDao: SuggestionDao
companion object {
fun create(context: Context): MangaDatabase = Room.databaseBuilder(
context,
MangaDatabase::class.java,
"kotatsu-db"
).addMigrations(
Migration1To2(),
Migration2To3(),
Migration3To4(),
Migration4To5(),
Migration5To6(),
Migration6To7(),
Migration7To8(),
Migration8To9(),
).addCallback(
DatabasePrePopulateCallback(context.resources)
).build()
}
}

View File

@@ -1,26 +0,0 @@
package org.koitharu.kotatsu.core.db
import androidx.room.*
import org.koitharu.kotatsu.core.db.entity.TagEntity
@Dao
interface TagsDao {
@Query("SELECT * FROM tags")
suspend fun getAllTags(): List<TagEntity>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(tag: TagEntity): Long
@Update(onConflict = OnConflictStrategy.IGNORE)
suspend fun update(tag: TagEntity): Int
@Transaction
suspend fun upsert(tags: Iterable<TagEntity>) {
tags.forEach { tag ->
if (update(tag) <= 0) {
insert(tag)
}
}
}
}

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