Compare commits

..

725 Commits

Author SHA1 Message Date
Aria Moradi cc5a63205c v0.6.4
CI Publish / Validate Gradle Wrapper (push) Successful in 18s
CI Publish / Build Jar (push) Failing after 47s
CI Publish / Make debian-all release (push) Has been skipped
CI Publish / Make linux-assets release (push) Has been skipped
CI Publish / Make linux-x64 release (push) Has been skipped
CI Publish / Make macOS-arm64 release (push) Has been skipped
CI Publish / Make macOS-x64 release (push) Has been skipped
CI Publish / Make windows-x64 release (push) Has been skipped
CI Publish / Make windows-x86 release (push) Has been skipped
CI Publish / release (push) Has been skipped
2022-08-19 00:16:55 +04:30
Aria Moradi 814166a884 Fix mistakes from #384 (#385) 2022-08-10 19:14:16 +04:30
Aria Moradi 55240d9e9b Rename every instance of Tachidesk jar to Tachdidesk-Server.jar (#384) 2022-08-10 18:40:16 +04:30
Mahor 9dc598150f Replace linux-all with linux-assets (#381)
* Move linux package specific files to scripts/resources/pkg

* Replace linux-all with linux-assets

* Fix linux-x64 launchers issue

* Remove -e
2022-08-10 18:20:07 +04:30
Mahor 21c087e273 Tidy up bundler script (#380)
* Tidy up bundler script

* Update paths

* Remove -e

* Revert "Remove -e"

This reverts commit 1e29293dd0148c8aa692004f36b29d7abd9ca0f0.
2022-08-10 18:10:45 +04:30
Mitchell Syer bdf3a7014f Improve DocumentationDsl, bugfix default values and add queryParams (#378)
* Improve DocumentationDsl, bugfix default values and add queryParams

Adding `queryParams<Int>("mangaId[]")` would allow something like this: `http://127.0.0.1:4567/api/v1/download/manga?mangaId[]=1&mangaId[]=2`

* Remove extra comma

* Make QueryParams not nullable and use default value if empty

* Allow nullable again
2022-07-30 17:59:27 +04:30
Mahor dfea6e9b1b Update gradle action (#372)
* Update gradle action

* Update actions in build_pull_request.yml
2022-07-04 23:23:31 -04:00
Mahor 50eef1190e Run workflow jobs toghether (#371)
* Run scripts in parallel

* Re enable deb package builds
2022-07-04 10:06:30 -04:00
Mahor ed180121ff Refactor scripts (#370)
* Rename debian to deb

* Merge scripts into one

* Add error handler

* Disable wine installation to change electron icon due to error

* Replace debuild with dpkg-buildpackage

* Update workflows with new script

* Fix path
2022-07-02 15:42:08 -04:00
Vedant bdb0ad89d4 Publish to Windows Package Managar (WinGet) (#369)
* Update publish.yml

* Create winget.yml

* Update winget.yml

* Update publish.yml

* Update winget.yml
2022-06-30 08:29:23 +04:30
Mahor 7195a30d55 Add linux-all.tar.gz & systemd service (#366)
* Update my email address

* Add systemd configs to debian package

* Add systemd configs

* Tidy up

* Add linux-all.tar.gz

* Rename Tachidesk.jar to tachidesk-server.jar

* Fix typo

* Fix typo
2022-06-16 17:58:31 +04:30
Mitchell Syer 5b0426a94c Docs improvements (#359)
* Use Array since Javalin OpenAPI requires it to read the list generics

* Use custom Pager class for documentation
2022-05-21 14:42:10 +04:30
Mitchell Syer a6d012abd9 Fix documentation errors (#358) 2022-05-20 15:54:06 +04:30
Aria Moradi 86f0b3f29f fix WebUI release name
CI Publish / Validate Gradle Wrapper (push) Successful in 13s
CI Publish / Build artifacts and release (push) Failing after 15s
2022-05-06 20:36:42 +04:30
Aria Moradi 85e3aa34ac bump WebUI 2022-05-06 20:19:11 +04:30
Aria Moradi 5bbc1dedef fix formatting by kotlinter 2022-05-06 17:52:16 +04:30
Aria Moradi 39b468ef06 fix copymanga (#354) 2022-05-06 17:45:05 +04:30
Mitchell Syer fe17176b31 document all endpoints (#350)
* Document all endpoints

* Forgot about global endpoints
2022-04-27 16:01:39 +04:30
abhijeetChawla 84f701c4ab add ChapterCount to manga object in categoryMangas endpoint (#349)
* adds ChapterCount to the Manga returned when accessing the array of Manga is a category

* removed a conflicting expresssion
2022-04-24 13:13:35 +04:30
Mitchell Syer 047f8c176f document manga endpoints (#348) 2022-04-24 13:08:33 +04:30
Mitchell Syer d82e79b680 Add displayValues json field for select filter (#347) 2022-04-24 13:06:19 +04:30
Aria Moradi 320d1ae9d8 add support for alternative web interfaces (#342)
* add support for alternative web interfaces

* fix naming

* won't bundle sorayomi zip

* clean diff
2022-04-16 21:09:36 +04:30
Aria Moradi a8892143a2 fix Applications dir dependency (#344) 2022-04-16 20:58:12 +04:30
Aria Moradi 50f4532406 add support for changing downloads dir (#343) 2022-04-16 20:20:57 +04:30
Fidel Selva 844454053d handle solid RAR archives (#339)
* Upgrade junrar version to 7.5.0 and set unrar.extractor.thread-keep-alive-seconds to 30 (default is 5)

* #338 Read whole archive in case RAR file is solid (it is, it can't be decompressed at an arbitrary location).
2022-04-16 18:24:03 +04:30
Mitchell Syer db5c5ed534 Save categories when manga is unfavorited (#335)
Fixes non-library manga with categories in backups
2022-04-08 06:10:39 +04:30
Aria Moradi a26b8ecca0 v0.6.3 2022-04-07 15:54:42 +04:30
Aria Moradi 5a32ccfa7a fix auth not actually blocking requests (#333) 2022-04-06 21:30:38 +04:30
Mitchell Syer f51818b157 Add QuickJS, replaces Duktape for Extensions Lib 1.3 (#331) 2022-04-02 19:43:45 +04:30
Mitchell Syer 31a624db51 Add last bit of code needed for Extensions Lib 1.3 (#330) 2022-04-02 05:02:26 +04:30
DattatreyaReddy Panta f045b18762 update description for Tachidesk-Sorayomi (#326)
* added Tachidesk-Flutter to readme

* Updated Description for Tachidesk-Sorayomi
2022-03-27 16:41:35 +04:30
Mitchell Syer f5006cac7d Add thumbnail support for stub sources (#320) 2022-03-22 15:51:58 +04:30
Mitchell Syer 152b193ad5 Improve source handling, fix errors with uninitialized mangas in broken sources (#319) 2022-03-22 15:51:07 +04:30
Mitchell Syer a27af0b642 Fix sources list of one source throws an exception (#308) 2022-03-20 19:24:09 +03:30
Aria Moradi 44ffed3f7c add support for tachiyomi extensions Lib 1.3 (#316)
* closes #315

* provide real values

* add support for tachiyomi extensions lib 1.3
2022-03-19 02:36:42 +03:30
Aria Moradi fa035ad9be fix meta update changing all keys (#314) 2022-03-18 00:14:22 +03:30
Mahor 186ace4343 Update README.md (#305)
* Update README.md

* Update README.md again
2022-03-05 09:38:20 +03:30
Aria Moradi 8fb1a0bb1f fix filterlist bugs (#306) 2022-03-05 01:13:48 +03:30
Aria Moradi 05513bf8b9 support array filter changes (#304)
* support array filter changes

* typo

* better formating
2022-03-05 00:06:55 +03:30
Aria Moradi 858784857e v0.6.2
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 15s
2022-03-04 19:03:23 +03:30
Mahor 291a23949a Refactor debian-packager.sh, rename launcher scripts (#303)
* Improve windows-bundler.sh

* Overhaul debian-packager.sh. Rename base package name to tachidesk-server

* Add -electron-launcher-debian.sh
2022-03-03 13:26:56 +03:30
Aria Moradi 454de23844 fix wrong release name
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 15s
2022-02-19 05:38:04 +03:30
Aria Moradi 1176092fc6 v0.6.1 2022-02-19 05:29:46 +03:30
Aria Moradi 0fc2c57395 fix mentions 2022-02-19 05:27:34 +03:30
Aria Moradi 0b292f8d74 update WebUI and CHANGELOG 2022-02-19 05:17:56 +03:30
Aria Moradi 4bbe51331f remove gson (#295)
* remove gson

* also remove kotson

* fix build
2022-02-19 05:12:20 +03:30
Aria Moradi c289786dfa auto-remove duplicate chapters (#294)
* auto-remove duplicate chapters

* Apply suggestions from code review

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>

* Update Chapter.kt

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>
2022-02-19 04:44:17 +03:30
Aria Moradi 9a9752a6a1 no online fetch on backup (#293)
* no online fetch on backup

* Revert "no online fetch on backup"

This reverts commit 09af582b1a3ef77ca62167bc01f7dcc9643329c9.

* alternative solution
2022-02-19 02:57:03 +03:30
DattatreyaReddy Panta c43b688f8e add Tachidesk-Flutter to readme (#292) 2022-02-01 21:52:58 +03:30
Mahor a6272d5221 Improve windows-bundler.sh (#290) 2022-01-22 14:10:10 +03:30
Mahor b440a58d95 Fix build_push.yml Hopefully (#289) 2022-01-18 11:01:39 +03:30
Mahor ec1589aa2d fix Debian package errors (#288)
* Fix lintian errors

Fix lintian errors
Short description in debian/changelog to hide lintian changelog warnings
Use launcher scripts that run java and electron from /usr/bin

* Update changelog version

* Rename laucnher scripts. Put electron installaion guide in electron-launcher-standalone.sh

* Seperate debian packager codes from unix-bundler.sh

* chmod +x debian-packager.sh

* Fix mistakes

* Fix mistakes

* Add missing '!' to shebang

* Change faviconlogo.png to tachidesk.png

* Change faviconlogo.png to tachidesk.png
2022-01-17 18:41:58 +03:30
Mahor 8d48e56fa0 Automated debian package building (#287)
* Automate debian package building

Move wxs files to scripts/resources/msi/
Define icon's path inside script instead of hardcoding it in wxs

* Revert back Windows script improvments

* Remove copyright year. Use uppercase for first letter of foruzesh

* Seperate deb from tar code with defining new debian-x64 arch

* Add ./unix-bundler.sh debian-x64

* Fix mistake

* Remove unneeded change of license
2022-01-16 08:27:59 +03:30
Mahor df7938037e Automated MSI package building (#277)
* Create msi package instead of zipping stuff

* Keep the zip release, Install wixl inside windows-bundler.sh

* Fix mistakes

* Seprate mv command

* Automate versioning

* Fix syntax mistake

* Fix mistake
2022-01-12 23:48:43 +03:30
Mitchell Syer c908ee2d49 Allow app compilation on Java 18+ (#286) 2022-01-09 22:30:10 +03:30
Mitchell Syer b714abddae Handlers must return a result (#282) 2022-01-07 17:03:35 +03:30
Mitchell Syer 63ca189907 Update Gradle and Dependencies (#281) 2022-01-07 17:03:01 +03:30
Aria Moradi 6130fb9ba2 update dex2jar 2021-12-13 17:16:19 +03:30
Aria Moradi f0edc676fc fix compile erorr 2021-12-13 17:16:03 +03:30
Aria Moradi b68fdb0772 ignore non image files (#269)
* ignore non image files

* Update server/src/main/kotlin/eu/kanade/tachiyomi/source/local/LocalSource.kt

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>
2021-12-03 20:53:18 +03:30
Sascha Hahne 76c7bdd604 Add Route to stop and reset the updater (#260) 2021-12-01 23:18:32 +03:30
Mitchell Syer 205101568e Improve documentation with Http codes (#261)
* Improve documentation dsl with Http codes

* Fix plaintext requiring T
2021-12-01 23:17:41 +03:30
Aria Moradi efff68c49b refactor getChapter (#268)
* refactor

* better naming

* fix copytight notice
2021-12-01 22:39:19 +03:30
Aria Moradi f74f60bb1d Update README.md 2021-11-30 11:18:44 +03:30
Aria Moradi 63ea28a620 Update README.md 2021-11-29 20:22:43 +03:30
Aria Moradi 2c6d043277 bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 15s
2021-11-29 19:24:07 +03:30
Aria Moradi 9a226f7b64 update 2021-11-29 19:14:40 +03:30
Aria Moradi 3b73a0fd72 empty searchTerm support (#259)
* linter run

* convert search params to queryParams
2021-11-29 18:42:53 +03:30
Aria Moradi 2478aa77cd add support for MultiSelectListPreference (#258)
* add support for MultiSelectListPreference

* Update AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>

* don't convert to list

* fix by @Syer10

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>
2021-11-28 23:11:56 +03:30
Aria Moradi a41068dbc9 migrate application directories (#255) 2021-11-28 19:56:06 +03:30
Aria Moradi 5e47b7ae6b Update README.md 2021-11-16 21:37:44 +03:30
Aria Moradi debf45a7d5 Update README.md 2021-11-16 21:09:16 +03:30
Aria Moradi e7041e8c8c Fix first page not being detected correctly (#253)
* fix first page not being recognized correctly

* fix first page not being recognized correctly
2021-11-15 23:49:02 +03:30
Aria Moradi bd960992bc cleanup directory names (#251) 2021-11-15 23:40:49 +03:30
Aria Moradi 0c5f6b432c update 2021-11-15 12:22:49 +03:30
Aria Moradi 49232edbd5 update 2021-11-15 12:06:04 +03:30
Mitchell Syer b02884f58d Add a Kotlin DSL for endpoint documentation (#249) 2021-11-14 18:16:39 +03:30
Aria Moradi 845b588426 Mention the existence of Mahor's Tachidesk-GTK 2021-11-13 13:51:20 +03:30
Aria Moradi 3a97d7c8be update 2021-11-13 13:27:17 +03:30
Sascha Hahne 2cb2ded2d9 Implement Update of Library/Category (#235)
* Implement Update Controller tests

* Basic Threading and notify

* WIP

* Reworked using coroutines

* Use Map for JobSummary Tracking

* Change Tests

* Clean up

* Changes based on review

* Rethrow cancellationexception

* Clean up

* Fix Merge Error

* Actually handle messages

* Clean up

* Remove useless annotation
2021-11-10 22:38:41 +03:30
Aria Moradi 14e02bee6c update 2021-11-10 12:17:26 +03:30
Aria Moradi 30f7cdc1ba add pagination to recentChapters (#246)
* add pagination to recentChapters

* Use kotlin native library

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>

Co-authored-by: Mitchell Syer <Mitchellptbo@gmail.com>
2021-11-08 18:45:52 +03:30
Mitchell Syer 420d14fc37 Fix Manga Meta, add Manga Meta test (#245)
* Fix Manga Meta, add Manga Meta test

* Tweak assertion strings
2021-11-08 03:08:22 +03:30
Aria Moradi 3d7953d977 add manga data to download queue object (#244)
* add manga data to download queue object

* fix lint erro
2021-11-07 21:32:57 +03:30
Aria Moradi 35238b3da1 stop supporting zero based image storage (#242)
* stop supporting zero based image storage, closes #210

* add test
2021-11-07 21:27:11 +03:30
Aria Moradi 446f4283e0 Update CONTRIBUTING.md 2021-11-02 15:58:30 +03:30
Aria Moradi 8062dd3709 convert request type 2021-11-02 12:14:44 +03:30
Aria Moradi 41c8fde8c5 ignore build artifacts generated by teting 2021-11-02 12:13:33 +03:30
Aria Moradi d90b986d19 implement Source Filters 2021-11-02 04:15:08 +03:30
Aria Moradi 64ea8416b2 refactor 2021-11-01 23:46:46 +03:30
Aria Moradi 100a4c9d35 refactor 2021-11-01 18:02:06 +03:30
Aria Moradi 4ef6dec89a cleanup 2021-11-01 02:10:51 +03:30
Aria Moradi a14cdc48bd fix credit 2021-11-01 02:09:14 +03:30
Aria Moradi 8a4ddbc6df update 2021-11-01 02:05:02 +03:30
Aria Moradi ee33acc561 allow injecting Sources 2021-10-31 18:05:55 +03:30
Aria Moradi 5fe69becf3 improve tests 2021-10-31 17:31:46 +03:30
Aria Moradi d460d3ccdf change windows bundle names 2021-10-31 14:06:59 +03:30
Sascha Hahne 0ee74943e8 Fix category reorder Endpoint. Added Test for Category Reorder (#232)
* Fix category reorder Endpoint. Added Test for Category Reorder

* Remove streams and use kotlin filtering
2021-10-30 14:46:22 +03:30
Aria Moradi 82837e38d2 update 2021-10-30 14:25:23 +03:30
Sascha Hahne 91df90d760 Fix broken test (#231) 2021-10-29 19:40:20 +03:30
Mitchell Syer 1ee37da720 Fix unread and download counts casing (#230) 2021-10-28 19:11:10 +03:30
Aria Moradi 6f8fc5b69d Update README.md 2021-10-28 12:35:24 +03:30
Sascha Hahne be1918c769 add Cache Header to Thumbnail Response for improved library performance (#228) 2021-10-26 21:46:38 +03:30
Sascha Hahne 0057b35a0a Expose unread and download count of Manga in category api (#227)
* #224 Created view for unread and download badges

* #224 Basic test structure

* Created test and cleaned up a bit

* Move counts to MangaDataClass and delete MangaViewDataClass

* Readded trailing space

* Removed SQL view and calculate with joins now
2021-10-25 13:41:07 +03:30
Sascha Hahne d12974702a Fix tests (#226) 2021-10-24 23:19:27 +03:30
Aria Moradi 921c41689d update 2021-10-24 23:08:56 +03:30
Aria Moradi 6389899507 remove anime support 2021-10-24 22:58:25 +03:30
Aria Moradi 92ede2a2b3 Update README.md 2021-10-24 17:28:02 +03:30
Aria Moradi 826a63ed71 Update README.md 2021-10-24 16:57:06 +03:30
Aria Moradi d1576a2a72 Update README.md 2021-10-24 14:27:12 +03:30
Aria Moradi 95f218d704 Update README.md 2021-10-23 20:36:45 +03:30
Aria Moradi 315d3a0ac0 Update CONTRIBUTING.md 2021-10-23 20:04:10 +03:30
Aria Moradi 954818cef2 Update CONTRIBUTING.md 2021-10-23 20:02:42 +03:30
Aria Moradi 5a95ca9b1b Update CONTRIBUTING.md 2021-10-23 20:00:35 +03:30
Aria Moradi c1e6f4c26e better cleaning algorithm 2021-10-23 19:27:50 +03:30
Aria Moradi 7c603258fb Update README.md 2021-10-21 14:32:58 +03:30
Mahor fcbc582686 Update README.md (#223)
Add PPA's description for Ubuntu-based distributions
2021-10-20 12:15:46 +03:30
Aria Moradi 9c4906b90b cleanup 2021-10-20 08:34:07 +03:30
Aria Moradi d35e31e02d bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 16s
CI Publish / Build artifacts and release (push) Failing after 15s
2021-10-18 14:41:01 +03:30
Aria Moradi 6c4ca36c09 update WebUI 2021-10-18 14:37:13 +03:30
Aria Moradi 70355dc505 update 2021-10-11 00:21:10 +03:30
Aria Moradi 20aeaf2a05 update 2021-10-11 00:18:49 +03:30
Mitchell Syer 1f13e1d08b Use a custom task to run electron (#220) 2021-10-11 00:16:32 +03:30
Aria Moradi eb9d35c123 code cleanup 2021-10-11 00:15:15 +03:30
Mitchell Syer 45808cd530 Support using a CatalogueSource instead of only HttpSources (#219) 2021-10-11 00:01:04 +03:30
Aria Moradi fd715a3f92 fix workflow 2021-10-10 23:52:35 +03:30
Aria Moradi e3b32367a7 update 2021-10-10 23:51:21 +03:30
Aria Moradi bf9554a746 update 2021-10-10 23:32:19 +03:30
Aria Moradi b9f8ca1488 update 2021-10-10 23:01:58 +03:30
Aria Moradi e8c4159678 use correct conversion units 2021-10-10 21:31:38 +03:30
Aria Moradi e57e71629e update 2021-10-10 21:05:24 +03:30
Aria Moradi 2bfd9d24a4 remove isNsfw annotation detection 2021-10-10 21:04:28 +03:30
Aria Moradi b18b8fe22f update 2021-10-10 20:58:10 +03:30
Aria Moradi b154ff2f9d fix export chapter ordering, include new props in backup 2021-10-10 20:53:50 +03:30
Aria Moradi e9b764b63c update 2021-10-10 12:27:50 +03:30
Aria Moradi 7216b97d92 mimic Tachyomi's behaviour more closely, fixes ReadComicOnline (EN) 2021-10-10 12:18:21 +03:30
Aria Moradi 0e9d93b194 prepare CHANGELOG 2021-10-06 21:18:21 +03:30
Aria Moradi 2cbee62f0a update docs 2021-09-28 18:06:20 +03:30
Aria Moradi 379e9da5fe clenup 2021-09-28 18:00:24 +03:30
Aria Moradi ae7caa4901 merge 2021-09-28 17:57:55 +03:30
Aria Moradi cd8b4c9dd7 convert android.jar lib to a maven repo 2021-09-28 17:55:50 +03:30
Aria Moradi 60cd61dfd2 Update README.md 2021-09-28 03:42:20 +03:30
Aria Moradi 5a6637d9fc Update README.md 2021-09-28 03:39:45 +03:30
Aria Moradi dca7ed23f5 Update README.md 2021-09-28 03:36:06 +03:30
Aria Moradi 8cb5791f3b Update README.md 2021-09-28 03:34:14 +03:30
Aria Moradi 9b67f2c58f Update CHANGELOG.md 2021-09-28 03:24:57 +03:30
Aria Moradi 3815810d4f Update for release 2021-09-28 01:11:24 +03:30
Aria Moradi 819ceba17d bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 16s
2021-09-28 00:52:49 +03:30
Aria Moradi 0aa0d62e03 update changelog file and it's template 2021-09-28 00:51:05 +03:30
Aria Moradi b3e2a35880 update WebUI 2021-09-28 00:50:33 +03:30
Aria Moradi 15ec20c65d fix sorting 2021-09-27 20:27:40 +03:30
Aria Moradi d4d6d7e12f add recentChapters endpoint 2021-09-27 18:27:05 +03:30
Aria Moradi 2e7a4f1421 remove no longer relevant comment 2021-09-27 14:44:48 +03:30
Aria Moradi ab8a52faf3 rename ChapterTable.chapterIndex to ChapterTable.sourceOrder 2021-09-27 14:36:06 +03:30
Aria Moradi bd465559fb Update README.md 2021-09-26 23:48:29 +03:30
Aria Moradi 13ec45a95c aftermath of adding kotlinter to all modules 2021-09-25 04:34:02 +03:30
Mitchell Syer 13b034875b Workaround StdLib issue and add KtLint to all modules (#206)
* Workaround buildconfig kotlin stdlib issue

* Add KtLint to all modules
2021-09-25 04:31:03 +03:30
Aria Moradi bb701fb088 fix macOS-arm64 java path 2021-09-24 14:06:19 +03:30
Aria Moradi b367414865 changes 2021-09-24 13:56:26 +03:30
Aria Moradi 4b00eec608 update CHANGELOG 2021-09-19 18:01:13 +04:30
Aria Moradi 5e11b51152 update CHANGELOG 2021-09-19 17:59:37 +04:30
Aria Moradi 9fb43b996e CHANGELOG update 2021-09-19 17:39:28 +04:30
Aria Moradi bc2072e81f bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 13s
CI Publish / Build artifacts and release (push) Failing after 15s
2021-09-19 17:36:46 +04:30
Aria Moradi f36bc3f643 update WebUI 2021-09-19 17:34:18 +04:30
Aria Moradi f7901ad843 fix windows paths 2021-09-19 16:43:16 +04:30
Aria Moradi 3771030ed6 closes #202 2021-09-19 14:24:13 +04:30
Aria Moradi 57197e58b5 fix Task path 2021-09-19 14:14:42 +04:30
Aria Moradi ac601399ac update WebUI 2021-09-19 14:14:21 +04:30
Aria Moradi 6a0e221153 fix compile 2021-09-19 01:01:20 +04:30
Aria Moradi 6a949fc851 Minor cleanup 2021-09-19 00:59:04 +04:30
Aria Moradi f1a077dc2f update CHANGELOG 2021-09-18 22:09:34 +04:30
Mitchell Syer f20962b02b Gradle Updates (#199)
* Cleanup and update gradle, update dependencies

* Duplicate Jsoup
2021-09-18 22:07:19 +04:30
Mitchell Syer 77e057f244 Update BytecodeEditor to use Java NIO Paths (#200) 2021-09-18 21:57:15 +04:30
Aria Moradi 2c5114c770 bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 13s
CI Publish / Build artifacts and release (push) Failing after 16s
2021-09-18 21:07:38 +04:30
Aria Moradi a30895a199 update WebUI 2021-09-18 21:03:01 +04:30
Aria Moradi 6d46d4b3da closes #131 2021-09-18 20:30:56 +04:30
Aria Moradi 006efbbb77 add ChapterRecognition from tachiyomi, closes #10 2021-09-18 19:40:44 +04:30
Aria Moradi 52334087ad add support for Archive chapters to Local source 2021-09-18 19:14:06 +04:30
Aria Moradi ea8fb2c70a add comment 2021-09-18 16:11:25 +04:30
Aria Moradi 531d148718 don't save Local source chapters into disk again! 2021-09-18 14:53:59 +04:30
Aria Moradi d83ddea323 better URLs 2021-09-18 14:49:38 +04:30
Aria Moradi b5dea34090 update WebUI 2021-09-18 02:39:15 +04:30
Aria Moradi 7d8e3202b5 lint 2021-09-18 02:28:52 +04:30
Aria Moradi d956e0af4b add Local Source (#196) 2021-09-18 02:20:30 +04:30
Aria Moradi 9ad70990b5 update WebUI 2021-09-18 02:19:43 +04:30
Aria Moradi 82d711f077 fix typo 2021-09-18 02:19:38 +04:30
Aria Moradi 5fc28ef711 handle when title is changing properly 2021-09-18 02:10:35 +04:30
Aria Moradi 1f3dc682e2 migrate to kotlinx.json 2021-09-18 01:43:10 +04:30
Aria Moradi cce7768246 clean up imports 2021-09-18 01:03:06 +04:30
Aria Moradi 01172b0664 better exception messages 2021-09-18 01:00:42 +04:30
Aria Moradi 1ca11fdd34 add Local Source 2021-09-18 00:47:50 +04:30
Aria Moradi 52a064ae45 lint 2021-09-17 16:32:14 +04:30
Aria Moradi 6c62ddf927 depricate zero based chapters 2021-09-17 16:31:47 +04:30
Aria Moradi 47e04c08d0 fix lint complain 2021-09-17 15:17:18 +04:30
Aria Moradi d1601874b4 [SKIP CI] update CHANGELOG.md 2021-09-17 01:31:13 +04:30
Aria Moradi 6bc19af041 add ability to delete downloaded chapters 2021-09-17 01:29:42 +04:30
Aria Moradi 4e72a3886f actaully make sure the chapter exists 2021-09-17 00:38:15 +04:30
Aria Moradi 8e6b219eea update CHANGELOG.md 2021-09-14 04:18:19 +04:30
Aria Moradi bd638251e4 add BasicAuth support 2021-09-14 04:17:01 +04:30
Aria Moradi 0173d5e4b3 migrate to Javalin 4 2021-09-14 03:23:00 +04:30
Aria Moradi 4f364e134b remove expand char limit on MangaTable columns 2021-09-13 20:57:41 +04:30
Aria Moradi 94d2519717 add CHANGELOG for the next release 2021-09-13 20:14:02 +04:30
Aria Moradi 6a11d2e357 bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build artifacts and release (push) Failing after 16s
2021-09-13 19:32:05 +04:30
Aria Moradi 0a9e0bc9e4 update WebUI 2021-09-13 19:31:07 +04:30
Aria Moradi 5914e367d1 better CHANGELOG 2021-09-13 19:29:54 +04:30
Mitchell Syer aeaed888d4 Update Proto models to match Tachi preview (#192) 2021-09-12 04:04:48 +04:30
Aria Moradi a0f054b005 CHANGELOG.md 2021-09-11 19:47:06 +04:30
Aria Moradi 4498e9d444 beter handling of uninstalling Extensions 2021-09-11 16:26:04 +04:30
Aria Moradi 43e0763fef fix a bug where if two sources return the same URL, a false duplicate might be detected 2021-09-11 14:47:03 +04:30
Aria Moradi a519c8a482 better PR links 2021-09-11 03:18:36 +04:30
Aria Moradi 19bc595a2a update CHANGELOG.md 2021-09-11 03:13:26 +04:30
Aria Moradi db07825c58 remove println instance 2021-09-11 03:09:26 +04:30
Aria Moradi b199e3bf0e fix installing apk with weird name 2021-09-11 01:21:22 +04:30
Aria Moradi 1f9ea0891e add some logging 2021-09-11 00:48:17 +04:30
Aria Moradi 0a7aa48f1e fix apk log and apk name 2021-09-11 00:14:52 +04:30
Aria Moradi 4b65b7da6c rm dummy 2021-09-10 21:42:52 +04:30
Mosei 183a7dac4b Create docker_build_stable (#184)
* Create docker_build_stable

Add docker build workflow

* Rename docker_build_stable to docker_build_stable.yml

* Update docker_build_stable.yml

* Update docker_build_stable.yml
2021-09-10 21:42:31 +04:30
Aria Moradi 6726f008c1 add dummy file to trigger workflow 2021-09-10 21:22:28 +04:30
Mosei 89cf0c140f Update publish.yml (#190) 2021-09-10 20:49:57 +04:30
Mosei 504025ce80 Update build_push.yml (#191) 2021-09-10 20:49:33 +04:30
Aria Moradi fee9e914f1 fix exposed crash 2021-09-10 00:45:00 +04:30
Aria Moradi 76efa71c68 update WebUI 2021-09-09 23:05:58 +04:30
Aria Moradi 26e61959ae update WebUI 2021-09-09 16:46:19 +04:30
Aria Moradi 9a8956ef9d update dependencies 2021-09-09 16:41:41 +04:30
Aria Moradi 10d3ffc2f6 better UX 2021-09-09 06:05:09 +04:30
Aria Moradi 090399f61d add support for installing external APK 2021-09-09 05:22:45 +04:30
Aria Moradi ae7d975a92 run won't get stuck now 2021-09-09 05:15:51 +04:30
Aria Moradi 55ec6bcafe add TODO for changing later 2021-09-09 05:15:08 +04:30
Aria Moradi f0566d15af fix compiler warning 2021-09-08 20:27:29 +04:30
Aria Moradi a730b692bc update WebUI 2021-09-08 20:24:22 +04:30
Aria Moradi 826d767423 [SKIP CI] update CHANGELOG.md 2021-09-08 20:23:45 +04:30
Aria Moradi 6d227c7fcd Fix typo 2021-09-06 22:23:26 +04:30
Aria Moradi 7d9d97840e Update README.md 2021-09-06 14:41:00 +04:30
Mosei 110ded45a0 Update README.md (#189)
Remove depreciated arbuilder’s docker link
2021-09-05 21:16:25 +04:30
Aria Moradi 7872b593c7 Credit to @Syer10 2021-09-05 17:50:45 +04:30
Aria Moradi 90be30bddb add support for the new gnere type in WebUI 2021-09-05 01:40:34 +04:30
Mitchell Syer a298c61dab Change type of Manga.genre to a List<String> (#188) 2021-09-05 01:36:52 +04:30
Aria Moradi eb416c45bd remove not-code changes from CHANGELOG 2021-09-05 00:54:01 +04:30
Aria Moradi b05b817aeb Update README.md 2021-09-03 18:52:06 +04:30
Aria Moradi 666602283a update
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 15s
2021-09-03 07:59:41 +04:30
Aria Moradi ac040a4bae fix oopsies n'shit 2021-09-03 07:57:53 +04:30
Aria Moradi b4982c8f22 update 2021-09-03 07:55:15 +04:30
Aria Moradi ce3ad92095 remove node module cache, won't need it anymore 2021-09-03 07:54:07 +04:30
Aria Moradi 8e1ac8698c bump version 2021-09-03 07:48:31 +04:30
Aria Moradi b60a39c7cb update 2021-09-03 07:46:11 +04:30
Aria Moradi 3b3e8ba4c8 add new unix bundles to release 2021-09-03 07:45:11 +04:30
Aria Moradi e387f6d3be update 2021-09-03 07:44:00 +04:30
Aria Moradi 799d469cb6 bump electron version 2021-09-03 07:43:13 +04:30
Aria Moradi a54a596fa7 fix macOS bundler 2021-09-03 07:39:28 +04:30
Aria Moradi 92d73d0285 add linux and macOS bundler script 2021-09-03 06:50:42 +04:30
Aria Moradi acb752e4e8 update jre 2021-09-03 05:43:33 +04:30
Aria Moradi 9e377abba6 update CHANGELOG 2021-09-03 04:55:01 +04:30
Aria Moradi 04552c0923 update WebUI 2021-09-03 04:52:34 +04:30
Aria Moradi 2e1fb85b73 [skip ci] update changelog 2021-09-03 04:49:38 +04:30
Aria Moradi 50db32d9b4 this is dumb 2021-09-03 04:48:32 +04:30
Aria Moradi 28743d953e [skip ci] r857 2021-09-03 04:41:00 +04:30
Aria Moradi b109d26aa7 fixed typo 2021-09-03 04:39:45 +04:30
Aria Moradi 7fd21bd06d [skip ci] r855 2021-09-02 17:45:52 +04:30
Aria Moradi 12e0ffb466 text cleanup 2021-09-02 17:43:43 +04:30
Aria Moradi 9259341df8 missed this changelog 2021-09-02 17:31:30 +04:30
Aria Moradi 8e8aca7e7b Update CONTRIBUTING.md 2021-09-02 17:29:26 +04:30
Aria Moradi 7f0bcd987b Update CONTRIBUTING.md 2021-09-02 17:24:32 +04:30
Aria Moradi ef21de95cb add continues changelog file 2021-09-02 17:20:53 +04:30
Aria Moradi ca3246de02 bump version 2021-09-02 15:21:27 +04:30
Aria Moradi f0940b7926 bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 15s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-08-31 17:43:23 +04:30
Aria Moradi 0066e0b901 suppress warnings 2021-08-31 17:33:29 +04:30
Aria Moradi 9771f566b0 better comments 2021-08-30 02:48:10 +04:30
Aria Moradi 38ad4c6dec refactor 2021-08-30 02:44:35 +04:30
Aria Moradi 37cf80a188 code cleanup 2021-08-30 02:38:15 +04:30
Aria Moradi c86ee53f66 resolve compiler warnings 2021-08-29 22:25:43 +04:30
Aria Moradi c2cea7e797 can serialize Search Filters 2021-08-29 22:19:44 +04:30
Aria Moradi a8ef6cdd4f change category re-order url 2021-08-29 21:52:23 +04:30
Aria Moradi 53d157fee8 update 2021-08-29 21:47:09 +04:30
Aria Moradi c2e07b13f6 fix categories not being normalized 2021-08-29 20:09:17 +04:30
Aria Moradi 2e8cc48311 update WebUI 2021-08-29 02:11:11 +04:30
Aria Moradi f6f811eb77 update WebUI 2021-08-29 01:59:36 +04:30
Aria Moradi ac5528fb15 add when the statement was true 2021-08-27 04:49:53 +04:30
Aria Moradi 940d2b7862 bump version 2021-08-26 22:31:06 +04:30
Aria Moradi 835fe3dad3 sorround with try, catch as it might throw an exception 2021-08-26 22:24:54 +04:30
Aria Moradi dfaecc08c5 add realUrl to Manga, reperesents open in WebView URL 2021-08-26 22:11:51 +04:30
Aria Moradi 87f5e9b847 fix migration number 2021-08-26 22:10:51 +04:30
Aria Moradi 3d3939e808 better logs 2021-08-26 22:10:27 +04:30
Aria Moradi 90822e3858 merge manga data while restoring backup 2021-08-26 16:28:45 +04:30
Aria Moradi 14eec47e9c correct value for inLibrary 2021-08-26 01:34:56 +04:30
Aria Moradi 15ed3fcc69 actual fix for source order 2021-08-26 01:31:59 +04:30
Aria Moradi fd8fa9f3ef fix chapter restore order 2021-08-26 01:28:42 +04:30
Aria Moradi b81075f4a7 fix docker builds faling? 2021-08-24 22:23:39 +04:30
Aria Moradi f11a52e8e1 we don't need that feild anymore 2021-08-24 22:23:00 +04:30
Aria Moradi 9c007483d4 better method of detemining if a source is Nsfw 2021-08-24 02:44:13 +04:30
Aria Moradi ff4e818e4c add some comments 2021-08-23 21:48:27 +04:30
Aria Moradi 45a50ca0c1 add isNsfw to SourceDataClass 2021-08-23 21:46:28 +04:30
Aria Moradi 65d9021c37 close response 2021-08-23 06:10:31 +04:30
Aria Moradi 66481a0391 NPE fix suggested by @syer10 2021-08-23 06:05:04 +04:30
Aria Moradi a14a82bc9a fix oppsie, sync dependencies with tachiyomi 2021-08-23 05:27:39 +04:30
Aria Moradi 756c57a16e also intercept on 403 2021-08-23 04:56:27 +04:30
Aria Moradi 8b19e34dc5 Update README.md 2021-08-23 04:38:32 +04:30
Aria Moradi 50083019ee add copyright notices 2021-08-23 04:37:30 +04:30
Aria Moradi 155272e638 add new keys 2021-08-23 04:28:07 +04:30
Aria Moradi 08443ceb3d remove comment 2021-08-23 04:20:04 +04:30
Aria Moradi c215696f04 have a lighter log level 2021-08-23 04:17:40 +04:30
Aria Moradi 5ca42bf9b6 make it compile 2021-08-23 04:02:55 +04:30
Aria Moradi 3272b9dec5 add CloudflareInterceptor from TachiWeb-Server 2021-08-23 03:45:10 +04:30
Aria Moradi 2ebd5da4aa bump kotlinter version 2021-08-22 19:00:33 +04:30
Aria Moradi 34f024ace2 migrate dex2jar dependency to @ThexXTURBOXx version 2021-08-21 16:36:34 +04:30
Aria Moradi b31f2d50f6 No more legacy backup 2021-08-21 06:39:12 +04:30
Aria Moradi da44d3b2b4 bump to v0.4.7
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-08-21 06:30:45 +04:30
Aria Moradi 99ec2aca6a update WebUI 2021-08-21 06:27:14 +04:30
Aria Moradi 6c278604ec got rid of legacy backups 2021-08-21 06:23:58 +04:30
Aria Moradi 1e094a467a not TODO 2021-08-21 06:13:55 +04:30
Aria Moradi 978ccfeeba the true commit 2021-08-21 06:12:22 +04:30
Aria Moradi e93d66d8a1 add backup validation endpoints 2021-08-21 06:08:17 +04:30
Aria Moradi c29a749833 proto export support 2021-08-21 05:48:05 +04:30
Aria Moradi b08d5d1261 all forms of Default are illegal 2021-08-21 05:10:09 +04:30
Aria Moradi 9b129789e9 all forms of Default are illegal 2021-08-21 05:05:01 +04:30
Aria Moradi a76a6d2798 creating a categort named Default is illegal 2021-08-21 03:58:46 +04:30
Aria Moradi 086a760378 update WebUI 2021-08-21 03:55:22 +04:30
Aria Moradi f78c8d4fd8 Default is now a category, no more library 2021-08-21 03:54:16 +04:30
Aria Moradi 7b91489997 better print 2021-08-21 01:20:18 +04:30
Aria Moradi 36a8980c95 TODO block no longer relevant 2021-08-21 01:11:47 +04:30
Aria Moradi 7c65640cb7 include extra chapter data in restore 2021-08-21 00:37:50 +04:30
Aria Moradi d70e68495a restoring with clean db and not installed extensions work 2021-08-21 00:18:03 +04:30
Aria Moradi 2586202772 better comments 2021-08-19 21:11:53 +04:30
Aria Moradi b5f771368a put back dex2jar where it should be 2021-08-19 03:15:35 +04:30
Aria Moradi 0c28320ce3 better debug launcher 2021-08-19 02:54:36 +04:30
Aria Moradi c8b4fbc36b new observation 2021-08-19 02:06:48 +04:30
Aria Moradi e9b07849fe move dex2jar to server, lint 2021-08-19 01:47:26 +04:30
Aria Moradi 409260af6f Merge pull request #176 from Suwayomi/protobuf
protobuf backup support
2021-08-19 00:47:32 +04:30
Aria Moradi d3d53d1a4e initial support for portobuf backup 2021-08-19 00:46:45 +04:30
Aria Moradi e2db191f70 consolidate the external backup api 2021-08-18 23:34:39 +04:30
Aria Moradi d61816734d add all proto backup classes we need 2021-08-18 22:58:56 +04:30
Aria Moradi f4dad8058f Merge branch 'master' into protobuf 2021-08-18 21:51:12 +04:30
Aria Moradi 70bdb375c3 Update README.md 2021-08-18 19:10:46 +04:30
Aria Moradi e724ab0a29 Update README.md 2021-08-18 19:10:16 +04:30
Aria Moradi 7d0ee2ac11 Update README.md 2021-08-18 06:17:04 +04:30
Aria Moradi 59b7e852e2 Update README.md 2021-08-18 06:15:44 +04:30
Aria Moradi b2eb1a391d Update README.md 2021-08-18 05:31:34 +04:30
Aria Moradi 9b3aee98d3 Update CONTRIBUTING.md 2021-08-18 05:30:19 +04:30
Aria Moradi 0476f4144c Update CONTRIBUTING.md 2021-08-18 05:29:24 +04:30
Aria Moradi ed77f45fae Update CONTRIBUTING.md 2021-08-18 05:28:26 +04:30
Aria Moradi 0cd529e746 Update CONTRIBUTING.md 2021-08-18 05:26:55 +04:30
Aria Moradi 5969048318 Update README.md 2021-08-18 05:19:42 +04:30
Aria Moradi d1a7f8baa0 Update README.md 2021-08-18 05:04:22 +04:30
Aria Moradi 18dc936002 Update README.md (#177)
* Update README.md

* Update README.md
2021-08-18 04:50:10 +04:30
Aria Moradi b4b7b5d572 bump to v0.4.6
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-08-18 04:29:14 +04:30
Aria Moradi 291c2e692d clean up build.gradle files, move constants to buildSrc 2021-08-18 04:24:58 +04:30
Aria Moradi 8a9a4f21b1 remove some stuff we don't use 2021-08-18 04:06:13 +04:30
Aria Moradi cd31332b39 better download progress 2021-08-18 03:55:52 +04:30
Aria Moradi cc8d2162a0 fix compile issue 2021-08-18 02:59:07 +04:30
Aria Moradi e6313cdc67 yeet improvments from jui 2021-08-18 01:21:17 +04:30
Aria Moradi 5af64892e7 Merge branch 'master' into protobuf 2021-08-18 00:28:42 +04:30
Aria Moradi a5578a7ac7 fix compile warnings 2021-08-17 23:54:02 +04:30
Aria Moradi fcdda6406e update dependencies 2021-08-17 23:53:41 +04:30
Aria Moradi 9bdd9f8aa6 better endpoint urls based on suggestion from @mgn-norm 2021-08-17 21:45:19 +04:30
Aria Moradi f3856f051b protobuf backup endpoints 2021-08-17 20:09:31 +04:30
Aria Moradi d3a6662c60 make it compile 2021-08-15 03:16:13 +04:30
Aria Moradi 5474eddf84 fix some inconsitencies 2021-08-15 02:41:23 +04:30
Aria Moradi b666cd47d4 fix shouldOverwrite 2021-08-15 00:25:08 +04:30
Aria Moradi 8a986383fe fixes #175, better webUI download task 2021-08-14 17:10:41 +04:30
Aria Moradi 9fa17f617e add anime seach functionality 2021-08-11 08:47:07 +04:30
Aria Moradi e46e165704 bump to v0.4.5
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-08-11 00:39:08 +04:30
Aria Moradi a6af423fb4 Merge branch 'master' of github.com:Suwayomi/Tachidesk-Server 2021-08-10 09:42:41 +04:30
Aria Moradi 3397e694c0 sync anime lib implementation with 12 (#133)
* sync anime lib implementation with 11

* fix wrong api

* delete unused classes

* adapt to lib 12

* add LICENSE for eu.kanade.tachiyomi

* changes for lib 12

* update to lib 12

* update webUI
2021-08-10 09:42:14 +04:30
Aria Moradi 77ff82505e fix wrong api 2021-08-10 04:01:08 +04:30
Aria Moradi c3f2838270 fix name tag generator 2021-08-10 03:40:49 +04:30
Aria Moradi aed7f205b6 update webUI 2021-08-10 03:39:36 +04:30
Aria Moradi 95b3587f7a update webUI 2021-08-10 02:04:35 +04:30
Aria Moradi a4baeb995a refactor endpoints to the new styles 2021-08-09 23:18:41 +04:30
Aria Moradi 032ab54206 fix tag generator 2021-08-09 23:18:06 +04:30
Aria Moradi 1f9c1eb1c0 only open browser when appropriate 2021-08-09 07:15:41 +04:30
Aria Moradi a213e568ba update property strings 2021-08-09 06:59:16 +04:30
Aria Moradi 7aeaeb4b86 move copyright notice to it's place 2021-08-09 06:49:12 +04:30
Aria Moradi 81aef4b8fa remove un-used files 2021-08-09 06:48:02 +04:30
Aria Moradi 31f0b6a16c ability to override server.conf with java -D arguments 2021-08-09 06:45:49 +04:30
Aria Moradi 44e3a682fd update Project name 2021-08-09 01:27:09 +04:30
Aria Moradi 70402a6d3a update webUI to r20
CI Publish / Validate Gradle Wrapper (push) Successful in 13s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-08-08 14:18:46 +04:30
Aria Moradi 5c4143224a Bump to v0.4.4 2021-08-08 07:11:03 +04:30
Aria Moradi f943e924f7 Update build_push.yml 2021-08-08 07:00:12 +04:30
Aria Moradi 7d2f542f8a bundle WebUI for stable builds 2021-08-08 06:18:00 +04:30
Aria Moradi fb1f88e971 lint 2021-08-08 05:36:54 +04:30
Aria Moradi f566f13423 launch parameter for Syer 2021-08-08 05:32:14 +04:30
Aria Moradi 0f88baf1c1 download webUI on demand 2021-08-08 05:31:58 +04:30
Aria Moradi a04cbcd814 add webUIEnabled config 2021-08-08 01:11:21 +04:30
Aria Moradi a17d6a2ea4 clean up the after effects of bringing back webUI 2021-08-07 22:52:44 +04:30
Aria Moradi 08f49e0ac4 Revert "changes for the headless Tachidesk"
This reverts commit e575aaf4fb.
2021-08-07 22:37:27 +04:30
Aria Moradi 7787dd1ecc better comments 2021-08-07 22:18:05 +04:30
Aria Moradi 3d0765d4ab posibly fixes #119 2021-08-07 22:01:38 +04:30
Aria Moradi b51651ace4 refactor to fancy migration classes 2021-08-07 21:58:36 +04:30
Aria Moradi 568fa56d59 add suppress unused class warning 2021-08-07 17:15:01 +04:30
Aria Moradi 50dee9251c rename preview repo 2021-08-06 07:22:11 +04:30
Aria Moradi e575aaf4fb changes for the headless Tachidesk 2021-08-06 07:15:38 +04:30
Aria Moradi bdd5caae1a kick webUI out of Tachidesk 2021-08-06 04:55:03 +04:30
Aria Moradi 3af7de3460 partial implementation for Extenstion Preferences 2021-08-06 04:53:53 +04:30
Aria Moradi caa219f8d6 remove not used types 2021-08-06 03:44:54 +04:30
Aria Moradi afabaccf1d implement data store for extension prefs 2021-08-06 03:37:09 +04:30
Aria Moradi 53cc73701c update exposed version 2021-08-05 23:53:45 +04:30
Aria Moradi c69b954ffd move migration lib outside of Tachidesk 2021-08-05 22:53:31 +04:30
Aria Moradi d05c447fe4 refactor and comment 2021-08-05 20:43:08 +04:30
Aria Moradi 5810a24cb0 about api url is changed 2021-08-05 17:12:53 +04:30
Syer10 e04c6a9f4d Update Android jar to API 30 (#172) 2021-08-05 15:13:57 +04:30
Aria Moradi e3a9f7af42 it's named Stable 2021-08-05 06:42:28 +04:30
Aria Moradi 5eb58a73ee check app update api closes #72 2021-08-05 06:39:09 +04:30
Aria Moradi 68ad1f72ce new about url, fix typo 2021-08-05 05:49:18 +04:30
Aria Moradi 704a52d943 separate Global API 2021-08-05 05:40:48 +04:30
Aria Moradi 67ec9ccc4e mark methods as @JsonIgnore to avoid Jackson serializing them 2021-08-05 03:31:32 +04:30
Aria Moradi c7112ec67f mark methods as @JsonIgnore to avoid Jackson serializing them 2021-08-05 03:28:21 +04:30
Aria Moradi 1e1e2034eb Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-08-04 15:36:44 +04:30
Aria Moradi 5f316c6f44 rename to value 2021-08-04 15:36:29 +04:30
KraXen72 0c39718f82 the plural of Manga *is* Mangas don't let anyone tell you otherwise (#168) 2021-08-04 02:03:50 +04:30
Aria Moradi 8a5ac4a0af add better comments 2021-08-01 18:12:49 +04:30
Syer10 492d5f5e84 Fix list preference crashing on set (#166) 2021-08-01 17:13:50 +04:30
Syer10 5a3621fe39 Override getDefaultValueType with values based on the preference (#167) 2021-08-01 17:13:29 +04:30
Syer10 fb862e23e5 Fix main thread scheduler, fixes Komga and LANraragi(not the preferences though) (#165) 2021-07-31 19:43:50 +04:30
Aria Moradi 3d69348301 add comment about which types should be supported 2021-07-31 08:35:56 +04:30
Aria Moradi 30787846a2 sync androidx.preference method signatures with extensions-lib 2021-07-31 08:28:45 +04:30
Aria Moradi 345ca27f85 support ListPreference 2021-07-31 07:59:05 +04:30
Aria Moradi b7a6d6cae8 fix HentaiHand preferences 2021-07-31 07:41:19 +04:30
Aria Moradi dadb686514 refine extension preferences API 2021-07-31 07:24:45 +04:30
Aria Moradi 75f635a28b add configure button to source card 2021-07-31 05:06:46 +04:30
Aria Moradi f2bd5b8149 add text to EditTextPreference 2021-07-31 05:04:30 +04:30
Aria Moradi 6ed4c79ca4 merge missing commit from #163 2021-07-31 04:50:43 +04:30
Aria Moradi 333f954919 hide anime menu stuff 2021-07-31 04:14:48 +04:30
Aria Moradi 2494d0821d ConfigurableExtension(PreferenceScreen) support (#163)
* initial PreferenceScreen support, works with 'NeoXXX Scans' (pt-br)

* convert EditTextPreference to json successfully

* commit what I've got

* bring back the old SharedPreferences for CustomContext, implement Toast

* put back syer's implementation
2021-07-31 03:53:28 +04:30
Aria Moradi e349d0cef3 add pereference change 2021-07-31 03:50:41 +04:30
Aria Moradi eddad2ba89 Merge branch 'preference-screen' of https://github.com/Syer10/Tachidesk into preference-screen 2021-07-31 02:50:20 +04:30
Aria Moradi bfaf88afd6 put back syer's implementation 2021-07-31 02:49:15 +04:30
Syer10 cd59aed8c7 Fix Invalid Type exception 2021-07-30 17:56:12 -04:00
Aria Moradi f18ca5811f bring back the old SharedPreferences for CustomContext, implement Toast 2021-07-31 02:10:48 +04:30
Aria Moradi 1ed9bcf7c8 commit what I've got 2021-07-31 00:41:09 +04:30
Aria Moradi 29a79ab079 dont print manifestXml 2021-07-30 19:00:58 +04:30
Aria Moradi 7c03c73419 convert EditTextPreference to json successfully 2021-07-30 18:48:07 +04:30
Aria Moradi 74f3b9b609 merge master into preference-screen 2021-07-30 16:55:14 +04:30
Aria Moradi a3953d530e make it compile 2021-07-30 16:52:06 +04:30
Aria Moradi 2280e8c725 initial PreferenceScreen support, works with 'NeoXXX Scans' (pt-br) 2021-07-30 15:05:21 +04:30
Syer10 b327df732c Comments, comments, and comments!! And future proofing (#162) 2021-07-30 05:56:13 +04:30
Aria Moradi 21d7cf5d6a prepare for PreferenceScreen support, remove some old depricated android libs 2021-07-30 00:46:45 +04:30
Aria Moradi 5b64bdc5b7 add copyright notices to Syer10's previous PR 2021-07-29 23:26:23 +04:30
Aria Moradi a3a25b6263 move replace classes 2021-07-29 22:59:03 +04:30
Aria Moradi c7611c8024 log data root dir 2021-07-29 22:36:39 +04:30
Aria Moradi f08170504c Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-07-29 22:35:29 +04:30
Syer10 863dccb5ea Modify extension bytecode to fix SimpleDateFormat cannot parse errors (#149)
- Fixes sources like NHentai
- Fixes mass testing
- Cleans up a bit of the build.gradle.kts's
- Fix Tsuki by setting a http.agent system property
2021-07-29 22:21:25 +04:30
Syer10 fc8bb10ca3 Modify extension bytecode to fix SimpleDateFormat cannot parse errors 2021-06-26 12:51:54 -04:00
Syer10 d06c3586fd Fix sources that require the singleton Json object (#147) 2021-06-24 11:37:26 +04:30
Syer10 395989b528 Improve process time for getAndroid.ps1 (#146) 2021-06-23 00:15:39 +04:30
Aria Moradi a325440f24 bump to v0.4.3
CI Publish / Validate Gradle Wrapper (push) Successful in 10s
CI Publish / Build artifacts and release (push) Failing after 22s
2021-06-17 00:28:19 +04:30
Aria Moradi 14072bb5a0 fix manga extensions not loading 2021-06-17 00:26:34 +04:30
Aria Moradi 7fc33ba8db fix cache 2021-06-06 03:19:03 +04:30
Aria Moradi 47e51b6615 fix naming 2021-06-06 03:13:09 +04:30
Aria Moradi 857562eaff add build flexiblity for Equinox 2021-06-06 02:48:26 +04:30
Aria Moradi bace854b50 rm dummy 2021-06-06 02:05:47 +04:30
Aria Moradi e4a404472d Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-06-06 02:05:26 +04:30
Aria Moradi 7bfa215b4c change old paths 2021-06-06 01:52:05 +04:30
Aria Moradi ab7af4b80b fix typo 2021-06-06 01:35:39 +04:30
Aria Moradi 2c7ebd8ece prepare for integration with Equinox 2021-06-06 01:34:49 +04:30
Syer10 c96da79058 Fix MacOS crashing on launch (#132) 2021-06-05 22:36:36 +04:30
Aria Moradi 8f09ebacf5 dummy file to trigger gh actions 2021-06-04 23:10:40 +04:30
Aria Moradi e21f3b9c75 closes #130 2021-06-04 21:51:48 +04:30
Aria Moradi 37eeef06e2 correct spelling 2021-06-04 16:34:19 +04:30
Aria Moradi b7fe56687c Bump styfle/cancel-workflow-action from 0.5.0 to 0.9.0 2021-06-04 13:35:20 +04:30
Aria Moradi 60565729ca lint by linter 2021-06-04 13:35:07 +04:30
Aria Moradi 36f4e1c340 move all packages to 'suwayomi.tachidesk' 2021-06-04 13:08:20 +04:30
Aria Moradi abc2a5214b Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-06-04 10:43:39 +04:30
Aria Moradi a29010e0d7 fix chached image returning file type with extra . 2021-06-04 10:43:03 +04:30
arbuilder db99ab66ae Update build_push.yml (#124)
* Update build_push.yml

docker workflow for preview build

* Update build_push.yml

remove cd master

* Update build_push.yml

Change access token
2021-06-01 13:27:57 +04:30
arbuilder 84cc73c149 Update publish.yml (#123)
* Update publish.yml

add docker build workflow

* Update publish.yml

Remove cd master

* Update publish.yml

Change access token
2021-06-01 13:25:38 +04:30
Aria Moradi 10a29cab33 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-30 04:56:59 +04:30
Aria Moradi 849e2f103a [SKIP CI] download chapters for real now 2021-05-30 04:24:21 +04:30
Syer10 6c22fe193a Add meta info for clients to store custom data in (#113)
* Add meta info for clients to store custom data in

* PR comments

* Really update migration
2021-05-30 04:18:08 +04:30
Syer10 e69dbbf418 Working shared preferences (#112)
* Working shared preferences

* Remove unneeded prefs dir

* Todo
2021-05-30 04:05:56 +04:30
Aria Moradi dfa59a1691 bump version to v0.4.2
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-05-30 04:04:11 +04:30
Aria Moradi 5023e96301 Implemented Dowloads front-end 2021-05-30 04:01:49 +04:30
Aria Moradi 224c24ee9f a little reminder 2021-05-30 02:21:43 +04:30
Aria Moradi e3b154cf9e Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-29 23:59:29 +04:30
Aria Moradi d249867c4c finishing touches of download backend, done @jipfr's requests 2021-05-29 23:57:22 +04:30
Aria Moradi b56045e984 downloader backend done 2021-05-29 23:05:51 +04:30
Manchewable 3777cc646e Improve continuous horizontal reader (#110)
* differentiate ContinuesHorizontalLTR and ContinuesHorizontalRTL

* fix displaying pages in horizontal viewer

* add scroll handler for horizontal mode

* update curPage when images pass through center of the screen

* add click events to navigate pages

* remove console.log

* fix click mapping for ContinuesHorizontalRTL

* remove disable eslint inline comment

* fix ContinuesHorizontalRTL not updating curPage on scroll

* add ability to click to drag

* add margin in between images
2021-05-29 19:41:59 +04:30
Manchewable aa5a1083d0 fit images to height (#108) 2021-05-28 23:27:31 +04:30
Manchewable 2ae5e0742e reference to img elements directly (#106) 2021-05-28 23:25:04 +04:30
Aria Moradi e5e875c54a closes #100 2021-05-28 20:21:05 +04:30
Aria Moradi 1a99ec76e4 spinner image, closes #77 2021-05-28 19:37:26 +04:30
Manchewable 1b122d1157 Add a Double Page Viewer (#105)
* add double page reader

* implement singleRTL

* add on image load handler

* add retry display time interval

* remove comments

* add double page wrapper

* fix image getting out of bounds

* remove comments

* remove unused styles

* return imageStyle as type CSSProperties

* rename DoublePagedReader to DoublePagedPager
2021-05-28 17:06:55 +04:30
Aria Moradi 77f2f8cc18 add copyright notice to files that miss it 2021-05-28 16:23:26 +04:30
Aria Moradi f0a99980b6 fixed issue with clearing up orphan chapters 2021-05-28 03:46:32 +04:30
Aria Moradi b0d43ffe69 anime filter everywhere
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-05-28 03:02:14 +04:30
Aria Moradi 16cb0184a4 fix catalog source imports 2021-05-28 02:53:36 +04:30
Aria Moradi f211a33ea3 bump to v0.4.1 2021-05-28 02:49:01 +04:30
Aria Moradi 440c815189 missed from previous commit 2021-05-28 02:46:19 +04:30
Aria Moradi 25829aacfd new anime library 2021-05-28 02:43:30 +04:30
Aria Moradi 700a739f95 probably fixes http leaks (by @Syer10) 2021-05-27 22:45:44 +04:30
Aria Moradi d9620bec05 fix getManga returning false for inLibrary 2021-05-27 22:30:29 +04:30
Aria Moradi 4b6c51b1f8 bump to v0.4.0
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build artifacts and release (push) Failing after 17s
2021-05-27 19:32:16 +04:30
Aria Moradi bd02edf0b1 barebones anime player 2021-05-27 18:37:45 +04:30
Aria Moradi 5c7123a997 Manga page Finished 2021-05-27 17:13:22 +04:30
Aria Moradi c17e3bd04f can work with anime extensions successfully 2021-05-27 05:13:01 +04:30
Aria Moradi 994ae97256 no dependenct on tachidesk 2021-05-27 03:33:56 +04:30
Aria Moradi 781428a690 add initial anime stuff 2021-05-27 03:25:55 +04:30
Aria Moradi c23ac5faa8 fix compile issue 2021-05-27 02:23:17 +04:30
Aria Moradi e8d41f83c2 move databse to server package, move tables to a better place 2021-05-27 02:21:53 +04:30
Aria Moradi 921a0a3361 Merge branch 'master' into anime 2021-05-27 02:16:07 +04:30
Aria Moradi dda5a2df93 reconsider package strings 2021-05-27 02:13:17 +04:30
Aria Moradi 155f9f107d more of package moving 2021-05-27 02:07:32 +04:30
Aria Moradi 24f68b8f1a move packages 2021-05-27 01:57:40 +04:30
Aria Moradi 0ffbe194fa move packages 2021-05-27 01:57:15 +04:30
Aria Moradi 0b41e2b72b Adapted Tachiyomi-mi extensions-lib implementation 2021-05-27 00:04:33 +04:30
arbuilder ef07b9b4ce [SKIP CI] Update Docker info (#99)
* Update README.md

update docker info

* [SKIP CI] update docker info

* [SKIP CI] Update Readme

change to small case
2021-05-26 11:00:13 +04:30
Aria Moradi f3999cf2d9 [SKIP CI] update docker info 2021-05-26 02:48:13 +04:30
Syer10 1729847937 Allow building without git access (#98)
Just something SY needs...
2021-05-26 02:39:25 +04:30
Aria Moradi 37bff6c76c About Screen 2021-05-25 21:06:27 +04:30
Aria Moradi 4ef32d8037 build type 2021-05-25 19:23:47 +04:30
Aria Moradi d2f6a33f0a fix listener not being removed 2021-05-25 16:19:08 +04:30
Aria Moradi 31d9903251 got rid of all instances of diabling no-unused-vars 2021-05-25 13:24:56 +04:30
Aria Moradi e97642d92a prevPage handle
* go back to previous chapter on page 0 when prevPage is triggered
2021-05-25 13:14:07 +04:30
Aria Moradi c49fc0ff5f only show supported pagers 2021-05-25 13:12:42 +04:30
Aria Moradi deb2ab1ff4 closes #96 2021-05-25 13:12:17 +04:30
Manchewable 23466cf853 Added some key mappings to navigate pages (#95)
* Added some key mappings to navigate pages

* use keyboard event codes

* unused files removed

* use a reference to current page

* fix some bugs with Virtuoso

* add keymapping for space to navigate to next page

* commit my changes

* fix functions not regenerating

* fix partial scroll back to start of page issue

Co-authored-by: Aria Moradi <aria.moradi007@gmail.com>
2021-05-24 23:46:05 +04:30
Aria Moradi 16b34f874d fix some bugs with Virtuoso 2021-05-24 21:26:55 +04:30
Aria Moradi 0e0d08ae5a bump to v0.3.9
CI Publish / Validate Gradle Wrapper (push) Successful in 14s
CI Publish / Build artifacts and release (push) Failing after 19s
2021-05-24 18:32:01 +04:30
Aria Moradi 986b4c2c27 unused files removed 2021-05-24 18:31:39 +04:30
Aria Moradi 0bf9ccfcbd [SKIP CI] fix more typo 2021-05-24 18:22:48 +04:30
Aria Moradi 5e8c47928d [SKIP CI] fix typo 2021-05-24 18:22:16 +04:30
Aria Moradi ffae7f911f [SKIP CI] update windows instructions 2021-05-24 18:21:23 +04:30
Aria Moradi e37fdf6d79 [SKIP CI] update preview link 2021-05-24 17:31:07 +04:30
Aria Moradi b359116745 clean up tests 2021-05-24 17:09:05 +04:30
Aria Moradi 60073aace3 test new publish 2021-05-24 17:04:47 +04:30
Aria Moradi 874b13fa14 test new publish 2021-05-24 17:02:30 +04:30
Aria Moradi b146d1024b test new publish 2021-05-24 16:56:03 +04:30
Aria Moradi 332e95c021 test new publish 2021-05-24 16:52:30 +04:30
Aria Moradi 1f68141df5 test new publish 2021-05-24 16:39:17 +04:30
Aria Moradi dd731cd306 test new publish 2021-05-24 16:34:12 +04:30
Aria Moradi 38d8d03cae test new publish 2021-05-24 16:30:32 +04:30
Aria Moradi ec7d840f37 test new publish 2021-05-24 16:29:03 +04:30
Aria Moradi 2813dbb897 test new publish 2021-05-24 16:27:46 +04:30
Aria Moradi 77d1402b8a test new publish 2021-05-24 16:25:42 +04:30
Aria Moradi 08e8a9d105 Electron launcher 2021-05-24 15:37:25 +04:30
Aria Moradi 71661f70b6 flexible z names 2021-05-24 01:49:42 +04:30
Aria Moradi ac1e79ba83 electron! 2021-05-24 01:39:12 +04:30
Aria Moradi d082809776 prepare for electron 2021-05-24 00:42:25 +04:30
Aria Moradi a458a696db webview starts! 2021-05-23 23:04:02 +04:30
Aria Moradi 75786a91b0 add webview 2021-05-23 22:10:04 +04:30
Aria Moradi 6ddb5db57b use HEAD for counting commits
CI Publish / Validate Gradle Wrapper (push) Successful in 10s
CI Publish / Build artifacts and release (push) Failing after 18s
2021-05-23 18:22:35 +04:30
Aria Moradi 4f70cc9283 bump to v0.3.8 2021-05-23 17:27:33 +04:30
Aria Moradi 23b643d637 set default category when adding new manga 2021-05-23 15:28:46 +04:30
Aria Moradi fdfc256c4d Meaningful icons! 2021-05-23 13:48:02 +04:30
Aria Moradi fba56c1b75 replace win64 exe with @Syer10's MSVC build 2021-05-23 12:48:47 +04:30
Aria Moradi 4743bfacf7 [SKIP CI] removing Swing force fixed it for @nar1n 2021-05-21 16:47:46 +04:30
Aria Moradi 2356537f7c try swing 2021-05-21 15:55:37 +04:30
Aria Moradi fa071aee84 refactor github api 2021-05-20 20:41:00 +04:30
Aria Moradi c00ca23a8b put the comment where it should be 2021-05-20 20:27:22 +04:30
Aria Moradi 733b017936 fix webUI not being copied 2021-05-20 19:51:52 +04:30
Aria Moradi 4147f2e368 better comment 2021-05-20 19:21:30 +04:30
Aria Moradi 154b9992eb rewrite without retrofit and kotlin-serialization 2021-05-20 19:20:07 +04:30
Aria Moradi 88b881b043 get rid of guava 2021-05-20 17:56:33 +04:30
Aria Moradi 5d1491fb8c fix package directive 2021-05-20 16:23:13 +04:30
Aria Moradi 3a33196cf1 cleanup dependencies 2021-05-20 16:22:54 +04:30
Aria Moradi fa8e0478da lint file 2021-05-20 13:50:10 +04:30
Aria Moradi 7e7e069244 - Set log level eairlier
- Set AndroidCompat's data root properly
2021-05-20 13:48:33 +04:30
Aria Moradi 18e0d34af0 [SKIP CI] "improvments" 2021-05-20 10:52:57 +04:30
Aria Moradi 3fe3f35483 better commit messages 2021-05-20 10:33:33 +04:30
Aria Moradi cf8e274883 better use of kotlin DSL 2021-05-20 10:24:33 +04:30
Aria Moradi 10dee8b345 improve downloader 2021-05-20 02:36:20 +04:30
Aria Moradi ae8d30593f lint 2021-05-19 23:05:25 +04:30
Aria Moradi 9cde46b5da Fix chpater names, closes #81 2021-05-19 23:03:40 +04:30
Aria Moradi 8e61632155 open the right ip 2021-05-19 17:40:26 +04:30
Aria Moradi e2c4b4cb57 handle when the user runs the app instead of clicking on systemtray 2021-05-19 17:38:33 +04:30
Aria Moradi 326da504ea fix gradle complaning about lint tasks depending on webUI:copyBuild 2021-05-19 17:03:12 +04:30
Aria Moradi c5874a3f10 better chapter looks 2021-05-19 16:50:48 +04:30
Aria Moradi 02802fab97 Application mutex 2021-05-19 16:36:17 +04:30
Aria Moradi 29dea10be2 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-19 13:42:59 +04:30
Aria Moradi 6bc36193dc open server's location please! 2021-05-19 13:42:18 +04:30
Syer10 81e123388e Fix restore crashing (#90) 2021-05-19 05:29:44 +04:30
Aria Moradi 8ebd7869a5 [SKIP CI] name em 2021-05-19 04:30:21 +04:30
Aria Moradi 7a2f5f13f1 [SKIP CI] name em 2021-05-19 04:28:57 +04:30
Aria Moradi 25d7dad39f build the ref that you have been given! 2021-05-19 04:26:20 +04:30
Aria Moradi c8f8795920 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-19 03:57:27 +04:30
Aria Moradi 84206a7074 bump to v0.3.7
CI Publish / Validate Gradle Wrapper (push) Successful in 13s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-19 03:52:55 +04:30
Aria Moradi 6fd8b36dca [SKIP CI] links to the new preview repo 2021-05-19 03:45:24 +04:30
Aria Moradi d1500baae1 try with access token 2021-05-19 03:21:47 +04:30
Aria Moradi 045801dd1a push to Suwayomi/Tachidesk-preview 2021-05-19 02:56:46 +04:30
Aria Moradi 14a2cbc793 [SKIP CI] fix typo 2021-05-19 02:52:28 +04:30
Aria Moradi fd385017df [SKIP CI] fix typo 2021-05-19 02:50:22 +04:30
Aria Moradi 9b05954cf2 [SKIP CI] fix typo 2021-05-19 02:49:10 +04:30
Aria Moradi 6aaf636069 [SKIP CI] update for new scripts 2021-05-19 02:47:48 +04:30
Aria Moradi d30e89e5ec update workflows to include both 32-bit and 64-bit windows bundles 2021-05-19 02:42:14 +04:30
Aria Moradi 7acc745478 Merge the two windows bundlers 2021-05-19 02:31:56 +04:30
Aria Moradi 5a9a2d816e 32-bit variant of bundler 2021-05-19 02:26:29 +04:30
Aria Moradi 105f11ed02 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-19 00:28:56 +04:30
Aria Moradi 3021437a05 new preview system! 2021-05-19 00:28:14 +04:30
Aria Moradi 439602fc03 [SKIP CI] no more preview 2021-05-18 23:42:43 +04:30
Aria Moradi 34e13b9589 [SKIP CI] improve wording... 2021-05-18 23:28:59 +04:30
Aria Moradi 2aab4ae918 [SKIP CI] asking for help! 2021-05-18 23:27:14 +04:30
Aria Moradi 7ef67671a4 print tachidesk info on startup 2021-05-18 22:36:41 +04:30
Syer10 e8df84416c Smarter Chapters and cleanup (#87)
* Smarter Chapters and cleanup

* Fix check
2021-05-18 22:22:15 +04:30
Aria Moradi be930bb68b update to the new scheme 2021-05-18 22:03:18 +04:30
Aria Moradi db52948865 update windows instructions 2021-05-18 21:42:30 +04:30
Aria Moradi d2a72526f6 bump to v0.3.6
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-18 21:40:42 +04:30
Aria Moradi 0a9f57b32b cleanup 2021-05-18 21:38:41 +04:30
Aria Moradi 180f210536 update windows instructions 2021-05-18 21:35:57 +04:30
Aria Moradi c1baa31eed the new and simple way of packaging windows 2021-05-18 21:31:25 +04:30
Aria Moradi cacc97cec7 bump to v0.3.5
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-18 02:39:00 +04:30
Aria Moradi d5691fd81c show last read page on initial load 2021-05-18 02:26:45 +04:30
Aria Moradi 49dc9fe5f6 fix wrong chapter count, abstract next page 2021-05-18 01:10:28 +04:30
Aria Moradi c0b49c7428 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-18 00:45:42 +04:30
Aria Moradi fa345af42d use Dispatchers.IO 2021-05-18 00:43:32 +04:30
Aria Moradi db3cc786a1 rename the job 2021-05-18 00:43:21 +04:30
Aria Moradi fe879ae51d [SKIP CI] update windows instructions 2021-05-18 00:01:04 +04:30
Aria Moradi 2f55460ffb unzip the jre
CI Publish / Validate Gradle Wrapper (push) Successful in 14s
CI Publish / Build FatJar (push) Failing after 17s
2021-05-17 23:33:54 +04:30
Aria Moradi fbc5bd4642 bump to v0.3.4 2021-05-17 23:29:36 +04:30
Aria Moradi 5e0c7d3c9d ditch packr because it can't load extension jars 2021-05-17 23:28:23 +04:30
Aria Moradi 083996a48d wating on: https://github.com/Kotlin/kotlinx.coroutines/issues/261
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 17s
2021-05-17 14:30:59 +04:30
Aria Moradi 9d38f478e3 fix slow manga thumbnails issue, next manga reset page issue 2021-05-17 14:22:24 +04:30
Aria Moradi 57274a0a01 remove unused electron script 2021-05-17 12:32:15 +04:30
Aria Moradi b3b56b7fc8 also build windows package for publish 2021-05-17 12:30:15 +04:30
Forgenn 0b690577da Load next chapter when getting to the last page (#84)
* Load next chapter when scrolling to the bottom (Webtoon, Continues Vertical)

* Load next chapter when scrolling to the bottom (Paged reader)

* Added missing types to IReaderProps

* Move load next chapter when at last page to VerticalReader

* Dependency fix

* Use react history for loading next page
2021-05-17 12:27:14 +04:30
Aria Moradi e9683a3a37 bump to v0.3.3 2021-05-17 12:02:01 +04:30
Aria Moradi f8f67b3eba finish up 2021-05-17 11:59:59 +04:30
Aria Moradi 7b16b082d8 needs kt 2021-05-17 11:55:49 +04:30
Aria Moradi 2a783f0d8e btter folder name 2021-05-17 11:54:33 +04:30
Aria Moradi 42ae32de33 give the correct path 2021-05-17 11:40:38 +04:30
Aria Moradi cec7ddc486 update file permissions 2021-05-17 11:28:26 +04:30
Aria Moradi 9c55fc3868 make windows package with packr 2021-05-17 11:20:24 +04:30
Syer10 104c5a8d83 Code cleanup (#85)
* GC Unused or only used once objects

* Move things around a bit

* Revert some changes

* Fix imports

* Revert about change

* Put back logger

* Private logger

* Revert systemtray

* Move import
2021-05-17 02:48:01 +04:30
Aria Moradi 7450b16742 - Reader -> Pager
- add cloneObject
- add missing copyright notices
2021-05-17 01:38:59 +04:30
Aria Moradi 3ecd0931a1 missing from the previous commit 2021-05-17 01:37:25 +04:30
Aria Moradi 2f2a52ae2f Move navbars 2021-05-17 01:36:31 +04:30
Aria Moradi f464087c30 also handle Errors from java 2021-05-16 23:58:32 +04:30
Aria Moradi 2364960388 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-16 22:15:35 +04:30
Aria Moradi 76be4d64cd update launch4j's jre and make it 64bit 2021-05-16 12:39:05 +04:30
Aria Moradi 7d98e8ce47 [SKIP CI] correct link 2021-05-16 01:53:35 +04:30
Aria Moradi 40831fc681 [SKIP CI] new links 2021-05-16 01:52:01 +04:30
Aria Moradi e38e7ccf26 [SKIP CI] troubleshooting from the wiki 2021-05-16 01:48:49 +04:30
Aria Moradi 98b9e2f2cf [SKIP CI] no need to delete data anymore... 2021-05-16 01:47:33 +04:30
Aria Moradi 4bf3c12f76 fixed when spinner stops just after first offline chapter fetch 2021-05-16 01:07:48 +04:30
Aria Moradi bab25f9ad9 bump version
CI Publish / Validate Gradle Wrapper (push) Successful in 12s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-15 23:24:25 +04:30
Aria Moradi a62ee8f8c3 handle reader types 2021-05-15 23:22:37 +04:30
Aria Moradi 5f23691e20 add toast lib 2021-05-15 20:37:07 +04:30
Aria Moradi 3de9ccc62f stop spinning if chapter list is empty 2021-05-15 18:51:38 +04:30
Aria Moradi 1896f7f37b remove lazy load 2021-05-15 18:26:40 +04:30
Aria Moradi 490643dc02 proof of concept readers 2021-05-15 18:17:12 +04:30
Aria Moradi 9808976088 restructure the reader 2021-05-15 17:18:57 +04:30
Aria Moradi 5a73068a10 bump to v0.3.1
CI Publish / Validate Gradle Wrapper (push) Successful in 17s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-15 14:53:44 +04:30
Aria Moradi 01d5c2540d chapter updates when pressing UI buttons 2021-05-15 13:43:26 +04:30
Aria Moradi 866b01f865 support bookmarked and isRead in webUI 2021-05-14 19:22:10 +04:30
Aria Moradi da6a953099 exposed error 2021-05-14 17:31:07 +04:30
Aria Moradi bce8d58845 make it look nicer? 2021-05-14 02:01:28 +04:30
Aria Moradi 3cfce2db04 fix chapters not shown on movbile 2021-05-13 21:40:42 +04:30
Aria Moradi 327aae5dd9 Merge pull request #79 from Suwayomi/read-category
Support more chapter parameters
2021-05-13 18:34:27 +04:30
Aria Moradi 1bdfde7032 no longer TODO 2021-05-13 18:33:24 +04:30
Aria Moradi 295a0817b0 fix wrong chapters being removed, fix da css 2021-05-13 18:29:20 +04:30
Aria Moradi a02dc02d52 remove console prints 2021-05-13 17:49:33 +04:30
Aria Moradi dc012edf7d staisfying results? with chapters scrolling 2021-05-13 17:46:40 +04:30
Aria Moradi 1e2eb11c13 update dependencies 2021-05-13 15:01:37 +04:30
Aria Moradi 3a825f4f25 fix manga thumbnail loading bug 2021-05-12 10:39:21 +04:30
Aria Moradi b9ea8c5f74 code cleanup 2021-05-12 10:20:01 +04:30
Aria Moradi 320d7e2536 reformat 2021-05-11 18:55:09 +04:30
Aria Moradi c200785479 handle front, handle orphans 2021-05-11 18:45:53 +04:30
Aria Moradi 8abb132ad6 chapter new parameters get endpoint 2021-05-11 15:50:18 +04:30
Aria Moradi 8bb2269f36 [SKIP CI] fix typo 2021-05-08 20:33:53 +04:30
Aria Moradi 9d17b26283 [SKIP CI] up for debate 2021-05-07 19:41:34 +04:30
Aria Moradi 5909f15db7 [SKIP CI] code of conduct 2021-05-07 19:39:24 +04:30
Aria Moradi 11672ca576 [SKIP CI] 2021-05-07 19:35:11 +04:30
Aria Moradi e09773def3 [SKIP CI] potential contributors 2021-05-07 19:32:32 +04:30
Aria Moradi f6d4432e6f [SKIP CI] typo 2021-05-07 19:13:48 +04:30
Aria Moradi 45a6abc5c2 [SKIP CI] improve structure 2021-05-07 19:13:04 +04:30
Aria Moradi dc5e677a38 [SKIP CI] simplify 2021-05-07 19:05:11 +04:30
Aria Moradi a82549dc17 [SKIP CI] why a web app? 2021-05-07 19:02:56 +04:30
Aria Moradi a002e19d9d [SKIP CI] move info to CONTRIBUTING.md 2021-05-07 18:58:09 +04:30
Aria Moradi cdf1f98d28 [SKIP CI] move troubleshooting to wiki 2021-05-07 18:51:47 +04:30
Aria Moradi 0ff1ebdeb7 [SKIP CI] not alternative 2021-05-07 18:36:32 +04:30
Aria Moradi 17f4a396f8 [SKIP CI] one must know friend from foe! 2021-05-07 18:29:01 +04:30
Aria Moradi 8aa3cf4368 [SKIP CI] move stuff around 2021-05-07 18:27:10 +04:30
Aria Moradi 0136c5e493 [SKIP CI] alternative ui projects 2021-05-07 18:21:32 +04:30
Aria Moradi 8b94b9ee80 [SKIP CI] add contributing.md 2021-05-07 18:17:55 +04:30
Aria Moradi bed63f19f2 [SKIP CI] move technical info to contributing.md 2021-05-07 18:04:51 +04:30
Aria Moradi e2a6545a84 [SKIP CI] 2021-05-07 15:28:30 +04:30
Aria Moradi e3d3ec6895 fix sed output 2021-05-07 14:41:19 +04:30
Aria Moradi 7ba476bd79 include v 2021-05-07 14:39:15 +04:30
Aria Moradi 2dd41ebd27 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-07 14:25:11 +04:30
Aria Moradi 038df78171 new preview version format 2021-05-07 14:24:28 +04:30
Aria Moradi 6e5ff2b508 [SKIP CI] it be "chrome OS" 2021-05-07 13:45:31 +04:30
Aria Moradi ec8d1e8680 [SKIP CI] more housekeeping! 2021-05-07 13:42:02 +04:30
Aria Moradi 1f0f0c33b7 [SKIP CI] housekeeping 2021-05-07 13:32:42 +04:30
Aria Moradi 825940fcac [SKIP CI] add running instructions 2021-05-07 13:17:15 +04:30
Aria Moradi 4618834af2 [SKIP CI] Make it simpler 2021-05-07 11:24:40 +04:30
Aria Moradi 55d968df5e [SKIP CI] add some doc comments 2021-05-06 23:06:35 +04:30
Aria Moradi 63a078cf7d Add migrations (#76)
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-06 18:46:12 +04:30
Aria Moradi 5304917e53 fix multiple version warning 2021-05-06 14:14:04 +04:30
Aria Moradi 831b74d2ec bintray is dead 2021-05-06 13:07:40 +04:30
Aria Moradi 1bad9dcd69 [SKIP CI] 2021-05-05 15:54:05 +04:30
Aria Moradi dd43716851 [SKIP CI] more info 2021-05-05 15:26:52 +04:30
Aria Moradi f2e55e95a2 reaffirmation of what Tachidesk is for some Twitter users... 2021-05-05 15:22:46 +04:30
Aria Moradi 14658a0c4d be fancy about the manifest info 😎 2021-05-04 00:15:31 +04:30
Aria Moradi 4195e7056b fix windowsPackge not building the jar 2021-05-03 23:51:48 +04:30
Aria Moradi 1d29e8b248 fix webUI not working with gradle 7.0 2021-05-03 23:21:37 +04:30
Syer10 b718c718df Download directly to file instead of a dir (#70) 2021-05-03 23:00:18 +04:30
Aria Moradi a3601cf1b5 fix pull request build 2021-05-03 22:57:54 +04:30
Aria Moradi 0236a9639b rename vals, comments 2021-05-03 22:30:43 +04:30
Syer10 5f4c7454ee Update everything (#68)
* Update everything, cleanup build.gradle.kts's

* Make requested changes
2021-05-03 22:19:09 +04:30
Aria Moradi 773120c96a make the app build 2021-05-03 20:50:09 +04:30
Aria Moradi 4b273c6bf9 add a bit of docs 2021-05-03 20:48:29 +04:30
Aria Moradi b626aa66ba Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-03 20:41:46 +04:30
Syer10 1dd029559e Stop Javalin properly on shutdown (#69) 2021-05-03 20:40:02 +04:30
Aria Moradi 59cbe5d5bc [SKIP CI] Yes, we do use git 2021-04-30 06:15:56 +04:30
Aria Moradi 40d1173653 put DBManager where it should be 2021-04-30 06:10:41 +04:30
Aria Moradi bf6a0aba5d Rework the version endpoint 2021-04-30 06:07:29 +04:30
Kolby Moroz Liebl 34d8feacdd Add version api endpoint (#66) 2021-04-30 05:47:23 +04:30
Kolby Moroz Liebl 1ea821584c [SKIP CI] Remove IE Requirement in ps1 script (#65) 2021-04-29 01:52:24 +04:30
Aria Moradi 3d2fee19bb refactor 2021-04-28 10:25:01 +04:30
Forgenn 449d12779a Truncate manga description if it's too long (#63)
* Manga description changed from 4096 to 8192

* Check that the description of a manga is not longer than 4096, trim otherwise

* Revert description length changes
2021-04-28 09:50:56 +04:30
Aria Moradi 6fb6a251e7 [SKIP CI] latest pointer link 2021-04-18 20:52:59 +04:30
Aria Moradi 4d6220f894 dir pointer 2021-04-18 20:45:15 +04:30
Aria Moradi fe747bfc52 [SKIP CI] fix link 2021-04-18 20:14:17 +04:30
Aria Moradi 0c2d038870 [SKIP CI] add logo back 2021-04-18 20:05:58 +04:30
Aria Moradi 4e3f73af75 fix string 2021-04-18 19:58:07 +04:30
Aria Moradi 63e5e1b45f add indexer 2021-04-18 19:50:26 +04:30
Aria Moradi 2e1558bd96 [SKIP CI] fix discord links, again 2021-04-18 19:40:25 +04:30
Aria Moradi 0671dee8b2 [SKIP CI] fix discord link 2021-04-18 19:38:43 +04:30
Aria Moradi 8f91b8089a [SKIP CI] fix preview 2021-04-18 19:38:05 +04:30
Aria Moradi 009b45f676 [SKIP CI] discord? 2021-04-18 19:26:28 +04:30
Aria Moradi 8f7d5eb311 [SKIP CI] badges 2021-04-18 19:22:25 +04:30
Aria Moradi f3de835ef3 Update build_push.yml 2021-04-18 18:51:58 +04:30
Aria Moradi fd6662f428 bring back the old licenses 2021-04-18 17:48:42 +04:30
Aria Moradi fde137b3ed restore categories 2021-04-18 12:40:09 +04:30
Aria Moradi a1349aa0e3 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-04-18 11:54:44 +04:30
Aria Moradi c9ef5f9b9d lint meh 2021-04-18 11:50:02 +04:30
Aria Moradi 8fbf564177 also backup chapter and category data 2021-04-18 11:48:14 +04:30
Aria Moradi ae0b1a818c [SKIP CI] update troubleshooting guide 2021-04-15 15:57:42 +04:30
379 changed files with 14727 additions and 25445 deletions
+3 -2
View File
@@ -9,7 +9,7 @@
# Gradle wrapper
*.jar binary
# Images
# Binary files types
*.webp binary
*.png binary
*.jpg binary
@@ -24,4 +24,5 @@
*.woff binary
*.pyc binary
*.swp binary
*.pdf binary
*.pdf binary
*.exe binary
-20
View File
@@ -1,20 +0,0 @@
#!/bin/bash
cp master/server/build/Tachidesk-*.jar preview
cd preview
new_jar_build=$(ls *.jar| tail -1)
echo "last jar build file name: $new_jar_build"
cp -f $new_jar_build Tachidesk-latest.jar
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git status
if [ -n "$(git status --porcelain)" ]; then
git add .
git commit -m "Update preview repository"
git push
else
echo "No changes to commit"
fi
+9 -24
View File
@@ -10,27 +10,27 @@ jobs:
steps:
- name: Clone repo
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
build:
name: Build FatJar
name: Build pull request
needs: check_wrapper
if: "!startsWith(github.event.head_commit.message, '[SKIP CI]')"
runs-on: ubuntu-latest
steps:
- name: Cancel previous runs
uses: styfle/cancel-workflow-action@0.5.0
uses: styfle/cancel-workflow-action@0.10.0
with:
access_token: ${{ github.token }}
- name: Checkout master branch
- name: Checkout pull request
uses: actions/checkout@v2
with:
ref: master
ref: ${{ github.event.pull_request.head.sha }}
path: master
fetch-depth: 0
@@ -45,24 +45,9 @@ jobs:
mkdir -p ~/.gradle
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
- name: Download android.jar
run: |
cd master
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
- name: Cache node_modules
uses: actions/cache@v2
with:
path: |
**/react/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
- name: Build and copy webUI, Build Jar and launch4j
uses: eskatos/gradle-command-action@v1
- name: Build Jar
uses: gradle/gradle-build-action@v2
with:
build-root-directory: master
wrapper-directory: master
arguments: :webUI:copyBuild :server:windowsPackage --stacktrace
wrapper-cache-enabled: true
dependencies-cache-enabled: true
configuration-cache-enabled: true
arguments: :server:shadowJar --stacktrace
+154 -32
View File
@@ -1,4 +1,4 @@
name: CI build master
name: CI build
on:
push:
@@ -9,28 +9,26 @@ jobs:
check_wrapper:
name: Validate Gradle Wrapper
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
build:
name: Build FatJar
name: Build Jar
needs: check_wrapper
if: "!startsWith(github.event.head_commit.message, '[SKIP CI]')"
runs-on: ubuntu-latest
steps:
- name: Cancel previous runs
uses: styfle/cancel-workflow-action@0.5.0
uses: styfle/cancel-workflow-action@0.10.0
with:
access_token: ${{ github.token }}
- name: Checkout master branch
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: master
path: master
@@ -47,34 +45,158 @@ jobs:
mkdir -p ~/.gradle
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
- name: Download android.jar
run: |
cd master
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
- name: Cache node_modules
uses: actions/cache@v2
with:
path: |
**/react/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
- name: Build and copy webUI, Build Jar and launch4j
uses: eskatos/gradle-command-action@v1
- name: Build Jar
uses: gradle/gradle-build-action@v2
env:
ProductBuildType: "Preview"
with:
build-root-directory: master
wrapper-directory: master
arguments: :webUI:copyBuild :server:windowsPackage --stacktrace
wrapper-cache-enabled: true
dependencies-cache-enabled: true
configuration-cache-enabled: true
arguments: :server:shadowJar --stacktrace
- name: Checkout preview branch
uses: actions/checkout@v2
- name: Upload Jar
uses: actions/upload-artifact@v3
with:
ref: preview
path: preview
name: jar
path: master/server/build/*.jar
if-no-files-found: error
- name: Deploy preview
- name: Upload icons
uses: actions/upload-artifact@v3
with:
name: icon
path: master/server/src/main/resources/icon
if-no-files-found: error
- name: Tar scripts dir to maintain file permissions
run: tar -cvzf scripts.tar.gz -C master/ scripts/
- name: Upload scripts.tar.gz
uses: actions/upload-artifact@v3
with:
name: scripts
path: scripts.tar.gz
if-no-files-found: error
bundle:
strategy:
fail-fast: false
matrix:
os:
- debian-all
- linux-assets
- linux-x64
- macOS-x64
- macOS-arm64
- windows-x64
- windows-x86
name: Make ${{ matrix.os }} release
needs: build
runs-on: ubuntu-latest
steps:
- name: Download Jar
uses: actions/download-artifact@v3
with:
name: jar
path: server/build
- name: Download icons
uses: actions/download-artifact@v3
with:
name: icon
path: server/src/main/resources/icon
- name: Download scripts.tar.gz
uses: actions/download-artifact@v3
with:
name: scripts
- name: Make ${{ matrix.os }} release
run: |
./master/.github/scripts/commit-repo.sh
mkdir upload
tar -xvpf scripts.tar.gz
scripts/bundler.sh -o upload/ ${{ matrix.os }}
- name: Upload ${{ matrix.os }} release
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}
path: upload/*
if-no-files-found: error
release:
needs: bundle
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: jar
path: release
- uses: actions/download-artifact@v3
with:
name: debian-all
path: release
- uses: actions/download-artifact@v3
with:
name: linux-assets
path: release
- uses: actions/download-artifact@v3
with:
name: linux-x64
path: release
- uses: actions/download-artifact@v3
with:
name: macOS-x64
path: release
- uses: actions/download-artifact@v3
with:
name: macOS-arm64
path: release
- uses: actions/download-artifact@v3
with:
name: windows-x64
path: release
- uses: actions/download-artifact@v3
with:
name: windows-x86
path: release
- name: Checkout Preview branch
uses: actions/checkout@v3
with:
repository: "Suwayomi/Tachidesk-Server-preview"
ref: main
path: preview
token: ${{ secrets.DEPLOY_PREVIEW_TOKEN }}
- name: Generate Tag Name
id: GenTagName
run: |
cd release
genTag=$(ls *.jar | sed -e's/Tachidesk-Server-\|.jar//g')
echo "$genTag"
echo "::set-output name=value::$genTag"
- name: Create Tag
run: |
TAG="${{ steps.GenTagName.outputs.value }}"
echo "tag: $TAG"
cd preview
echo "{ \"latest\": \"$TAG\" }" > index.json
git add index.json
git config --global user.email \
"github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git commit -m "Updated to $TAG"
git push origin main
git tag $TAG
git push origin $TAG
- name: Upload Preview Release
uses: softprops/action-gh-release@v1
with:
token: ${{ secrets.DEPLOY_PREVIEW_TOKEN }}
repository: "Suwayomi/Tachidesk-Server-preview"
tag_name: ${{ steps.GenTagName.outputs.value }}
files: release/*
+15
View File
@@ -0,0 +1,15 @@
name: Docker Build Stable
on:
release:
types: [published]
jobs:
build_publish_docker_container:
runs-on: ubuntu-latest
steps:
- name: run docker build and publish script
run: |
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.DEPLOY_PREVIEW_TOKEN }}" -d '{"ref":"main", "inputs":{"tachidesk_release_type": "stable"}}' https://api.github.com/repos/suwayomi/docker-tachidesk/actions/workflows/build_container_images.yml/dispatches
+130 -66
View File
@@ -1,37 +1,36 @@
name: CI Publish
on:
workflow_dispatch:
push:
tags:
- 'v*'
- "v*"
jobs:
check_wrapper:
name: Validate Gradle Wrapper
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
build:
name: Build FatJar
name: Build Jar
needs: check_wrapper
runs-on: ubuntu-latest
steps:
- name: Cancel previous runs
uses: styfle/cancel-workflow-action@0.5.0
uses: styfle/cancel-workflow-action@0.10.0
with:
access_token: ${{ github.token }}
- name: Checkout master branch
uses: actions/checkout@v2
- name: Checkout ${{ github.ref }}
uses: actions/checkout@v3
with:
ref: master
ref: ${{ github.ref }}
path: master
fetch-depth: 0
@@ -44,66 +43,131 @@ jobs:
run: |
cd master
mkdir -p ~/.gradle
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
cp .github/runner-files/ci-gradle.properties \
~/.gradle/gradle.properties
- name: Download android.jar
run: |
cd master
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
- name: Cache node_modules
uses: actions/cache@v2
with:
path: |
**/react/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- name: Build and copy webUI, Build Jar and launch4j
uses: eskatos/gradle-command-action@v1
- name: Build and copy webUI, Build Jar
uses: gradle/gradle-build-action@v2
env:
ProductBuildType: "Stable"
with:
build-root-directory: master
wrapper-directory: master
arguments: :webUI:copyBuild :server:windowsPackage --stacktrace
wrapper-cache-enabled: true
dependencies-cache-enabled: true
configuration-cache-enabled: true
arguments: :server:downloadWebUI :server:shadowJar --stacktrace
- name: Upload Release
uses: xresloader/upload-to-github-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Jar
uses: actions/upload-artifact@v3
with:
file: "master/server/build/*.jar;master/server/build/*-win32.zip"
tags: true
draft: true
verbose: true
name: jar
path: master/server/build/*.jar
if-no-files-found: error
# - name: Create Release
# id: create_release
# uses: actions/create-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: ${{ github.ref }}
# release_name: Release ${{ github.ref }}
# body: |
# Release body
# draft: false
# prerelease: true
#
# - name: Get the Ref
# id: get-ref
# uses: ankitvgupta/ref-to-tag-action@master
# with:
# ref: ${{ github.ref }}
# head_ref: ${{ github.head_ref }}
#
# - name: Get the tag
# run: echo "The tag was ${{ steps.get-ref.outputs.tag }}"
#
# - name: Upload Release
# uses: AButler/upload-release-assets@v2.0
# with:
# files: 'master/repo/*'
# repo-token: ${{ secrets.GITHUB_TOKEN }}
# release-tag: ${{ steps.get-ref.outputs.tag }}
- name: Upload icons
uses: actions/upload-artifact@v3
with:
name: icon
path: master/server/src/main/resources/icon
if-no-files-found: error
- name: Tar scripts dir to maintain file permissions
run: tar -cvzf scripts.tar.gz -C master/ scripts/
- name: Upload scripts.tar.gz
uses: actions/upload-artifact@v3
with:
name: scripts
path: scripts.tar.gz
if-no-files-found: error
bundle:
strategy:
fail-fast: false
matrix:
os:
- debian-all
- linux-assets
- linux-x64
- macOS-x64
- macOS-arm64
- windows-x64
- windows-x86
name: Make ${{ matrix.os }} release
needs: build
runs-on: ubuntu-latest
steps:
- name: Download Jar
uses: actions/download-artifact@v3
with:
name: jar
path: server/build
- name: Download icons
uses: actions/download-artifact@v3
with:
name: icon
path: server/src/main/resources/icon
- name: Download scripts.tar.gz
uses: actions/download-artifact@v3
with:
name: scripts
- name: Make ${{ matrix.os }} release
run: |
mkdir upload/
tar -xvpf scripts.tar.gz
scripts/bundler.sh -o upload/ ${{ matrix.os }}
- name: Upload ${{ matrix.os }} files
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.os }}
path: upload/*
if-no-files-found: error
release:
if: startsWith(github.ref, 'refs/tags/v')
needs: bundle
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
name: jar
path: release
- uses: actions/download-artifact@v3
with:
name: debian-all
path: release
- uses: actions/download-artifact@v3
with:
name: linux-assets
path: release
- uses: actions/download-artifact@v3
with:
name: linux-x64
path: release
- uses: actions/download-artifact@v3
with:
name: macOS-x64
path: release
- uses: actions/download-artifact@v3
with:
name: macOS-arm64
path: release
- uses: actions/download-artifact@v3
with:
name: windows-x64
path: release
- uses: actions/download-artifact@v3
with:
name: windows-x86
path: release
- name: Generate checksums
run: cd release && sha256sum * > Checksums.sha256
- name: Release
uses: softprops/action-gh-release@v1
with:
token: ${{ secrets.WINGET_PUBLISH_PAT }}
draft: true
files: release/*
+12
View File
@@ -0,0 +1,12 @@
name: Publish to WinGet
on:
release:
types: [released]
jobs:
publish:
runs-on: windows-latest # action can only be run on windows
steps:
- uses: vedantmgoyal2009/winget-releaser@latest
with:
identifier: Suwayomi.Tachidesk-Server
token: ${{ secrets.WINGET_PUBLISH_PAT }}
+14 -4
View File
@@ -1,11 +1,21 @@
# Ignore Gradle project-specific cache directory
# Ignore project-specific local files and dirs
.gradle
.idea
gradle.properties
# But we need these
!.idea/runConfigurations
# Ignore Gradle build output directory
build
server/out
AndroidCompat/out
server/src/main/resources/react
server/tmp/
server/tachiserver-data/
# WebUI is either to be downloaded on-demand or is a dynamic build asset
server/src/main/resources/WebUI.zip
# bundling stage downlaoded assets
scripts/OpenJDK*
scripts/zulu*
scripts/electron-*
scripts/rcedit-*
-4
View File
@@ -1,4 +0,0 @@
dependencies {
// Config API, moved to the global build.gradle
// implementation("com.typesafe:config:1.4.0")
}
@@ -1,18 +1,20 @@
package xyz.nulldev.ts.config
import net.harawata.appdirs.AppDirsFactory
/*
* Copyright (C) Contributors to the Suwayomi project
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import net.harawata.appdirs.AppDirsFactory
const val CONFIG_PREFIX = "suwayomi.tachidesk.config"
val ApplicationRootDir: String
get(): String {
return System.getProperty(
"ir.armor.tachidesk.rootDir",
AppDirsFactory.getInstance().getUserDataDir("Tachidesk", null, null)
"$CONFIG_PREFIX.server.rootDir",
AppDirsFactory.getInstance().getUserDataDir("Tachidesk", null, null)
)
}
}
@@ -6,7 +6,7 @@ import org.kodein.di.singleton
class ConfigKodeinModule {
fun create() = DI.Module("ConfigManager") {
//Config module
// Config module
bind<ConfigManager>() with singleton { GlobalConfigManager }
}
}
}
@@ -7,6 +7,7 @@ package xyz.nulldev.ts.config
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import ch.qos.logback.classic.Level
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions
@@ -20,7 +21,7 @@ open class ConfigManager {
private val generatedModules = mutableMapOf<Class<out ConfigModule>, ConfigModule>()
val config by lazy { loadConfigs() }
//Public read-only view of modules
// Public read-only view of modules
val loadedModules: Map<Class<out ConfigModule>, ConfigModule>
get() = generatedModules
@@ -34,27 +35,40 @@ open class ConfigManager {
/**
* Get a config module (Java API)
*/
@Suppress("UNCHECKED_CAST")
fun <T : ConfigModule> module(type: Class<T>): T = loadedModules[type] as T
/**
* Load configs
*/
fun loadConfigs(): Config {
//Load reference configs
val compatConfig = ConfigFactory.parseResources("compat-reference.conf")
// Load reference configs
val compatConfig = ConfigFactory.parseResources("compat-reference.conf")
val serverConfig = ConfigFactory.parseResources("server-reference.conf")
val baseConfig =
ConfigFactory.parseMap(
mapOf(
"androidcompat.rootDir" to "$ApplicationRootDir/android-compat" // override AndroidCompat's rootDir
)
)
//Load user config
// Load user config
val userConfig =
File(ApplicationRootDir, "server.conf").let {
ConfigFactory.parseFile(it)
}
val config = ConfigFactory.empty()
.withFallback(userConfig)
.withFallback(compatConfig)
.withFallback(serverConfig)
.resolve()
.withFallback(baseConfig)
.withFallback(userConfig)
.withFallback(compatConfig)
.withFallback(serverConfig)
.resolve()
// set log level early
if (debugLogsEnabled(config)) {
setLogLevel(Level.DEBUG)
}
logger.debug {
"Loaded config:\n" + config.root().render(ConfigRenderOptions.concise().setFormatted(true))
@@ -1,8 +1,44 @@
package xyz.nulldev.ts.config
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import com.typesafe.config.Config
import io.github.config4k.getValue
import kotlin.reflect.KProperty
/**
* Abstract config module.
*/
@Suppress("UNUSED_PARAMETER")
abstract class ConfigModule(config: Config)
/**
* Abstract jvm-commandline-argument-overridable config module.
*/
abstract class SystemPropertyOverridableConfigModule(config: Config, moduleName: String) : ConfigModule(config) {
val overridableConfig = SystemPropertyOverrideDelegate(config, moduleName)
}
/** Defines a config property that is overridable with jvm `-D` commandline arguments prefixed with [CONFIG_PREFIX] */
class SystemPropertyOverrideDelegate(val config: Config, val moduleName: String) {
inline operator fun <R, reified T> getValue(thisRef: R, property: KProperty<*>): T {
val configValue: T = config.getValue(thisRef, property)
val combined = System.getProperty(
"$CONFIG_PREFIX.$moduleName.${property.name}",
configValue.toString()
)
return when (T::class.simpleName) {
"Int" -> combined.toInt()
"Boolean" -> combined.toBoolean()
// add more types as needed
else -> combined // covers String
} as T
}
}
@@ -0,0 +1,20 @@
package xyz.nulldev.ts.config
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import ch.qos.logback.classic.Level
import com.typesafe.config.Config
import mu.KotlinLogging
import org.slf4j.Logger
fun setLogLevel(level: Level) {
(KotlinLogging.logger(Logger.ROOT_LOGGER_NAME).underlyingLogger as ch.qos.logback.classic.Logger).level = level
}
fun debugLogsEnabled(config: Config) =
System.getProperty("suwayomi.tachidesk.config.server.debugLogsEnabled", config.getString("server.debugLogsEnabled")).toBoolean()
@@ -3,4 +3,4 @@ package xyz.nulldev.ts.config.util
import com.typesafe.config.Config
operator fun Config.get(key: String) = getString(key)
?: throw IllegalStateException("Could not find value for config entry: $key!")
?: throw IllegalStateException("Could not find value for config entry: $key!")
@@ -1 +0,0 @@
xyz.nulldev.ts.api.v2.java.impl.ServerAPIImpl
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because one or more lines are too long
@@ -1,22 +0,0 @@
[
{
"label": "Sync",
"icon": "import_export",
"type": "nested",
"prefs": []
},
{
"label": "Server",
"icon": "dns",
"type": "nested",
"prefs": [
{
"label": "Password authentication",
"type": "text-password",
"default": "",
"key": "pref_ts_server_password",
"hint": "Enter a password"
}
]
}
]
+14 -49
View File
@@ -1,63 +1,28 @@
plugins {
application
}
repositories {
mavenCentral()
jcenter()
maven {
url = uri("https://jitpack.io")
}
maven {
url = uri("https://maven.google.com")
}
}
dependencies {
// Android stub library
implementation(fileTree("lib/"))
// Android JAR libs
// compileOnly( fileTree(dir: new File(rootProject.rootDir, "libs/other"), include: "*.jar")
// JSON
compileOnly( "com.google.code.gson:gson:2.8.6")
// Javassist
compileOnly( "org.javassist:javassist:3.27.0-GA")
implementation("com.github.Suwayomi:android-jar:1.0.0")
// XML
compileOnly( group= "xmlpull", name= "xmlpull", version= "1.1.3.1")
compileOnly("xmlpull:xmlpull:1.1.3.4a")
// Config API
implementation(project(":AndroidCompat:Config"))
// APK sig verifier
compileOnly("com.android.tools.build:apksig:4.2.0-alpha13")
compileOnly("com.android.tools.build:apksig:7.1.0-beta05")
// AndroidX annotations
compileOnly( "androidx.annotation:annotation:1.2.0-alpha01")
compileOnly("androidx.annotation:annotation:1.3.0")
// substitute for duktape-android
// 'org.mozilla:rhino' includes some code that we don't need so use 'org.mozilla:rhino-runtime' instead
implementation("org.mozilla:rhino-runtime:1.7.13")
// 'org.mozilla:rhino-engine' provides the same interface as 'javax.script' a.k.a Nashorn
implementation("org.mozilla:rhino-engine:1.7.13")
}
implementation("org.mozilla:rhino-runtime:1.7.14") // slimmer version of 'org.mozilla:rhino'
implementation("org.mozilla:rhino-engine:1.7.14") // provides the same interface as 'javax.script' a.k.a Nashorn
//def fatJarTask = tasks.getByPath(':AndroidCompat:JVMPatch:fatJar')
//
//// Copy JVM core patches
//task copyJVMPatches(type: Copy) {
// from fatJarTask.outputs.files
// into 'src/main/resources/patches'
//}
//
//compileOnly(Java.dependsOn gradle.includedBuild('dex2jar').task(':dex-translator:assemble')
//compileOnly(Java.dependsOn copyJVMPatches
//copyJVMPatches.dependsOn fatJarTask
//
// Kotlin wrapper around Java Preferences, makes certain things easier
val multiplatformSettingsVersion = "0.8.1"
implementation("com.russhwolf:multiplatform-settings-jvm:$multiplatformSettingsVersion")
implementation("com.russhwolf:multiplatform-settings-serialization-jvm:$multiplatformSettingsVersion")
// Android version of SimpleDateFormat
implementation("com.ibm.icu:icu4j:70.1")
}
+15 -8
View File
@@ -15,7 +15,7 @@ Write-Output "Getting required Android.jar..."
Remove-Item -Recurse -Force "tmp" -ErrorAction SilentlyContinue | Out-Null
New-Item -ItemType Directory -Force -Path "tmp" | Out-Null
$androidEncoded = (Invoke-WebRequest -Uri "https://android.googlesource.com/platform/prebuilts/sdk/+/3b8a524d25fa6c3d795afb1eece3f24870c60988/27/public/android.jar?format=TEXT").content
$androidEncoded = (Invoke-WebRequest -Uri "https://android.googlesource.com/platform/prebuilts/sdk/+/6cd31be5e4e25901aadf838120d71a79b46d9add/30/public/android.jar?format=TEXT" -UseBasicParsing).content
$android_jar = (Get-Location).Path + "\tmp\android.jar"
@@ -24,7 +24,7 @@ $android_jar = (Get-Location).Path + "\tmp\android.jar"
# We need to remove any stub classes that we have implementations for
Write-Output "Patching JAR..."
function Remove-Files-Zip($zipfile, $path)
function Remove-Files-Zip($zipfile, $paths)
{
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression') | Out-Null
@@ -32,7 +32,18 @@ function Remove-Files-Zip($zipfile, $path)
$mode = [IO.Compression.ZipArchiveMode]::Update
$zip = New-Object IO.Compression.ZipArchive($stream, $mode)
($zip.Entries | Where-Object { $_.FullName -like $path }) | ForEach-Object { Write-Output "Deleting: $($_.FullName)"; $_.Delete() }
if ($paths.getType().Name -eq "Object[]")
{
$paths | ForEach-Object {
$path = $_
($zip.Entries | Where-Object { $_.FullName -like $path }) | ForEach-Object { Write-Output "Deleting: $($_.FullName)"; $_.Delete() }
}
}
else
{
($zip.Entries | Where-Object { $_.FullName -like $paths }) | ForEach-Object { Write-Output "Deleting: $($_.FullName)"; $_.Delete() }
}
$zip.Dispose()
$stream.Close()
@@ -78,16 +89,12 @@ function Dedupe($path)
$classes = Get-ChildItem . *.* -Recurse | Where-Object { !$_.PSIsContainer }
$classes | ForEach-Object {
"Processing class: $($_.FullName)"
Remove-Files-Zip $android_jar "$($_.Name).class" | Out-Null
Remove-Files-Zip $android_jar "$($_.Name)$*.class" | Out-Null
Remove-Files-Zip $android_jar "$($_.Name)Kt.class" | Out-Null
Remove-Files-Zip $android_jar "$($_.Name)Kt$*.class" | Out-Null
Remove-Files-Zip $android_jar ("$($_.Name).class","$($_.Name)$*.class","$($_.Name)Kt.class","$($_.Name)Kt$*.class") | Out-Null
}
Pop-Location
}
Dedupe "AndroidCompat/src/main/java"
Dedupe "server/src/main/java"
Dedupe "server/src/main/kotlin"
Write-Output "Copying Android.jar to library folder..."
+8 -11
View File
@@ -13,14 +13,14 @@ do
which $dep >/dev/null 2>&1 || { echo >&2 "Error: This script needs $dep installed."; abort=yes; }
done
if [ $abort = yes ]; then
if [ "$abort" = yes ]; then
echo "Some of the dependencies didn't exist. Aborting."
exit 1
fi
# foolproof against running from AndroidCompat dir instead of running from project root
if [ "$(basename $(pwd))" = "AndroidCompat" ]; then
if [ "$(basename "$(pwd)")" = "AndroidCompat" ]; then
cd ..
fi
@@ -30,7 +30,7 @@ rm -rf "tmp"
mkdir -p "tmp"
pushd "tmp"
curl "https://android.googlesource.com/platform/prebuilts/sdk/+/3b8a524d25fa6c3d795afb1eece3f24870c60988/27/public/android.jar?format=TEXT" | base64 --decode > android.jar
curl "https://android.googlesource.com/platform/prebuilts/sdk/+/6cd31be5e4e25901aadf838120d71a79b46d9add/30/public/android.jar?format=TEXT" | base64 --decode > android.jar
# We need to remove any stub classes that we have implementations for
echo "Patching JAR..."
@@ -59,7 +59,7 @@ zip --delete android.jar javax/*
echo "Removing java..."
zip --delete android.jar java/*
echo "Removing overriden classes..."
echo "Removing overridden classes..."
zip --delete android.jar android/app/Application.class
zip --delete android.jar android/app/Service.class
zip --delete android.jar android/net/Uri.class
@@ -68,12 +68,12 @@ zip --delete android.jar android/os/Environment.class
zip --delete android.jar android/text/format/Formatter.class
zip --delete android.jar android/text/Html.class
# Dedup overriden Android classes
# Dedup overridden Android classes
ABS_JAR="$(realpath android.jar)"
function dedup() {
pushd "$1"
CLASSES="$(find * -type f)"
echo "$CLASSES" | while read class
CLASSES="$(find ./* -type f)"
echo "$CLASSES" | while read -r class
do
NAME="${class%.*}"
echo "Processing class: $NAME"
@@ -82,13 +82,10 @@ function dedup() {
popd
}
pushd ..
popd
dedup AndroidCompat/src/main/java
dedup server/src/main/java
dedup server/src/main/kotlin
popd
popd
echo "Copying Android.jar to library folder..."
mv tmp/android.jar AndroidCompat/lib
-1
View File
@@ -1 +0,0 @@
android.jar
@@ -9,8 +9,10 @@ import android.content.Context
class PreferenceManager {
companion object {
@JvmStatic
fun getDefaultSharedPreferences(context: Context)
= context.getSharedPreferences(context.applicationInfo.packageName,
Context.MODE_PRIVATE)!!
fun getDefaultSharedPreferences(context: Context) =
context.getSharedPreferences(
context.applicationInfo.packageName,
Context.MODE_PRIVATE
)!!
}
}
@@ -1,291 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 android.support.v4.content;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.StatFs;
import android.support.v4.os.EnvironmentCompat;
import java.io.File;
/**
* Helper for accessing features in {@link android.content.Context}
* introduced after API level 4 in a backwards compatible fashion.
*/
public class ContextCompat {
/**
* Start a set of activities as a synthesized task stack, if able.
*
* <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
* app navigation using the back key changed. The back key's behavior is local
* to the current task and does not capture navigation across different tasks.
* Navigating across tasks and easily reaching the previous task is accomplished
* through the "recents" UI, accessible through the software-provided Recents key
* on the navigation or system bar. On devices with the older hardware button configuration
* the recents UI can be accessed with a long press on the Home key.</p>
*
* <p>When crossing from one task stack to another post-Android 3.0,
* the application should synthesize a back stack/history for the new task so that
* the user may navigate out of the new task and back to the Launcher by repeated
* presses of the back key. Back key presses should not navigate across task stacks.</p>
*
* <p>startActivities provides a mechanism for constructing a synthetic task stack of
* multiple activities. If the underlying API is not available on the system this method
* will return false.</p>
*
* @param context Start activities using this activity as the starting context
* @param intents Array of intents defining the activities that will be started. The element
* length-1 will correspond to the top activity on the resulting task stack.
* @return true if the underlying API was available and the call was successful, false otherwise
*/
public static boolean startActivities(Context context, Intent[] intents) {
return startActivities(context, intents, null);
}
/**
* Start a set of activities as a synthesized task stack, if able.
*
* <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
* app navigation using the back key changed. The back key's behavior is local
* to the current task and does not capture navigation across different tasks.
* Navigating across tasks and easily reaching the previous task is accomplished
* through the "recents" UI, accessible through the software-provided Recents key
* on the navigation or system bar. On devices with the older hardware button configuration
* the recents UI can be accessed with a long press on the Home key.</p>
*
* <p>When crossing from one task stack to another post-Android 3.0,
* the application should synthesize a back stack/history for the new task so that
* the user may navigate out of the new task and back to the Launcher by repeated
* presses of the back key. Back key presses should not navigate across task stacks.</p>
*
* <p>startActivities provides a mechanism for constructing a synthetic task stack of
* multiple activities. If the underlying API is not available on the system this method
* will return false.</p>
*
* @param context Start activities using this activity as the starting context
* @param intents Array of intents defining the activities that will be started. The element
* length-1 will correspond to the top activity on the resulting task stack.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* @return true if the underlying API was available and the call was successful, false otherwise
*/
public static boolean startActivities(Context context, Intent[] intents,
Bundle options) {
context.startActivities(intents, options);
return true;
}
/**
* Returns absolute paths to application-specific directories on all
* external storage devices where the application's OBB files (if there are
* any) can be found. Note if the application does not have any OBB files,
* these directories may not exist.
* <p>
* This is like {@link Context#getFilesDir()} in that these files will be
* deleted when the application is uninstalled, however there are some
* important differences:
* <ul>
* <li>External files are not always available: they will disappear if the
* user mounts the external storage on a computer or removes it.
* <li>There is no security enforced with these files.
* </ul>
* <p>
* External storage devices returned here are considered a permanent part of
* the device, including both emulated external storage and physical media
* slots, such as SD cards in a battery compartment. The returned paths do
* not include transient devices, such as USB flash drives.
* <p>
* An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to write to the returned paths; they're always accessible to
* the calling app. Before then,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
* write. Write access outside of these paths on secondary external storage
* devices is not available. To request external storage access in a
* backwards compatible way, consider using {@code android:maxSdkVersion}
* like this:
*
* <pre class="prettyprint">&lt;uses-permission
* android:name="android.permission.WRITE_EXTERNAL_STORAGE"
* android:maxSdkVersion="18" /&gt;</pre>
* <p>
* The first path returned is the same as {@link Context#getObbDir()}.
* Returned paths may be {@code null} if a storage device is unavailable.
*
* @see Context#getObbDir()
* @see EnvironmentCompat#getStorageState(File)
*/
public static File[] getObbDirs(Context context) {
return context.getObbDirs();
}
/**
* Returns absolute paths to application-specific directories on all
* external storage devices where the application can place persistent files
* it owns. These files are internal to the application, and not typically
* visible to the user as media.
* <p>
* This is like {@link Context#getFilesDir()} in that these files will be
* deleted when the application is uninstalled, however there are some
* important differences:
* <ul>
* <li>External files are not always available: they will disappear if the
* user mounts the external storage on a computer or removes it.
* <li>There is no security enforced with these files.
* </ul>
* <p>
* External storage devices returned here are considered a permanent part of
* the device, including both emulated external storage and physical media
* slots, such as SD cards in a battery compartment. The returned paths do
* not include transient devices, such as USB flash drives.
* <p>
* An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to write to the returned paths; they're always accessible to
* the calling app. Before then,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
* write. Write access outside of these paths on secondary external storage
* devices is not available. To request external storage access in a
* backwards compatible way, consider using {@code android:maxSdkVersion}
* like this:
*
* <pre class="prettyprint">&lt;uses-permission
* android:name="android.permission.WRITE_EXTERNAL_STORAGE"
* android:maxSdkVersion="18" /&gt;</pre>
* <p>
* The first path returned is the same as
* {@link Context#getExternalFilesDir(String)}. Returned paths may be
* {@code null} if a storage device is unavailable.
*
* @see Context#getExternalFilesDir(String)
* @see EnvironmentCompat#getStorageState(File)
*/
public static File[] getExternalFilesDirs(Context context, String type) {
return context.getExternalFilesDirs(type);
}
/**
* Returns absolute paths to application-specific directories on all
* external storage devices where the application can place cache files it
* owns. These files are internal to the application, and not typically
* visible to the user as media.
* <p>
* This is like {@link Context#getCacheDir()} in that these files will be
* deleted when the application is uninstalled, however there are some
* important differences:
* <ul>
* <li>External files are not always available: they will disappear if the
* user mounts the external storage on a computer or removes it.
* <li>There is no security enforced with these files.
* </ul>
* <p>
* External storage devices returned here are considered a permanent part of
* the device, including both emulated external storage and physical media
* slots, such as SD cards in a battery compartment. The returned paths do
* not include transient devices, such as USB flash drives.
* <p>
* An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to write to the returned paths; they're always accessible to
* the calling app. Before then,
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
* write. Write access outside of these paths on secondary external storage
* devices is not available. To request external storage access in a
* backwards compatible way, consider using {@code android:maxSdkVersion}
* like this:
*
* <pre class="prettyprint">&lt;uses-permission
* android:name="android.permission.WRITE_EXTERNAL_STORAGE"
* android:maxSdkVersion="18" /&gt;</pre>
* <p>
* The first path returned is the same as
* {@link Context#getExternalCacheDir()}. Returned paths may be {@code null}
* if a storage device is unavailable.
*
* @see Context#getExternalCacheDir()
* @see EnvironmentCompat#getStorageState(File)
*/
public static File[] getExternalCacheDirs(Context context) {
return context.getExternalCacheDirs();
}
/**
* Return a drawable object associated with a particular resource ID.
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#LOLLIPOP}, the returned
* drawable will be styled for the specified Context's theme.
*
* @param id The desired resource identifier, as generated by the aapt tool.
* This integer encodes the package, type, and resource entry.
* The value 0 is an invalid identifier.
* @return Drawable An object that can be used to draw this resource.
*/
public static final Drawable getDrawable(Context context, int id) {
return context.getDrawable(id);
}
/**
* Returns the absolute path to the directory on the filesystem similar to
* {@link Context#getFilesDir()}. The difference is that files placed under this
* directory will be excluded from automatic backup to remote storage on
* devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later. See
* {@link android.app.backup.BackupAgent BackupAgent} for a full discussion
* of the automatic backup mechanism in Android.
*
* <p>No permissions are required to read or write to the returned path, since this
* path is internal storage.
*
* @return The path of the directory holding application files that will not be
* automatically backed up to remote storage.
*
* @see android.content.Context.getFilesDir
*/
public final File getNoBackupFilesDir(Context context) {
return context.getNoBackupFilesDir();
}
/**
* Returns the absolute path to the application specific cache directory on
* the filesystem designed for storing cached code. On devices running
* {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later, the system will delete
* any files stored in this location both when your specific application is
* upgraded, and when the entire platform is upgraded.
* <p>
* This location is optimal for storing compiled or optimized code generated
* by your application at runtime.
* <p>
* Apps require no extra permissions to read or write to the returned path,
* since this path lives in their private storage.
*
* @return The path of the directory holding application code cache files.
*/
public final File getCodeCacheDir(Context context) {
return context.getCodeCacheDir();
}
}
@@ -1,53 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 android.support.v4.os;
import android.os.Environment;
import java.io.File;
/**
* Helper for accessing features in {@link Environment} introduced after API
* level 4 in a backwards compatible fashion.
*/
public class EnvironmentCompat {
/**
* Unknown storage state, such as when a path isn't backed by known storage
* media.
*
* @see #getStorageState(File)
*/
public static final String MEDIA_UNKNOWN = "unknown";
/**
* Returns the current state of the storage device that provides the given
* path.
*
* @return one of {@link #MEDIA_UNKNOWN}, {@link Environment#MEDIA_REMOVED},
* {@link Environment#MEDIA_UNMOUNTED},
* {@link Environment#MEDIA_CHECKING},
* {@link Environment#MEDIA_NOFS},
* {@link Environment#MEDIA_MOUNTED},
* {@link Environment#MEDIA_MOUNTED_READ_ONLY},
* {@link Environment#MEDIA_SHARED},
* {@link Environment#MEDIA_BAD_REMOVAL}, or
* {@link Environment#MEDIA_UNMOUNTABLE}.
*/
public static String getStorageState(File path) {
return Environment.getStorageState(path);
}
}
@@ -1,193 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 android.support.v7.preference;
import android.support.annotation.Nullable;
import java.util.Set;
/**
* A data store interface to be implemented and provided to the Preferences framework. This can be
* used to replace the default {@link android.content.SharedPreferences}, if needed.
*
* <p>In most cases you want to use {@link android.content.SharedPreferences} as it is automatically
* backed up and migrated to new devices. However, providing custom data store to preferences can be
* useful if your app stores its preferences in a local db, cloud or they are device specific like
* "Developer settings". It might be also useful when you want to use the preferences UI but
* the data are not supposed to be stored at all because they are valid per session only.
*
* <p>Once a put method is called it is full responsibility of the data store implementation to
* safely store the given values. Time expensive operations need to be done in the background to
* prevent from blocking the UI. You also need to have a plan on how to serialize the data in case
* the activity holding this object gets destroyed.
*
* <p>By default, all "put" methods throw {@link UnsupportedOperationException}.
*/
public abstract class PreferenceDataStore {
/**
* Sets a {@link String} value to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param value the new value for the preference
* @see #getString(String, String)
*/
public void putString(String key, @Nullable String value) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Sets a set of Strings to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param values the set of new values for the preference
* @see #getStringSet(String, Set<String>)
*/
public void putStringSet(String key, @Nullable Set<String> values) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Sets an {@link Integer} value to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param value the new value for the preference
* @see #getInt(String, int)
*/
public void putInt(String key, int value) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Sets a {@link Long} value to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param value the new value for the preference
* @see #getLong(String, long)
*/
public void putLong(String key, long value) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Sets a {@link Float} value to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param value the new value for the preference
* @see #getFloat(String, float)
*/
public void putFloat(String key, float value) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Sets a {@link Boolean} value to the data store.
*
* <p>Once the value is set the data store is responsible for holding it.
*
* @param key the name of the preference to modify
* @param value the new value for the preference
* @see #getBoolean(String, boolean)
*/
public void putBoolean(String key, boolean value) {
throw new UnsupportedOperationException("Not implemented on this data store");
}
/**
* Retrieves a {@link String} value from the data store.
*
* @param key the name of the preference to retrieve
* @param defValue value to return if this preference does not exist in the storage
* @return the value from the data store or the default return value
* @see #putString(String, String)
*/
@Nullable
public String getString(String key, @Nullable String defValue) {
return defValue;
}
/**
* Retrieves a set of Strings from the data store.
*
* @param key the name of the preference to retrieve
* @param defValues values to return if this preference does not exist in the storage
* @return the values from the data store or the default return values
* @see #putStringSet(String, Set<String>)
*/
@Nullable
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
return defValues;
}
/**
* Retrieves an {@link Integer} value from the data store.
*
* @param key the name of the preference to retrieve
* @param defValue value to return if this preference does not exist in the storage
* @return the value from the data store or the default return value
* @see #putInt(String, int)
*/
public int getInt(String key, int defValue) {
return defValue;
}
/**
* Retrieves a {@link Long} value from the data store.
*
* @param key the name of the preference to retrieve
* @param defValue value to return if this preference does not exist in the storage
* @return the value from the data store or the default return value
* @see #putLong(String, long)
*/
public long getLong(String key, long defValue) {
return defValue;
}
/**
* Retrieves a {@link Float} value from the data store.
*
* @param key the name of the preference to retrieve
* @param defValue value to return if this preference does not exist in the storage
* @return the value from the data store or the default return value
* @see #putFloat(String, float)
*/
public float getFloat(String key, float defValue) {
return defValue;
}
/**
* Retrieves a {@link Boolean} value from the data store.
*
* @param key the name of the preference to retrieve
* @param defValue value to return if this preference does not exist in the storage
* @return the value from the data store or the default return value
* @see #getBoolean(String, boolean)
*/
public boolean getBoolean(String key, boolean defValue) {
return defValue;
}
}
@@ -1,4 +0,0 @@
package android.support.v7.preference;
public class PreferenceScreen {
}
@@ -0,0 +1,40 @@
package android.widget;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
public class EditText {
public EditText(android.content.Context context) { throw new RuntimeException("Stub!"); }
public EditText(android.content.Context context, android.util.AttributeSet attrs) { throw new RuntimeException("Stub!"); }
public EditText(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr) { throw new RuntimeException("Stub!"); }
public EditText(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes) { throw new RuntimeException("Stub!"); }
public boolean getFreezesText() { throw new RuntimeException("Stub!"); }
protected boolean getDefaultEditable() { throw new RuntimeException("Stub!"); }
protected android.text.method.MovementMethod getDefaultMovementMethod() { throw new RuntimeException("Stub!"); }
public android.text.Editable getText() { throw new RuntimeException("Stub!"); }
public void setText(java.lang.CharSequence text, android.widget.TextView.BufferType type) { throw new RuntimeException("Stub!"); }
public void setSelection(int start, int stop) { throw new RuntimeException("Stub!"); }
public void setSelection(int index) { throw new RuntimeException("Stub!"); }
public void selectAll() { throw new RuntimeException("Stub!"); }
public void extendSelection(int index) { throw new RuntimeException("Stub!"); }
public void setEllipsize(android.text.TextUtils.TruncateAt ellipsis) { throw new RuntimeException("Stub!"); }
public java.lang.CharSequence getAccessibilityClassName() { throw new RuntimeException("Stub!"); }
}
@@ -0,0 +1,91 @@
package android.widget;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
public class Toast {
public static final int LENGTH_LONG = 1;
public static final int LENGTH_SHORT = 0;
private CharSequence text;
private Toast(CharSequence text) {
this.text = text;
}
public Toast(android.content.Context context) {
throw new RuntimeException("Stub!");
}
public void show() {
System.out.printf("made a Toast: \"%s\"\n", text.toString());
}
public void cancel() {
throw new RuntimeException("Stub!");
}
public void setView(android.view.View view) {
throw new RuntimeException("Stub!");
}
public android.view.View getView() {
throw new RuntimeException("Stub!");
}
public void setDuration(int duration) {
throw new RuntimeException("Stub!");
}
public int getDuration() {
throw new RuntimeException("Stub!");
}
public void setMargin(float horizontalMargin, float verticalMargin) {
throw new RuntimeException("Stub!");
}
public float getHorizontalMargin() {
throw new RuntimeException("Stub!");
}
public float getVerticalMargin() {
throw new RuntimeException("Stub!");
}
public void setGravity(int gravity, int xOffset, int yOffset) {
throw new RuntimeException("Stub!");
}
public int getGravity() {
throw new RuntimeException("Stub!");
}
public int getXOffset() {
throw new RuntimeException("Stub!");
}
public int getYOffset() {
throw new RuntimeException("Stub!");
}
public static Toast makeText(android.content.Context context, java.lang.CharSequence text, int duration) {
return new Toast(text);
}
public static android.widget.Toast makeText(android.content.Context context, int resId, int duration) throws android.content.res.Resources.NotFoundException {
throw new RuntimeException("Stub!");
}
public void setText(int resId) {
throw new RuntimeException("Stub!");
}
public void setText(java.lang.CharSequence s) {
throw new RuntimeException("Stub!");
}
}
@@ -0,0 +1,18 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
public class CheckBoxPreference extends TwoStatePreference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/CheckBoxPreference.java
public CheckBoxPreference(Context context) {
super(context);
}
}
@@ -0,0 +1,33 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
public abstract class DialogPreference extends Preference {
private CharSequence dialogTitle;
private CharSequence dialogMessage;
public DialogPreference(Context context) { super(context); }
public CharSequence getDialogTitle() {
return dialogTitle;
}
public void setDialogTitle(CharSequence dialogTitle) {
this.dialogTitle = dialogTitle;
}
public CharSequence getDialogMessage() {
return dialogMessage;
}
public void setDialogMessage(CharSequence dialogMessage) {
this.dialogMessage = dialogMessage;
}
}
@@ -0,0 +1,53 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.widget.EditText;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class EditTextPreference extends DialogPreference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/EditTextPreference.java
private String text;
@JsonIgnore
private OnBindEditTextListener onBindEditTextListener;
public EditTextPreference(Context context) {
super(context);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public OnBindEditTextListener getOnBindEditTextListener() {
return onBindEditTextListener;
}
public void setOnBindEditTextListener(@Nullable OnBindEditTextListener onBindEditTextListener) {
this.onBindEditTextListener = onBindEditTextListener;
}
public interface OnBindEditTextListener {
void onBindEditText(@NonNull EditText editText);
}
/** Tachidesk specific API */
@Override
public String getDefaultValueType() {
return "String";
}
}
@@ -0,0 +1,66 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
import android.text.TextUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class ListPreference extends Preference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/ListPreference.java
// Note: remove @JsonIgnore and implement methods if any extension ever uses these methods or the variables behind them
private CharSequence[] entries;
private CharSequence[] entryValues;
public ListPreference(Context context) {
super(context);
}
public CharSequence[] getEntries() {
return entries;
}
public void setEntries(CharSequence[] entries) {
this.entries = entries;
}
public int findIndexOfValue(String value) {
if (value != null && entryValues != null) {
for (int i = entryValues.length - 1; i >= 0; i--) {
if (TextUtils.equals(entryValues[i].toString(), value)) {
return i;
}
}
}
return -1;
}
public CharSequence[] getEntryValues() {
return entryValues;
}
public void setEntryValues(CharSequence[] entryValues) {
this.entryValues = entryValues;
}
@JsonIgnore
public void setValueIndex(int index) { throw new RuntimeException("Stub!"); }
@JsonIgnore
public String getValue() { throw new RuntimeException("Stub!"); }
@JsonIgnore
public void setValue(String value) { throw new RuntimeException("Stub!"); }
/** Tachidesk specific API */
@Override
public String getDefaultValueType() {
return "String";
}
}
@@ -0,0 +1,61 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Set;
public class MultiSelectListPreference extends DialogPreference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/MultiSelectListPreference.java
// Note: remove @JsonIgnore and implement methods if any extension ever uses these methods or the variables behind them
private CharSequence[] entries;
private CharSequence[] entryValues;
public MultiSelectListPreference(Context context) {
super(context);
}
public void setEntries(CharSequence[] entries) {
this.entries = entries;
}
public CharSequence[] getEntries() {
return entries;
}
public void setEntryValues(CharSequence[] entryValues) {
this.entryValues = entryValues;
}
public CharSequence[] getEntryValues() {
return entryValues;
}
@JsonIgnore
public void setValues(Set<String> values) {
throw new RuntimeException("Stub!");
}
@JsonIgnore
public Set<String> getValues() {
throw new RuntimeException("Stub!");
}
public int findIndexOfValue(String value) {
throw new RuntimeException("Stub!");
}
/** Tachidesk specific API */
@Override
public String getDefaultValueType() {
return "Set<String>";
}
}
@@ -0,0 +1,148 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
import android.content.SharedPreferences;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.Set;
/**
* A minimal implementation of androidx.preference.Preference
*/
public class Preference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/Preference.java
// Note: `Preference` doesn't actually hold or persist the value, `OnPreferenceChangeListener` is called and it's up to the extension to persist it.
@JsonIgnore
protected Context context;
private String key;
private CharSequence title;
private CharSequence summary;
private Object defaultValue;
/** Tachidesk specific API */
@JsonIgnore
private SharedPreferences sharedPreferences;
@JsonIgnore
public OnPreferenceChangeListener onChangeListener;
public Preference(Context context) {
this.context = context;
}
public Context getContext() {
return context;
}
public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) {
this.onChangeListener = onPreferenceChangeListener;
}
public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
throw new RuntimeException("Stub!");
}
public CharSequence getTitle() {
return title;
}
public void setTitle(CharSequence title) {
this.title = title;
}
public CharSequence getSummary() {
return summary;
}
public void setSummary(CharSequence summary) {
this.summary = summary;
}
public void setEnabled(boolean enabled) {
throw new RuntimeException("Stub!");
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void setDefaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
}
public boolean callChangeListener(Object newValue) {
return onChangeListener == null || onChangeListener.onPreferenceChange(this, newValue);
}
public Object getDefaultValue() {
return defaultValue;
}
/** Tachidesk specific API */
public String getDefaultValueType() {
return defaultValue.getClass().getSimpleName();
}
/** Tachidesk specific API */
public SharedPreferences getSharedPreferences() {
return sharedPreferences;
}
/** Tachidesk specific API */
public void setSharedPreferences(SharedPreferences sharedPreferences) {
this.sharedPreferences = sharedPreferences;
}
public interface OnPreferenceChangeListener {
boolean onPreferenceChange(Preference preference, Object newValue);
}
public interface OnPreferenceClickListener {
boolean onPreferenceClick(Preference preference);
}
/** Tachidesk specific API */
@SuppressWarnings("unchecked")
public Object getCurrentValue() {
switch (getDefaultValueType()) {
case "String":
return sharedPreferences.getString(key, (String)defaultValue);
case "Boolean":
return sharedPreferences.getBoolean(key, (Boolean)defaultValue);
case "Set<String>":
return sharedPreferences.getStringSet(key, (Set<String>)defaultValue);
default:
throw new RuntimeException("Unsupported type");
}
}
/** Tachidesk specific API */
@SuppressWarnings("unchecked")
public void saveNewValue(Object value) {
switch (getDefaultValueType()) {
case "String":
sharedPreferences.edit().putString(key, (String)value).apply();
break;
case "Boolean":
sharedPreferences.edit().putBoolean(key, (Boolean)value).apply();
break;
case "Set<String>":
sharedPreferences.edit().putStringSet(key, (Set<String>)value).apply();
break;
default:
throw new RuntimeException("Unsupported type");
}
}
}
@@ -0,0 +1,36 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
import java.util.LinkedList;
import java.util.List;
public class PreferenceScreen extends Preference {
/** Tachidesk specific API */
private List<Preference> preferences = new LinkedList<>();
public PreferenceScreen(Context context) {
super(context);
}
public boolean addPreference(Preference preference) {
// propagate own shared preferences
preference.setSharedPreferences(getSharedPreferences());
preferences.add(preference);
return true;
}
/** Tachidesk specific API */
public List<Preference> getPreferences(){
return preferences;
}
}
@@ -0,0 +1,18 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
public class SwitchPreferenceCompat extends TwoStatePreference {
// reference: https://android.googlesource.com/platform/frameworks/support/+/996971f962fcd554339a7cb2859cef9ca89dbcb7/preference/preference/src/main/java/androidx/preference/CheckBoxPreference.java
public SwitchPreferenceCompat(Context context) {
super(context);
}
}
@@ -0,0 +1,50 @@
package androidx.preference;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.Context;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class TwoStatePreference extends Preference {
// Note: remove @JsonIgnore and implement methods if any extension ever uses these methods or the variables behind them
public TwoStatePreference(Context context) {
super(context);
setDefaultValue(false);
}
@JsonIgnore
public boolean isChecked() { throw new RuntimeException("Stub!"); }
@JsonIgnore
public void setChecked(boolean checked) { throw new RuntimeException("Stub!"); }
@JsonIgnore
public CharSequence getSummaryOn() { throw new RuntimeException("Stub!"); }
@JsonIgnore
public void setSummaryOn(CharSequence summary) { throw new RuntimeException("Stub!"); }
@JsonIgnore
public CharSequence getSummaryOff() { throw new RuntimeException("Stub!"); }
@JsonIgnore
public void setSummaryOff(CharSequence summary) { throw new RuntimeException("Stub!"); }
@JsonIgnore
public boolean getDisableDependentsState() { throw new RuntimeException("Stub!"); }
@JsonIgnore
public void setDisableDependentsState(boolean disableDependentsState) { throw new RuntimeException("Stub!"); }
/** Tachidesk specific API */
@Override
public String getDefaultValueType() {
return "Boolean";
}
}
@@ -14,9 +14,10 @@
* limitations under the License.
*/
package com.android.internal.util;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -25,19 +26,14 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ProtocolException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
/** {@hide} */
public class XmlUtils {
private static final String STRING_ARRAY_SEPARATOR = ":";
@@ -1396,9 +1392,9 @@ public class XmlUtils {
} else if (tagName.equals("long")) {
return Long.valueOf(parser.getAttributeValue(null, "value"));
} else if (tagName.equals("float")) {
return new Float(parser.getAttributeValue(null, "value"));
return Float.valueOf(parser.getAttributeValue(null, "value"));
} else if (tagName.equals("double")) {
return new Double(parser.getAttributeValue(null, "value"));
return Double.valueOf(parser.getAttributeValue(null, "value"));
} else if (tagName.equals("boolean")) {
return Boolean.valueOf(parser.getAttributeValue(null, "value"));
} else {
@@ -1,2 +0,0 @@
package com.f2prateek;
//TODO Consider if we can change this package into an Android dependency
@@ -1,34 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file may have been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class BooleanAdapter implements Preference.Adapter<Boolean> {
static final BooleanAdapter INSTANCE = new BooleanAdapter();
@Override public Boolean get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getBoolean(key, false);
}
@Override public void set(@NonNull String key, @NonNull Boolean value,
@NonNull SharedPreferences.Editor editor) {
editor.putBoolean(key, value);
}
}
@@ -1,40 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file may have been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class EnumAdapter<T extends Enum<T>> implements Preference.Adapter<T> {
private final Class<T> enumClass;
EnumAdapter(Class<T> enumClass) {
this.enumClass = enumClass;
}
@Override public T get(@NonNull String key, @NonNull SharedPreferences preferences) {
String value = preferences.getString(key, null);
assert value != null; // Not called unless key is present.
return Enum.valueOf(enumClass, value);
}
@Override
public void set(@NonNull String key, @NonNull T value, @NonNull SharedPreferences.Editor editor) {
editor.putString(key, value.name());
}
}
@@ -1,34 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file may have been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class FloatAdapter implements Preference.Adapter<Float> {
static final FloatAdapter INSTANCE = new FloatAdapter();
@Override public Float get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getFloat(key, 0f);
}
@Override public void set(@NonNull String key, @NonNull Float value,
@NonNull SharedPreferences.Editor editor) {
editor.putFloat(key, value);
}
}
@@ -1,34 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file may have been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class IntegerAdapter implements Preference.Adapter<Integer> {
static final IntegerAdapter INSTANCE = new IntegerAdapter();
@Override public Integer get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getInt(key, 0);
}
@Override public void set(@NonNull String key, @NonNull Integer value,
@NonNull SharedPreferences.Editor editor) {
editor.putInt(key, value);
}
}
@@ -1,34 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file may have been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class LongAdapter implements Preference.Adapter<Long> {
static final LongAdapter INSTANCE = new LongAdapter();
@Override public Long get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getLong(key, 0L);
}
@Override public void set(@NonNull String key, @NonNull Long value,
@NonNull SharedPreferences.Editor editor) {
editor.putLong(key, value);
}
}
@@ -1,127 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file has been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import rx.Observable;
import rx.functions.Action1;
/** A preference of type {@link T}. Instances can be created from {@link RxSharedPreferences}. */
public final class Preference<T> {
/** Stores and retrieves instances of {@code T} in {@link SharedPreferences}. */
public interface Adapter<T> {
/** Retrieve the value for {@code key} from {@code preferences}. */
T get(@NonNull String key, @NonNull SharedPreferences preferences);
/**
* Store non-null {@code value} for {@code key} in {@code editor}.
* <p>
* Note: Implementations <b>must not</b> call {@code commit()} or {@code apply()} on
* {@code editor}.
*/
void set(@NonNull String key, @NonNull T value, @NonNull SharedPreferences.Editor editor);
}
private final SharedPreferences preferences;
private final String key;
private final T defaultValue;
private final Adapter<T> adapter;
private final Observable<T> values;
Preference(SharedPreferences preferences, final String key, T defaultValue, Adapter<T> adapter,
Observable<String> keyChanges) {
this.preferences = preferences;
this.key = key;
this.defaultValue = defaultValue;
this.adapter = adapter;
this.values = keyChanges
.filter(key::equals)
.startWith("<init>") // Dummy value to trigger initial load.
.onBackpressureLatest()
.map(ignored -> get());
}
/** The key for which this preference will store and retrieve values. */
@NonNull
public String key() {
return key;
}
/** The value used if none is stored. May be {@code null}. */
@Nullable
public T defaultValue() {
return defaultValue;
}
/**
* Retrieve the current value for this preference. Returns {@link #defaultValue()} if no value is
* set.
*/
@Nullable
public T get() {
if (!preferences.contains(key)) {
return defaultValue;
}
return adapter.get(key, preferences);
}
/**
* Change this preference's stored value to {@code value}. A value of {@code null} will delete the
* preference.
*/
public void set(@Nullable T value) {
SharedPreferences.Editor editor = preferences.edit();
if (value == null) {
editor.remove(key);
} else {
adapter.set(key, value, editor);
}
editor.apply();
}
/** Returns true if this preference has a stored value. */
public boolean isSet() {
return preferences.contains(key);
}
/** Delete the stored value for this preference, if any. */
public void delete() {
set(null);
}
/**
* Observe changes to this preference. The current value or {@link #defaultValue()} will be
* emitted on first subscribe.
*/
@CheckResult @NonNull
public Observable<T> asObservable() {
return values;
}
/**
* An action which stores a new value for this preference. Passing {@code null} will delete the
* preference.
*/
@CheckResult @NonNull
public Action1<? super T> asAction() {
return (Action1<T>) this::set;
}
}
@@ -1,178 +0,0 @@
/*
Copyright 2014 Prateek Srivastava
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
This file has been modified after being copied from it's original source.
*/
package com.f2prateek.rx.preferences;
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.Collections;
import java.util.Set;
import rx.Observable;
import rx.subscriptions.Subscriptions;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static com.f2prateek.rx.preferences.Preconditions.checkNotNull;
/** A factory for reactive {@link Preference} objects. */
public final class RxSharedPreferences {
private static final Float DEFAULT_FLOAT = 0f;
private static final Integer DEFAULT_INTEGER = 0;
private static final Boolean DEFAULT_BOOLEAN = Boolean.FALSE;
private static final Long DEFAULT_LONG = 0L;
/** Create an instance of {@link RxSharedPreferences} for {@code preferences}. */
@CheckResult @NonNull
public static RxSharedPreferences create(@NonNull SharedPreferences preferences) {
checkNotNull(preferences, "preferences == null");
return new RxSharedPreferences(preferences);
}
private final SharedPreferences preferences;
private final Observable<String> keyChanges;
private RxSharedPreferences(final SharedPreferences preferences) {
this.preferences = preferences;
this.keyChanges = Observable.create((Observable.OnSubscribe<String>) subscriber -> {
final OnSharedPreferenceChangeListener listener = (preferences1, key) -> subscriber.onNext(key);
preferences.registerOnSharedPreferenceChangeListener(listener);
subscriber.add(Subscriptions.create(() -> preferences.unregisterOnSharedPreferenceChangeListener(listener)));
}).share();
}
/** Create a boolean preference for {@code key}. Default is {@code false}. */
@CheckResult @NonNull
public Preference<Boolean> getBoolean(@NonNull String key) {
return getBoolean(key, DEFAULT_BOOLEAN);
}
/** Create a boolean preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public Preference<Boolean> getBoolean(@NonNull String key, @Nullable Boolean defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, BooleanAdapter.INSTANCE, keyChanges);
}
/** Create an enum preference for {@code key}. Default is {@code null}. */
@CheckResult @NonNull
public <T extends Enum<T>> Preference<T> getEnum(@NonNull String key,
@NonNull Class<T> enumClass) {
return getEnum(key, null, enumClass);
}
/** Create an enum preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public <T extends Enum<T>> Preference<T> getEnum(@NonNull String key, @Nullable T defaultValue,
@NonNull Class<T> enumClass) {
checkNotNull(key, "key == null");
checkNotNull(enumClass, "enumClass == null");
Preference.Adapter<T> adapter = new EnumAdapter<>(enumClass);
return new Preference<>(preferences, key, defaultValue, adapter, keyChanges);
}
/** Create a float preference for {@code key}. Default is {@code 0}. */
@CheckResult @NonNull
public Preference<Float> getFloat(@NonNull String key) {
return getFloat(key, DEFAULT_FLOAT);
}
/** Create a float preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public Preference<Float> getFloat(@NonNull String key, @Nullable Float defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, FloatAdapter.INSTANCE, keyChanges);
}
/** Create an integer preference for {@code key}. Default is {@code 0}. */
@CheckResult @NonNull
public Preference<Integer> getInteger(@NonNull String key) {
//noinspection UnnecessaryBoxing
return getInteger(key, DEFAULT_INTEGER);
}
/** Create an integer preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public Preference<Integer> getInteger(@NonNull String key, @Nullable Integer defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, IntegerAdapter.INSTANCE, keyChanges);
}
/** Create a long preference for {@code key}. Default is {@code 0}. */
@CheckResult @NonNull
public Preference<Long> getLong(@NonNull String key) {
//noinspection UnnecessaryBoxing
return getLong(key, DEFAULT_LONG);
}
/** Create a long preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public Preference<Long> getLong(@NonNull String key, @Nullable Long defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, LongAdapter.INSTANCE, keyChanges);
}
/** Create a preference of type {@code T} for {@code key}. Default is {@code null}. */
@CheckResult @NonNull
public <T> Preference<T> getObject(@NonNull String key, @NonNull Preference.Adapter<T> adapter) {
return getObject(key, null, adapter);
}
/**
* Create a preference for type {@code T} for {@code key} with a default of {@code defaultValue}.
*/
@CheckResult @NonNull
public <T> Preference<T> getObject(@NonNull String key, @Nullable T defaultValue,
@NonNull Preference.Adapter<T> adapter) {
checkNotNull(key, "key == null");
checkNotNull(adapter, "adapter == null");
return new Preference<>(preferences, key, defaultValue, adapter, keyChanges);
}
/** Create a string preference for {@code key}. Default is {@code null}. */
@CheckResult @NonNull
public Preference<String> getString(@NonNull String key) {
return getString(key, null);
}
/** Create a string preference for {@code key} with a default of {@code defaultValue}. */
@CheckResult @NonNull
public Preference<String> getString(@NonNull String key, @Nullable String defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, StringAdapter.INSTANCE, keyChanges);
}
/** Create a string set preference for {@code key}. Default is an empty set. */
@TargetApi(HONEYCOMB)
@CheckResult @NonNull
public Preference<Set<String>> getStringSet(@NonNull String key) {
return getStringSet(key, Collections.emptySet());
}
/** Create a string set preference for {@code key} with a default of {@code defaultValue}. */
@TargetApi(HONEYCOMB)
@CheckResult @NonNull
public Preference<Set<String>> getStringSet(@NonNull String key,
@NonNull Set<String> defaultValue) {
checkNotNull(key, "key == null");
return new Preference<>(preferences, key, defaultValue, StringSetAdapter.INSTANCE, keyChanges);
}
}
@@ -1,17 +0,0 @@
package com.f2prateek.rx.preferences;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
final class StringAdapter implements Preference.Adapter<String> {
static final StringAdapter INSTANCE = new StringAdapter();
@Override public String get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getString(key, null);
}
@Override public void set(@NonNull String key, @NonNull String value,
@NonNull SharedPreferences.Editor editor) {
editor.putString(key, value);
}
}
@@ -1,22 +0,0 @@
package com.f2prateek.rx.preferences;
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import java.util.Set;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
@TargetApi(HONEYCOMB)
final class StringSetAdapter implements Preference.Adapter<Set<String>> {
static final StringSetAdapter INSTANCE = new StringSetAdapter();
@Override public Set<String> get(@NonNull String key, @NonNull SharedPreferences preferences) {
return preferences.getStringSet(key, null);
}
@Override public void set(@NonNull String key, @NonNull Set<String> value,
@NonNull SharedPreferences.Editor editor) {
editor.putStringSet(key, value);
}
}
@@ -1,7 +0,0 @@
package com.github.pwittchen.reactivenetwork.library
import android.net.NetworkInfo
class Connectivity {
val state = NetworkInfo.State.CONNECTED
}
@@ -1,14 +0,0 @@
package com.github.pwittchen.reactivenetwork.library
import android.content.Context
import rx.Observable
/**
* Created by nulldev on 12/29/16.
*/
class ReactiveNetwork {
companion object {
fun observeNetworkConnectivity(context: Context) = Observable.just(Connectivity())!!
}
}
@@ -1,11 +1,20 @@
package com.squareup.duktape;
/*
* Copyright (C) Contributors to the Suwayomi project
* Copyright (C) 2015 Square, Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 com.squareup.duktape;
import kotlin.NotImplementedError;
@@ -64,18 +73,18 @@ public final class Duktape implements Closeable, AutoCloseable {
throw new NotImplementedError("Not implemented!");
}
// /**
// * Attaches to a global JavaScript object called {@code name} that implements {@code type}.
// * {@code type} defines the interface implemented in JavaScript that will be accessible to Java.
// * {@code type} must be an interface that does not extend any other interfaces, and cannot define
// * any overloaded methods.
// * <p>Methods of the interface may return {@code void} or any of the following supported argument
// * types: {@code boolean}, {@link Boolean}, {@code int}, {@link Integer}, {@code double},
// * {@link Double}, {@link String}.
// */
// public synchronized <T> T get(final String name, final Class<T> type) {
// throw new NotImplementedError("Not implemented!");
// }
/**
* Attaches to a global JavaScript object called {@code name} that implements {@code type}.
* {@code type} defines the interface implemented in JavaScript that will be accessible to Java.
* {@code type} must be an interface that does not extend any other interfaces, and cannot define
* any overloaded methods.
* <p>Methods of the interface may return {@code void} or any of the following supported argument
* types: {@code boolean}, {@link Boolean}, {@code int}, {@link Integer}, {@code double},
* {@link Double}, {@link String}.
*/
public synchronized <T> T get(final String name, final Class<T> type) {
throw new NotImplementedError("Not implemented!");
}
/**
* Release the native resources associated with this object. You <strong>must</strong> call this
@@ -1,13 +1,6 @@
package com.squareup.duktape;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// part of tachiyomi-extensions which was originally licensed under Apache License Version 2.0
/* part of tachiyomi-extensions which is licensed under Apache License Version 2.0 */
import java.io.Closeable;
import java.io.IOException;
@@ -5,4 +5,4 @@ import android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory
class RequerySQLiteOpenHelperFactory {
fun create(configuration: SupportSQLiteOpenHelper.Configuration) = FrameworkSQLiteOpenHelperFactory().create(configuration)
}
}
@@ -1,5 +0,0 @@
package kotlinx.coroutines.experimental.android
import kotlinx.coroutines.GlobalScope
val UI = GlobalScope.coroutineContext
@@ -1,5 +1,6 @@
package rx.android.schedulers
import rx.Scheduler
import rx.internal.schedulers.ImmediateScheduler
class AndroidSchedulers {
@@ -11,6 +12,7 @@ class AndroidSchedulers {
/**
* Simulated main thread scheduler
*/
fun mainThread() = mainThreadScheduler
@JvmStatic
fun mainThread(): Scheduler = mainThreadScheduler
}
}
@@ -14,4 +14,4 @@ class AndroidCompat {
application.attach(context)
application.onCreate()
}
}
}
@@ -2,7 +2,6 @@ package xyz.nulldev.androidcompat
import org.kodein.di.DI
import org.kodein.di.conf.global
import xyz.nulldev.androidcompat.bytecode.ModApplier
import xyz.nulldev.androidcompat.config.ApplicationInfoConfigModule
import xyz.nulldev.androidcompat.config.FilesConfigModule
import xyz.nulldev.androidcompat.config.SystemConfigModule
@@ -12,19 +11,17 @@ import xyz.nulldev.ts.config.GlobalConfigManager
* Initializes the Android compatibility module
*/
class AndroidCompatInitializer {
val modApplier by lazy { ModApplier() }
fun init() {
modApplier.apply()
DI.global.addImport(AndroidCompatModule().create())
//Register config modules
// Register config modules
GlobalConfigManager.registerModules(
FilesConfigModule.register(GlobalConfigManager.config),
ApplicationInfoConfigModule.register(GlobalConfigManager.config),
SystemConfigModule.register(GlobalConfigManager.config)
)
// Set some properties extensions use
System.setProperty("http.agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
}
}
@@ -29,7 +29,7 @@ class AndroidCompatModule {
bind<PackageController>() with singleton { PackageController() }
//Context
// Context
bind<CustomContext>() with singleton { CustomContext() }
bind<Context>() with singleton {
val context: Context by DI.global.instance<CustomContext>()
@@ -38,7 +38,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.nulldev.androidcompat.info.ApplicationInfoImpl;
import xyz.nulldev.androidcompat.io.AndroidFiles;
import xyz.nulldev.androidcompat.io.sharedprefs.JsonSharedPreferences;
import xyz.nulldev.androidcompat.io.sharedprefs.JavaSharedPreferences;
import xyz.nulldev.androidcompat.service.ServiceSupport;
import xyz.nulldev.androidcompat.util.KodeinGlobalHelper;
@@ -50,10 +50,9 @@ import java.util.Map;
/**
* Custom context implementation.
*
* TODO Deal with packagemanager for extension sources
*/
public class CustomContext extends Context implements DIAware {
private DI kodein;
private final DI kodein;
public CustomContext() {
this(KodeinGlobalHelper.kodein());
}
@@ -165,23 +164,22 @@ public class CustomContext extends Context implements DIAware {
/** Fake shared prefs! **/
private Map<String, SharedPreferences> prefs = new HashMap<>(); //Cache
private File sharedPrefsFileFromString(String s) {
return new File(androidFiles.getPrefsDir(), s + ".json");
}
@Override
public synchronized SharedPreferences getSharedPreferences(String s, int i) {
SharedPreferences preferences = prefs.get(s);
//Create new shared preferences if one does not exist
if(preferences == null) {
preferences = getSharedPreferences(sharedPrefsFileFromString(s), i);
preferences = new JavaSharedPreferences(s);
prefs.put(s, preferences);
}
return preferences;
}
public SharedPreferences getSharedPreferences(File file, int mode) {
return new JsonSharedPreferences(file);
@Override
public SharedPreferences getSharedPreferences(@NotNull File file, int mode) {
String path = file.getAbsolutePath().replace('\\', '/');
int firstSlash = path.indexOf("/");
return new JavaSharedPreferences(path.substring(firstSlash));
}
@Override
@@ -191,8 +189,8 @@ public class CustomContext extends Context implements DIAware {
@Override
public boolean deleteSharedPreferences(String name) {
prefs.remove(name);
return sharedPrefsFileFromString(name).delete();
JavaSharedPreferences item = (JavaSharedPreferences) prefs.remove(name);
return item.deleteAll();
}
@Override
@@ -735,4 +733,3 @@ public class CustomContext extends Context implements DIAware {
}
}
@@ -1,22 +0,0 @@
package xyz.nulldev.androidcompat.bytecode
import javassist.CtClass
import mu.KotlinLogging
/**
* Applies Javassist modifications
*/
class ModApplier {
val logger = KotlinLogging.logger {}
fun apply() {
logger.info { "Applying Javassist mods..." }
val modifiedClasses = mutableListOf<CtClass>()
modifiedClasses.forEach {
it.toClass()
}
}
}
@@ -1,6 +1,7 @@
package xyz.nulldev.androidcompat.config
import com.typesafe.config.Config
import io.github.config4k.getValue
import xyz.nulldev.ts.config.ConfigModule
/**
@@ -8,11 +9,11 @@ import xyz.nulldev.ts.config.ConfigModule
*/
class ApplicationInfoConfigModule(config: Config) : ConfigModule(config) {
val packageName = config.getString("packageName")!!
val debug = config.getBoolean("debug")
val packageName: String by config
val debug: Boolean by config
companion object {
fun register(config: Config)
= ApplicationInfoConfigModule(config.getConfig("android.app"))
fun register(config: Config) =
ApplicationInfoConfigModule(config.getConfig("android.app"))
}
}
@@ -1,6 +1,7 @@
package xyz.nulldev.androidcompat.config
import com.typesafe.config.Config
import io.github.config4k.getValue
import xyz.nulldev.ts.config.ConfigModule
/**
@@ -8,26 +9,26 @@ import xyz.nulldev.ts.config.ConfigModule
*/
class FilesConfigModule(config: Config) : ConfigModule(config) {
val dataDir = config.getString("dataDir")!!
val filesDir = config.getString("filesDir")!!
val noBackupFilesDir = config.getString("noBackupFilesDir")!!
val externalFilesDirs: MutableList<String> = config.getStringList("externalFilesDirs")!!
val obbDirs: MutableList<String> = config.getStringList("obbDirs")!!
val cacheDir = config.getString("cacheDir")!!
val codeCacheDir = config.getString("codeCacheDir")!!
val externalCacheDirs: MutableList<String> = config.getStringList("externalCacheDirs")!!
val externalMediaDirs: MutableList<String> = config.getStringList("externalMediaDirs")!!
val rootDir = config.getString("rootDir")!!
val externalStorageDir = config.getString("externalStorageDir")!!
val downloadCacheDir = config.getString("downloadCacheDir")!!
val databasesDir = config.getString("databasesDir")!!
val dataDir: String by config
val filesDir: String by config
val noBackupFilesDir: String by config
val externalFilesDirs: MutableList<String> by config
val obbDirs: MutableList<String> by config
val cacheDir: String by config
val codeCacheDir: String by config
val externalCacheDirs: MutableList<String> by config
val externalMediaDirs: MutableList<String> by config
val rootDir: String by config
val externalStorageDir: String by config
val downloadCacheDir: String by config
val databasesDir: String by config
val prefsDir = config.getString("prefsDir")!!
val prefsDir: String by config
val packageDir = config.getString("packageDir")!!
val packageDir: String by config
companion object {
fun register(config: Config)
= FilesConfigModule(config.getConfig("android.files"))
fun register(config: Config) =
FilesConfigModule(config.getConfig("android.files"))
}
}
}
@@ -1,10 +1,11 @@
package xyz.nulldev.androidcompat.config
import com.typesafe.config.Config
import io.github.config4k.getValue
import xyz.nulldev.ts.config.ConfigModule
class SystemConfigModule(val config: Config) : ConfigModule(config) {
val isDebuggable = config.getBoolean("isDebuggable")
val isDebuggable: Boolean by config
val propertyPrefix = "properties."
@@ -15,7 +16,7 @@ class SystemConfigModule(val config: Config) : ConfigModule(config) {
fun hasProperty(property: String) = config.hasPath("$propertyPrefix$property")
companion object {
fun register(config: Config)
= SystemConfigModule(config.getConfig("android.system"))
fun register(config: Config) =
SystemConfigModule(config.getConfig("android.system"))
}
}
@@ -4,11 +4,21 @@ import java.io.InputStream
import java.io.Reader
import java.math.BigDecimal
import java.net.URL
import java.sql.*
import java.sql.Array
import java.sql.Blob
import java.sql.Clob
import java.sql.Date
import java.util.*
import java.sql.NClob
import java.sql.Ref
import java.sql.ResultSet
import java.sql.ResultSetMetaData
import java.sql.RowId
import java.sql.SQLXML
import java.sql.Time
import java.sql.Timestamp
import java.util.Calendar
@Suppress("UNCHECKED_CAST")
class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
private val cachedContent = mutableListOf<ResultSetEntry>()
@@ -19,7 +29,7 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
val parentMetadata = parent.metaData
val columnCount = parentMetadata.columnCount
val columnLabels = (1 .. columnCount).map {
val columnLabels = (1..columnCount).map {
parentMetadata.getColumnLabel(it)
}.toTypedArray()
@@ -31,10 +41,10 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
// How can we optimize this?
// We need to fill the cache as the set is loaded
//Fill cache
while(parent.next()) {
// Fill cache
while (parent.next()) {
cachedContent += ResultSetEntry().apply {
for(i in 1 .. columnCount)
for (i in 1..columnCount)
data += parent.getObject(i)
}
resultSetLength++
@@ -50,8 +60,8 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
private fun internalMove(row: Int) {
if(cursor < 0) cursor = 0
else if(cursor > resultSetLength + 1) cursor = resultSetLength + 1
if (cursor < 0) cursor = 0
else if (cursor > resultSetLength + 1) cursor = resultSetLength + 1
else cursor = row
}
@@ -65,10 +75,10 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
return obj(cachedFindColumn(column))
}
private fun cachedFindColumn(column: String?)
= columnCache.getOrPut(column!!, {
findColumn(column)
})
private fun cachedFindColumn(column: String?) =
columnCache.getOrPut(column!!, {
findColumn(column)
})
override fun getNClob(columnIndex: Int): NClob {
return obj(columnIndex) as NClob
@@ -147,27 +157,27 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getDate(columnIndex: Int): Date {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getDate(columnLabel: String?): Date {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getDate(columnIndex: Int, cal: Calendar?): Date {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getDate(columnLabel: String?, cal: Calendar?): Date {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun beforeFirst() {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -192,12 +202,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getBigDecimal(columnIndex: Int, scale: Int): BigDecimal {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getBigDecimal(columnLabel: String?, scale: Int): BigDecimal {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -226,22 +236,22 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getTime(columnIndex: Int): Time {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTime(columnLabel: String?): Time {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTime(columnIndex: Int, cal: Calendar?): Time {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTime(columnLabel: String?, cal: Calendar?): Time {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -262,28 +272,28 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun absolute(row: Int): Boolean {
if(row > 0) {
if (row > 0) {
internalMove(row)
} else {
last()
for(i in 1 .. row)
for (i in 1..row)
previous()
}
return cursorValid()
}
override fun getSQLXML(columnIndex: Int): SQLXML? {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getSQLXML(columnLabel: String?): SQLXML? {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun <T : Any?> unwrap(iface: Class<T>?): T {
if(thisIsWrapperFor(iface))
if (thisIsWrapperFor(iface))
return this as T
else
return parent.unwrap(iface)
@@ -416,12 +426,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getBlob(columnIndex: Int): Blob {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getBlob(columnLabel: String?): Blob {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -490,12 +500,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getObject(columnIndex: Int, map: MutableMap<String, Class<*>>?): Any {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getObject(columnLabel: String?, map: MutableMap<String, Class<*>>?): Any {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -521,9 +531,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
private fun castToLong(obj: Any?): Long {
if(obj == null) return 0
else if(obj is Long) return obj
else if(obj is Number) return obj.toLong()
if (obj == null) return 0
else if (obj is Long) return obj
else if (obj is Number) return obj.toLong()
else throw IllegalStateException("Object is not a long!")
}
@@ -536,12 +546,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getClob(columnIndex: Int): Clob {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getClob(columnLabel: String?): Clob {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -594,12 +604,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getArray(columnIndex: Int): Array {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getArray(columnLabel: String?): Array {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -678,32 +688,32 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getTimestamp(columnIndex: Int): Timestamp {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTimestamp(columnLabel: String?): Timestamp {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTimestamp(columnIndex: Int, cal: Calendar?): Timestamp {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getTimestamp(columnLabel: String?, cal: Calendar?): Timestamp {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getRef(columnIndex: Int): Ref {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getRef(columnLabel: String?): Ref {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -782,12 +792,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
}
override fun getRowId(columnIndex: Int): RowId {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
override fun getRowId(columnLabel: String?): RowId {
//TODO Maybe?
// TODO Maybe?
notImplemented()
}
@@ -838,4 +848,4 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
class ResultSetEntry {
val data = mutableListOf<Any?>()
}
}
}
@@ -0,0 +1,177 @@
package xyz.nulldev.androidcompat.io.sharedprefs
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import android.content.SharedPreferences
import com.russhwolf.settings.ExperimentalSettingsApi
import com.russhwolf.settings.ExperimentalSettingsImplementation
import com.russhwolf.settings.JvmPreferencesSettings
import com.russhwolf.settings.serialization.decodeValue
import com.russhwolf.settings.serialization.decodeValueOrNull
import com.russhwolf.settings.serialization.encodeValue
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerializationException
import kotlinx.serialization.builtins.SetSerializer
import kotlinx.serialization.builtins.serializer
import java.util.prefs.PreferenceChangeListener
import java.util.prefs.Preferences
@OptIn(ExperimentalSettingsImplementation::class, ExperimentalSerializationApi::class, ExperimentalSettingsApi::class)
class JavaSharedPreferences(key: String) : SharedPreferences {
private val javaPreferences = Preferences.userRoot().node("suwayomi/tachidesk/$key")
private val preferences = JvmPreferencesSettings(javaPreferences)
private val listeners = mutableMapOf<SharedPreferences.OnSharedPreferenceChangeListener, PreferenceChangeListener>()
// TODO: 2021-05-29 Need to find a way to get this working with all pref types
override fun getAll(): MutableMap<String, *> {
return preferences.keys.associateWith { preferences.getStringOrNull(it) }.toMutableMap()
}
override fun getString(key: String, defValue: String?): String? {
return if (defValue != null) {
preferences.getString(key, defValue)
} else {
preferences.getStringOrNull(key)
}
}
override fun getStringSet(key: String, defValues: Set<String>?): Set<String>? {
try {
return if (defValues != null) {
preferences.decodeValue(SetSerializer(String.serializer()), key, defValues)
} else {
preferences.decodeValueOrNull(SetSerializer(String.serializer()), key)
}
} catch (e: SerializationException) {
throw ClassCastException("$key was not a StringSet")
}
}
override fun getInt(key: String, defValue: Int): Int {
return preferences.getInt(key, defValue)
}
override fun getLong(key: String, defValue: Long): Long {
return preferences.getLong(key, defValue)
}
override fun getFloat(key: String, defValue: Float): Float {
return preferences.getFloat(key, defValue)
}
override fun getBoolean(key: String, defValue: Boolean): Boolean {
return preferences.getBoolean(key, defValue)
}
override fun contains(key: String): Boolean {
return key in preferences.keys
}
override fun edit(): SharedPreferences.Editor {
return Editor(preferences)
}
class Editor(private val preferences: JvmPreferencesSettings) : SharedPreferences.Editor {
val itemsToAdd = mutableMapOf<String, Any>()
override fun putString(key: String, value: String?): SharedPreferences.Editor {
if (value != null) {
itemsToAdd[key] = value
} else {
remove(key)
}
return this
}
override fun putStringSet(
key: String,
values: MutableSet<String>?
): SharedPreferences.Editor {
if (values != null) {
itemsToAdd[key] = values
} else {
remove(key)
}
return this
}
override fun putInt(key: String, value: Int): SharedPreferences.Editor {
itemsToAdd[key] = value
return this
}
override fun putLong(key: String, value: Long): SharedPreferences.Editor {
itemsToAdd[key] = value
return this
}
override fun putFloat(key: String, value: Float): SharedPreferences.Editor {
itemsToAdd[key] = value
return this
}
override fun putBoolean(key: String, value: Boolean): SharedPreferences.Editor {
itemsToAdd[key] = value
return this
}
override fun remove(key: String): SharedPreferences.Editor {
itemsToAdd.remove(key)
return this
}
override fun clear(): SharedPreferences.Editor {
itemsToAdd.clear()
return this
}
override fun commit(): Boolean {
addToPreferences()
return true
}
override fun apply() {
addToPreferences()
}
private fun addToPreferences() {
itemsToAdd.forEach { (key, value) ->
@Suppress("UNCHECKED_CAST")
when (value) {
is Set<*> -> preferences.encodeValue(SetSerializer(String.serializer()), key, value as Set<String>)
is String -> preferences.putString(key, value)
is Int -> preferences.putInt(key, value)
is Long -> preferences.putLong(key, value)
is Float -> preferences.putFloat(key, value)
is Double -> preferences.putDouble(key, value)
is Boolean -> preferences.putBoolean(key, value)
}
}
}
}
override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
val javaListener = PreferenceChangeListener {
listener.onSharedPreferenceChanged(this, it.key)
}
listeners[listener] = javaListener
javaPreferences.addPreferenceChangeListener(javaListener)
}
override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
val registeredListener = listeners.remove(listener)
if (registeredListener != null) {
javaPreferences.removePreferenceChangeListener(registeredListener)
}
}
fun deleteAll(): Boolean {
javaPreferences.removeNode()
return true
}
}
@@ -233,7 +233,7 @@ public class JsonSharedPreferences implements SharedPreferences {
private JsonSharedPreferencesEditor() {
}
private void recordChange(String key) {
private void recordChange(String key) {
if (!affectedKeys.contains(key)) {
affectedKeys.add(key);
}
@@ -14,8 +14,6 @@ import java.io.File
import javax.imageio.ImageIO
import javax.xml.parsers.DocumentBuilderFactory
data class InstalledPackage(val root: File) {
val apk = File(root, "package.apk")
val jar = File(root, "translated.jar")
@@ -40,20 +38,24 @@ data class InstalledPackage(val root: File) {
}?.filter {
it.tagName == "meta-data"
}?.map {
putString(it.attributes.getNamedItem("android:name").nodeValue,
it.attributes.getNamedItem("android:value").nodeValue)
putString(
it.attributes.getNamedItem("android:name").nodeValue,
it.attributes.getNamedItem("android:value").nodeValue
)
}
}
it.signatures = (parsed.apkSingers.flatMap { it.certificateMetas }
/*+ parsed.apkV2Singers.flatMap { it.certificateMetas }*/) // Blocked by: https://github.com/hsiafan/apk-parser/issues/72
.map { Signature(it.data) }.toTypedArray()
it.signatures = (
parsed.apkSingers.flatMap { it.certificateMetas }
/*+ parsed.apkV2Singers.flatMap { it.certificateMetas }*/
) // Blocked by: https://github.com/hsiafan/apk-parser/issues/72
.map { Signature(it.data) }.toTypedArray()
}
fun verify(): Boolean {
val res = ApkVerifier.Builder(apk)
.build()
.verify()
.build()
.verify()
return res.isVerified
}
@@ -69,7 +71,7 @@ data class InstalledPackage(val root: File) {
}.sortedByDescending { it.width * it.height }.firstOrNull() ?: return
ImageIO.write(read, "png", icon)
} catch(e: Exception) {
} catch (e: Exception) {
icon.delete()
}
}
@@ -77,7 +79,7 @@ data class InstalledPackage(val root: File) {
fun writeJar() {
try {
Dex2jar.from(apk).to(jar.toPath())
} catch(e: Exception) {
} catch (e: Exception) {
jar.delete()
}
}
@@ -92,4 +94,4 @@ data class InstalledPackage(val root: File) {
return out
}
}
}
}
@@ -48,7 +48,7 @@ class PackageController {
if (!installed.jar.exists()) {
throw IllegalStateException("Failed to translate APK dex!")
}
} catch(t: Throwable) {
} catch (t: Throwable) {
root.deleteRecursively()
throw t
}
@@ -63,7 +63,7 @@ class PackageController {
}
fun deletePackage(pack: InstalledPackage) {
if(!pack.root.exists()) error("Package was never installed!")
if (!pack.root.exists()) error("Package was never installed!")
val packageName = pack.info.packageName
pack.root.deleteRecursively()
@@ -74,7 +74,7 @@ class PackageController {
fun findPackage(packageName: String): InstalledPackage? {
val file = File(androidFiles.packagesDir, packageName)
return if(file.exists())
return if (file.exists())
InstalledPackage(file)
else
null
@@ -84,4 +84,4 @@ class PackageController {
val pkgName = ApkParsers.getMetaInfo(apkFile).packageName
return findPackage(pkgName)?.jar
}
}
}
@@ -24,4 +24,4 @@ fun ApkMeta.toPackageInfo(apk: File): PackageInfo {
sourceDir = apk.absolutePath
}
}
}
}
@@ -0,0 +1,249 @@
package xyz.nulldev.androidcompat.replace.java.text;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
public class NumberFormat extends java.text.NumberFormat {
private com.ibm.icu.text.NumberFormat delegate;
public NumberFormat(com.ibm.icu.text.NumberFormat delegate) {
this.delegate = delegate;
}
public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public String format(BigInteger number) {
return delegate.format(number);
}
public String format(BigDecimal number) {
return delegate.format(number);
}
public String format(com.ibm.icu.math.BigDecimal number) {
return delegate.format(number);
}
public String format(CurrencyAmount currAmt) {
return delegate.format(currAmt);
}
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public StringBuffer format(com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(number, toAppendTo, pos);
}
public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(currAmt, toAppendTo, pos);
}
public Number parse(String text, ParsePosition parsePosition) {
return delegate.parse(text, parsePosition);
}
public Number parse(String text) throws ParseException {
return delegate.parse(text);
}
public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) {
return delegate.parseCurrency(text, pos);
}
public boolean isParseIntegerOnly() {
return delegate.isParseIntegerOnly();
}
public void setParseIntegerOnly(boolean value) {
delegate.setParseIntegerOnly(value);
}
public void setParseStrict(boolean value) {
delegate.setParseStrict(value);
}
public boolean isParseStrict() {
return delegate.isParseStrict();
}
public void setContext(DisplayContext context) {
delegate.setContext(context);
}
public DisplayContext getContext(DisplayContext.Type type) {
return delegate.getContext(type);
}
public static java.text.NumberFormat getInstance(Locale inLocale) {
return new NumberFormat(com.ibm.icu.text.NumberFormat.getInstance(inLocale));
}
public static com.ibm.icu.text.NumberFormat getInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getInstance(inLocale);
}
public static com.ibm.icu.text.NumberFormat getInstance(int style) {
return com.ibm.icu.text.NumberFormat.getInstance(style);
}
public static com.ibm.icu.text.NumberFormat getInstance(Locale inLocale, int style) {
return com.ibm.icu.text.NumberFormat.getInstance(inLocale, style);
}
public static com.ibm.icu.text.NumberFormat getNumberInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getNumberInstance(inLocale);
}
public static com.ibm.icu.text.NumberFormat getIntegerInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getIntegerInstance(inLocale);
}
public static com.ibm.icu.text.NumberFormat getCurrencyInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getCurrencyInstance(inLocale);
}
public static com.ibm.icu.text.NumberFormat getPercentInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getPercentInstance(inLocale);
}
public static com.ibm.icu.text.NumberFormat getScientificInstance(ULocale inLocale) {
return com.ibm.icu.text.NumberFormat.getScientificInstance(inLocale);
}
public static Locale[] getAvailableLocales() {
return com.ibm.icu.text.NumberFormat.getAvailableLocales();
}
public static ULocale[] getAvailableULocales() {
return com.ibm.icu.text.NumberFormat.getAvailableULocales();
}
public static Object registerFactory(com.ibm.icu.text.NumberFormat.NumberFormatFactory factory) {
return com.ibm.icu.text.NumberFormat.registerFactory(factory);
}
public static boolean unregister(Object registryKey) {
return com.ibm.icu.text.NumberFormat.unregister(registryKey);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public Object clone() {
return delegate.clone();
}
public boolean isGroupingUsed() {
return delegate.isGroupingUsed();
}
public void setGroupingUsed(boolean newValue) {
delegate.setGroupingUsed(newValue);
}
public int getMaximumIntegerDigits() {
return delegate.getMaximumIntegerDigits();
}
public void setMaximumIntegerDigits(int newValue) {
delegate.setMaximumIntegerDigits(newValue);
}
public int getMinimumIntegerDigits() {
return delegate.getMinimumIntegerDigits();
}
public void setMinimumIntegerDigits(int newValue) {
delegate.setMinimumIntegerDigits(newValue);
}
public int getMaximumFractionDigits() {
return delegate.getMaximumFractionDigits();
}
public void setMaximumFractionDigits(int newValue) {
delegate.setMaximumFractionDigits(newValue);
}
public int getMinimumFractionDigits() {
return delegate.getMinimumFractionDigits();
}
public void setMinimumFractionDigits(int newValue) {
delegate.setMinimumFractionDigits(newValue);
}
public void setCurrency(Currency theCurrency) {
delegate.setCurrency(theCurrency);
}
public java.util.Currency getCurrency() {
return java.util.Currency.getInstance(delegate.getCurrency().getCurrencyCode());
}
public void setRoundingMode(int roundingMode) {
delegate.setRoundingMode(roundingMode);
}
public static com.ibm.icu.text.NumberFormat getInstance(ULocale desiredLocale, int choice) {
return com.ibm.icu.text.NumberFormat.getInstance(desiredLocale, choice);
}
@Deprecated
public static String getPatternForStyle(ULocale forLocale, int choice) {
return com.ibm.icu.text.NumberFormat.getPatternForStyle(forLocale, choice);
}
public ULocale getLocale(ULocale.Type type) {
return delegate.getLocale(type);
}
public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
return delegate.formatToCharacterIterator(obj);
}
public Object parseObject(String source) throws ParseException {
return delegate.parseObject(source);
}
}
@@ -0,0 +1,346 @@
package xyz.nulldev.androidcompat.replace.java.text;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.TimeZoneFormat;
import com.ibm.icu.util.ULocale;
import xyz.nulldev.androidcompat.replace.java.util.Calendar;
import xyz.nulldev.androidcompat.replace.java.util.TimeZone;
import java.text.*;
import java.util.Date;
import java.util.Locale;
/**
* Overridden to switch to Android implementation
*/
public class SimpleDateFormat extends java.text.DateFormat {
private com.ibm.icu.text.SimpleDateFormat delegate;
public SimpleDateFormat() {
delegate = new com.ibm.icu.text.SimpleDateFormat();
}
private SimpleDateFormat(com.ibm.icu.text.SimpleDateFormat delegate) {
this.delegate = delegate;
}
public SimpleDateFormat(String pattern) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern);
}
public SimpleDateFormat(String pattern, Locale loc) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern, loc);
}
public SimpleDateFormat(String pattern, ULocale loc) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern, loc);
}
public SimpleDateFormat(String pattern, String override, ULocale loc) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern, override, loc);
}
public SimpleDateFormat(String pattern, DateFormatSymbols formatData) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern, formatData);
}
public SimpleDateFormat(String pattern, DateFormatSymbols formatData, ULocale loc) {
delegate = new com.ibm.icu.text.SimpleDateFormat(pattern, formatData, loc);
}
@Deprecated
public static SimpleDateFormat getInstance(com.ibm.icu.util.Calendar.FormatConfiguration formatConfig) {
return new SimpleDateFormat(com.ibm.icu.text.SimpleDateFormat.getInstance(formatConfig));
}
public void set2DigitYearStart(Date startDate) {
delegate.set2DigitYearStart(startDate);
}
public Date get2DigitYearStart() {
return delegate.get2DigitYearStart();
}
public void setContext(DisplayContext context) {
delegate.setContext(context);
}
public StringBuffer format(com.ibm.icu.util.Calendar cal, StringBuffer toAppendTo, FieldPosition pos) {
return delegate.format(cal, toAppendTo, pos);
}
public void setNumberFormat(com.ibm.icu.text.NumberFormat newNumberFormat) {
delegate.setNumberFormat(newNumberFormat);
}
public void parse(String text, com.ibm.icu.util.Calendar cal, ParsePosition parsePos) {
delegate.parse(text, cal, parsePos);
}
public String toPattern() {
return delegate.toPattern();
}
public String toLocalizedPattern() {
return delegate.toLocalizedPattern();
}
public void applyPattern(String pat) {
delegate.applyPattern(pat);
}
public void applyLocalizedPattern(String pat) {
delegate.applyLocalizedPattern(pat);
}
public DateFormatSymbols getDateFormatSymbols() {
return delegate.getDateFormatSymbols();
}
public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) {
delegate.setDateFormatSymbols(newFormatSymbols);
}
public TimeZoneFormat getTimeZoneFormat() {
return delegate.getTimeZoneFormat();
}
public void setTimeZoneFormat(TimeZoneFormat tzfmt) {
delegate.setTimeZoneFormat(tzfmt);
}
@Override
public Object clone() {
return delegate.clone();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
return delegate.formatToCharacterIterator(obj);
}
@Deprecated
public StringBuffer intervalFormatByAlgorithm(com.ibm.icu.util.Calendar fromCalendar, com.ibm.icu.util.Calendar toCalendar, StringBuffer appendTo, FieldPosition pos) throws IllegalArgumentException {
return delegate.intervalFormatByAlgorithm(fromCalendar, toCalendar, appendTo, pos);
}
public void setNumberFormat(String fields, com.ibm.icu.text.NumberFormat overrideNF) {
delegate.setNumberFormat(fields, overrideNF);
}
public com.ibm.icu.text.NumberFormat getNumberFormat(char field) {
return delegate.getNumberFormat(field);
}
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
return delegate.format(date, toAppendTo, fieldPosition);
}
@Override
public Date parse(String text) throws ParseException {
return delegate.parse(text);
}
@Override
public Date parse(String text, ParsePosition pos) {
return delegate.parse(text, pos);
}
@Override
public Object parseObject(String source, ParsePosition pos) {
return delegate.parseObject(source, pos);
}
public static com.ibm.icu.text.DateFormat getTimeInstance(int style, ULocale locale) {
return com.ibm.icu.text.DateFormat.getTimeInstance(style, locale);
}
public static com.ibm.icu.text.DateFormat getDateInstance(int style, ULocale locale) {
return com.ibm.icu.text.DateFormat.getDateInstance(style, locale);
}
public static com.ibm.icu.text.DateFormat getDateTimeInstance(int dateStyle, int timeStyle, ULocale locale) {
return com.ibm.icu.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
}
public static Locale[] getAvailableLocales() {
return com.ibm.icu.text.DateFormat.getAvailableLocales();
}
public static ULocale[] getAvailableULocales() {
return com.ibm.icu.text.DateFormat.getAvailableULocales();
}
@Override
public void setCalendar(java.util.Calendar newCalendar) {
com.ibm.icu.util.Calendar cal = com.ibm.icu.util.Calendar.getInstance(com.ibm.icu.util.TimeZone.getTimeZone(newCalendar.getTimeZone().getID()));
cal.setTimeInMillis(newCalendar.getTimeInMillis());
delegate.setCalendar(cal);
}
@Override
public java.util.Calendar getCalendar() {
return new Calendar(delegate.getCalendar());
}
@Override
public java.text.NumberFormat getNumberFormat() {
return new NumberFormat(delegate.getNumberFormat());
}
@Override
public void setTimeZone(java.util.TimeZone zone) {
delegate.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(zone.getID()));
}
@Override
public java.util.TimeZone getTimeZone() {
return new TimeZone(delegate.getTimeZone());
}
@Override
public void setLenient(boolean lenient) {
delegate.setLenient(lenient);
}
@Override
public boolean isLenient() {
return delegate.isLenient();
}
public void setCalendarLenient(boolean lenient) {
delegate.setCalendarLenient(lenient);
}
public boolean isCalendarLenient() {
return delegate.isCalendarLenient();
}
public com.ibm.icu.text.DateFormat setBooleanAttribute(com.ibm.icu.text.DateFormat.BooleanAttribute key, boolean value) {
return delegate.setBooleanAttribute(key, value);
}
public boolean getBooleanAttribute(com.ibm.icu.text.DateFormat.BooleanAttribute key) {
return delegate.getBooleanAttribute(key);
}
public DisplayContext getContext(DisplayContext.Type type) {
return delegate.getContext(type);
}
public static com.ibm.icu.text.DateFormat getDateInstance(com.ibm.icu.util.Calendar cal, int dateStyle, Locale locale) {
return com.ibm.icu.text.DateFormat.getDateInstance(cal, dateStyle, locale);
}
public static com.ibm.icu.text.DateFormat getDateInstance(com.ibm.icu.util.Calendar cal, int dateStyle, ULocale locale) {
return com.ibm.icu.text.DateFormat.getDateInstance(cal, dateStyle, locale);
}
public static com.ibm.icu.text.DateFormat getTimeInstance(com.ibm.icu.util.Calendar cal, int timeStyle, Locale locale) {
return com.ibm.icu.text.DateFormat.getTimeInstance(cal, timeStyle, locale);
}
public static com.ibm.icu.text.DateFormat getTimeInstance(com.ibm.icu.util.Calendar cal, int timeStyle, ULocale locale) {
return com.ibm.icu.text.DateFormat.getTimeInstance(cal, timeStyle, locale);
}
public static com.ibm.icu.text.DateFormat getDateTimeInstance(com.ibm.icu.util.Calendar cal, int dateStyle, int timeStyle, Locale locale) {
return com.ibm.icu.text.DateFormat.getDateTimeInstance(cal, dateStyle, timeStyle, locale);
}
public static com.ibm.icu.text.DateFormat getDateTimeInstance(com.ibm.icu.util.Calendar cal, int dateStyle, int timeStyle, ULocale locale) {
return com.ibm.icu.text.DateFormat.getDateTimeInstance(cal, dateStyle, timeStyle, locale);
}
public static com.ibm.icu.text.DateFormat getInstance(com.ibm.icu.util.Calendar cal, Locale locale) {
return com.ibm.icu.text.DateFormat.getInstance(cal, locale);
}
public static com.ibm.icu.text.DateFormat getInstance(com.ibm.icu.util.Calendar cal, ULocale locale) {
return com.ibm.icu.text.DateFormat.getInstance(cal, locale);
}
public static com.ibm.icu.text.DateFormat getInstance(com.ibm.icu.util.Calendar cal) {
return com.ibm.icu.text.DateFormat.getInstance(cal);
}
public static com.ibm.icu.text.DateFormat getDateInstance(com.ibm.icu.util.Calendar cal, int dateStyle) {
return com.ibm.icu.text.DateFormat.getDateInstance(cal, dateStyle);
}
public static com.ibm.icu.text.DateFormat getTimeInstance(com.ibm.icu.util.Calendar cal, int timeStyle) {
return com.ibm.icu.text.DateFormat.getTimeInstance(cal, timeStyle);
}
public static com.ibm.icu.text.DateFormat getDateTimeInstance(com.ibm.icu.util.Calendar cal, int dateStyle, int timeStyle) {
return com.ibm.icu.text.DateFormat.getDateTimeInstance(cal, dateStyle, timeStyle);
}
public static com.ibm.icu.text.DateFormat getInstanceForSkeleton(String skeleton) {
return com.ibm.icu.text.DateFormat.getInstanceForSkeleton(skeleton);
}
public static com.ibm.icu.text.DateFormat getInstanceForSkeleton(String skeleton, Locale locale) {
return com.ibm.icu.text.DateFormat.getInstanceForSkeleton(skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getInstanceForSkeleton(String skeleton, ULocale locale) {
return com.ibm.icu.text.DateFormat.getInstanceForSkeleton(skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getInstanceForSkeleton(com.ibm.icu.util.Calendar cal, String skeleton, Locale locale) {
return com.ibm.icu.text.DateFormat.getInstanceForSkeleton(cal, skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getInstanceForSkeleton(com.ibm.icu.util.Calendar cal, String skeleton, ULocale locale) {
return com.ibm.icu.text.DateFormat.getInstanceForSkeleton(cal, skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getPatternInstance(String skeleton) {
return com.ibm.icu.text.DateFormat.getPatternInstance(skeleton);
}
public static com.ibm.icu.text.DateFormat getPatternInstance(String skeleton, Locale locale) {
return com.ibm.icu.text.DateFormat.getPatternInstance(skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getPatternInstance(String skeleton, ULocale locale) {
return com.ibm.icu.text.DateFormat.getPatternInstance(skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getPatternInstance(com.ibm.icu.util.Calendar cal, String skeleton, Locale locale) {
return com.ibm.icu.text.DateFormat.getPatternInstance(cal, skeleton, locale);
}
public static com.ibm.icu.text.DateFormat getPatternInstance(com.ibm.icu.util.Calendar cal, String skeleton, ULocale locale) {
return com.ibm.icu.text.DateFormat.getPatternInstance(cal, skeleton, locale);
}
public ULocale getLocale(ULocale.Type type) {
return delegate.getLocale(type);
}
@Override
public Object parseObject(String source) throws ParseException {
return delegate.parseObject(source);
}
}
@@ -0,0 +1,294 @@
package xyz.nulldev.androidcompat.replace.java.util;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.util.ULocale;
import java.util.Date;
import java.util.Locale;
public class Calendar extends java.util.Calendar {
private com.ibm.icu.util.Calendar delegate;
public Calendar(com.ibm.icu.util.Calendar delegate) {
this.delegate = delegate;
}
public static java.util.Calendar getInstance() {
return new Calendar(com.ibm.icu.util.Calendar.getInstance());
}
public static com.ibm.icu.util.Calendar getInstance(com.ibm.icu.util.TimeZone zone) {
return com.ibm.icu.util.Calendar.getInstance(zone);
}
public static java.util.Calendar getInstance(Locale aLocale) {
return new Calendar(com.ibm.icu.util.Calendar.getInstance(aLocale));
}
public static com.ibm.icu.util.Calendar getInstance(ULocale locale) {
return com.ibm.icu.util.Calendar.getInstance(locale);
}
public static com.ibm.icu.util.Calendar getInstance(com.ibm.icu.util.TimeZone zone, Locale aLocale) {
return com.ibm.icu.util.Calendar.getInstance(zone, aLocale);
}
public static com.ibm.icu.util.Calendar getInstance(com.ibm.icu.util.TimeZone zone, ULocale locale) {
return com.ibm.icu.util.Calendar.getInstance(zone, locale);
}
public static Locale[] getAvailableLocales() {
return com.ibm.icu.util.Calendar.getAvailableLocales();
}
@Override
protected void computeTime() {}
@Override
protected void computeFields() {}
public static ULocale[] getAvailableULocales() {
return com.ibm.icu.util.Calendar.getAvailableULocales();
}
public static String[] getKeywordValuesForLocale(String key, ULocale locale, boolean commonlyUsed) {
return com.ibm.icu.util.Calendar.getKeywordValuesForLocale(key, locale, commonlyUsed);
}
@Override
public long getTimeInMillis() {
return delegate.getTimeInMillis();
}
@Override
public void setTimeInMillis(long millis) {
delegate.setTimeInMillis(millis);
}
@Deprecated
public int getRelatedYear() {
return delegate.getRelatedYear();
}
@Deprecated
public void setRelatedYear(int year) {
delegate.setRelatedYear(year);
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
public boolean isEquivalentTo(com.ibm.icu.util.Calendar other) {
return delegate.isEquivalentTo(other);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean before(Object when) {
return delegate.before(when);
}
@Override
public boolean after(Object when) {
return delegate.after(when);
}
@Override
public int getActualMaximum(int field) {
return delegate.getActualMaximum(field);
}
@Override
public int getActualMinimum(int field) {
return delegate.getActualMinimum(field);
}
@Override
public void roll(int field, int amount) {
delegate.roll(field, amount);
}
@Override
public void add(int field, int amount) {
delegate.add(field, amount);
}
@Override
public void roll(int field, boolean up) {
roll(field, up ? 1 : -1);
}
public String getDisplayName(Locale loc) {
return delegate.getDisplayName(loc);
}
public String getDisplayName(ULocale loc) {
return delegate.getDisplayName(loc);
}
public int compareTo(com.ibm.icu.util.Calendar that) {
return delegate.compareTo(that);
}
public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, Locale loc) {
return delegate.getDateTimeFormat(dateStyle, timeStyle, loc);
}
public DateFormat getDateTimeFormat(int dateStyle, int timeStyle, ULocale loc) {
return delegate.getDateTimeFormat(dateStyle, timeStyle, loc);
}
@Deprecated
public static String getDateTimePattern(com.ibm.icu.util.Calendar cal, ULocale uLocale, int dateStyle) {
return com.ibm.icu.util.Calendar.getDateTimePattern(cal, uLocale, dateStyle);
}
public int fieldDifference(Date when, int field) {
return delegate.fieldDifference(when, field);
}
public void setTimeZone(com.ibm.icu.util.TimeZone value) {
delegate.setTimeZone(value);
}
@Override
public java.util.TimeZone getTimeZone() {
return new TimeZone(delegate.getTimeZone());
}
@Override
public void setLenient(boolean lenient) {
delegate.setLenient(lenient);
}
@Override
public boolean isLenient() {
return delegate.isLenient();
}
public void setRepeatedWallTimeOption(int option) {
delegate.setRepeatedWallTimeOption(option);
}
public int getRepeatedWallTimeOption() {
return delegate.getRepeatedWallTimeOption();
}
public void setSkippedWallTimeOption(int option) {
delegate.setSkippedWallTimeOption(option);
}
public int getSkippedWallTimeOption() {
return delegate.getSkippedWallTimeOption();
}
@Override
public void setFirstDayOfWeek(int value) {
delegate.setFirstDayOfWeek(value);
}
@Override
public int getFirstDayOfWeek() {
return delegate.getFirstDayOfWeek();
}
@Override
public void setMinimalDaysInFirstWeek(int value) {
delegate.setMinimalDaysInFirstWeek(value);
}
@Override
public int getMinimalDaysInFirstWeek() {
return delegate.getMinimalDaysInFirstWeek();
}
@Override
public int getMinimum(int field) {
return delegate.getMinimum(field);
}
@Override
public int getMaximum(int field) {
return delegate.getMaximum(field);
}
@Override
public int getGreatestMinimum(int field) {
return delegate.getGreatestMinimum(field);
}
@Override
public int getLeastMaximum(int field) {
return delegate.getLeastMaximum(field);
}
@Deprecated
public int getDayOfWeekType(int dayOfWeek) {
return delegate.getDayOfWeekType(dayOfWeek);
}
@Deprecated
public int getWeekendTransition(int dayOfWeek) {
return delegate.getWeekendTransition(dayOfWeek);
}
public boolean isWeekend(Date date) {
return delegate.isWeekend(date);
}
public boolean isWeekend() {
return delegate.isWeekend();
}
@Override
public Object clone() {
return delegate.clone();
}
@Override
public String toString() {
return delegate.toString();
}
public static com.ibm.icu.util.Calendar.WeekData getWeekDataForRegion(String region) {
return com.ibm.icu.util.Calendar.getWeekDataForRegion(region);
}
public com.ibm.icu.util.Calendar.WeekData getWeekData() {
return delegate.getWeekData();
}
public com.ibm.icu.util.Calendar setWeekData(com.ibm.icu.util.Calendar.WeekData wdata) {
return delegate.setWeekData(wdata);
}
public int getFieldCount() {
return delegate.getFieldCount();
}
public String getType() {
return delegate.getType();
}
@Deprecated
public boolean haveDefaultCentury() {
return delegate.haveDefaultCentury();
}
public ULocale getLocale(ULocale.Type type) {
return delegate.getLocale(type);
}
}
@@ -0,0 +1,196 @@
package xyz.nulldev.androidcompat.replace.java.util;
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import com.ibm.icu.util.ULocale;
import java.util.Date;
import java.util.Locale;
import java.util.Set;
public class TimeZone extends java.util.TimeZone {
private com.ibm.icu.util.TimeZone delegate;
public TimeZone(com.ibm.icu.util.TimeZone delegate) {
this.delegate = delegate;
}
@Override
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
return delegate.getOffset(era, year, month, day, dayOfWeek, milliseconds);
}
@Override
public int getOffset(long date) {
return delegate.getOffset(date);
}
public void getOffset(long date, boolean local, int[] offsets) {
delegate.getOffset(date, local, offsets);
}
@Override
public void setRawOffset(int offsetMillis) {
delegate.setRawOffset(offsetMillis);
}
@Override
public int getRawOffset() {
return delegate.getRawOffset();
}
@Override
public String getID() {
return delegate.getID();
}
@Override
public void setID(String ID) {
delegate.setID(ID);
}
public String getDisplayName(ULocale locale) {
return delegate.getDisplayName(locale);
}
@Override
public String getDisplayName(boolean daylight, int style, Locale locale) {
return delegate.getDisplayName(daylight, style, locale);
}
public String getDisplayName(boolean daylight, int style, ULocale locale) {
return delegate.getDisplayName(daylight, style, locale);
}
@Override
public int getDSTSavings() {
return delegate.getDSTSavings();
}
@Override
public boolean useDaylightTime() {
return delegate.useDaylightTime();
}
@Override
public boolean observesDaylightTime() {
return delegate.observesDaylightTime();
}
@Override
public boolean inDaylightTime(Date date) {
return delegate.inDaylightTime(date);
}
public static java.util.TimeZone getTimeZone(String ID) {
return new TimeZone(com.ibm.icu.util.TimeZone.getTimeZone(ID));
}
public static com.ibm.icu.util.TimeZone getFrozenTimeZone(String ID) {
return com.ibm.icu.util.TimeZone.getFrozenTimeZone(ID);
}
public static com.ibm.icu.util.TimeZone getTimeZone(String ID, int type) {
return com.ibm.icu.util.TimeZone.getTimeZone(ID, type);
}
public static void setDefaultTimeZoneType(int type) {
com.ibm.icu.util.TimeZone.setDefaultTimeZoneType(type);
}
public static int getDefaultTimeZoneType() {
return com.ibm.icu.util.TimeZone.getDefaultTimeZoneType();
}
public static Set<String> getAvailableIDs(com.ibm.icu.util.TimeZone.SystemTimeZoneType zoneType, String region, Integer rawOffset) {
return com.ibm.icu.util.TimeZone.getAvailableIDs(zoneType, region, rawOffset);
}
public static String[] getAvailableIDs(int rawOffset) {
return com.ibm.icu.util.TimeZone.getAvailableIDs(rawOffset);
}
public static String[] getAvailableIDs(String country) {
return com.ibm.icu.util.TimeZone.getAvailableIDs(country);
}
public static String[] getAvailableIDs() {
return com.ibm.icu.util.TimeZone.getAvailableIDs();
}
public static int countEquivalentIDs(String id) {
return com.ibm.icu.util.TimeZone.countEquivalentIDs(id);
}
public static String getEquivalentID(String id, int index) {
return com.ibm.icu.util.TimeZone.getEquivalentID(id, index);
}
public static java.util.TimeZone getDefault() {
return new TimeZone(com.ibm.icu.util.TimeZone.getDefault());
}
public static void setDefault(com.ibm.icu.util.TimeZone tz) {
com.ibm.icu.util.TimeZone.setDefault(tz);
}
public boolean hasSameRules(com.ibm.icu.util.TimeZone other) {
return delegate.hasSameRules(other);
}
@Override
public Object clone() {
return delegate.clone();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
public static String getTZDataVersion() {
return com.ibm.icu.util.TimeZone.getTZDataVersion();
}
public static String getCanonicalID(String id) {
return com.ibm.icu.util.TimeZone.getCanonicalID(id);
}
public static String getCanonicalID(String id, boolean[] isSystemID) {
return com.ibm.icu.util.TimeZone.getCanonicalID(id, isSystemID);
}
public static String getRegion(String id) {
return com.ibm.icu.util.TimeZone.getRegion(id);
}
public static String getWindowsID(String id) {
return com.ibm.icu.util.TimeZone.getWindowsID(id);
}
public static String getIDForWindowsID(String winid, String region) {
return com.ibm.icu.util.TimeZone.getIDForWindowsID(winid, region);
}
public boolean isFrozen() {
return delegate.isFrozen();
}
public com.ibm.icu.util.TimeZone freeze() {
return delegate.freeze();
}
public com.ibm.icu.util.TimeZone cloneAsThawed() {
return delegate.cloneAsThawed();
}
}
@@ -24,4 +24,4 @@ interface Resource {
fun getType(): Class<out Resource>
fun getValue(): Any?
}
}
@@ -18,7 +18,7 @@ class ServiceSupport {
private val logger = KotlinLogging.logger {}
fun startService(context: Context, intent: Intent) {
fun startService(@Suppress("UNUSED_PARAMETER") context: Context, intent: Intent) {
val name = intentToClassName(intent)
logger.debug { "Starting service: $name" }
@@ -27,15 +27,15 @@ class ServiceSupport {
runningServices[name] = service
//Setup service
// Setup service
thread {
callOnCreate(service)
//TODO Handle more complex cases
// TODO Handle more complex cases
service.onStartCommand(intent, 0, 0)
}
}
fun stopService(context: Context, intent: Intent) {
fun stopService(@Suppress("UNUSED_PARAMETER") context: Context, intent: Intent) {
val name = intentToClassName(intent)
stopService(name)
}
@@ -43,7 +43,7 @@ class ServiceSupport {
fun stopService(name: String) {
logger.debug { "Stopping service: $name" }
val service = runningServices.remove(name)
if(service == null) {
if (service == null) {
logger.warn { "An attempt was made to stop a service that is not running: $name" }
} else {
thread {
@@ -63,6 +63,6 @@ class ServiceSupport {
fun serviceInstanceFromClass(className: String): Service {
val clazzObj = Class.forName(className)
return clazzObj.getDeclaredConstructor().newInstance() as? Service
?: throw IllegalArgumentException("$className is not a Service!")
?: throw IllegalArgumentException("$className is not a Service!")
}
}
@@ -25,8 +25,9 @@ object KodeinGlobalHelper {
* Get a dependency
*/
@JvmStatic
@Suppress("UNCHECKED_CAST")
fun <T : Any> instance(type: Class<T>, kodein: DI? = null): T {
return when(type) {
return when (type) {
AndroidFiles::class.java -> {
val instance: AndroidFiles by (kodein ?: kodein()).instance()
instance as T
@@ -63,5 +64,4 @@ object KodeinGlobalHelper {
fun <T : Any> instance(type: Class<T>): T {
return instance(type, null)
}
}
@@ -1,36 +1,12 @@
# AndroidComapt Root dir
androidcompat.rootDir = androidcompat-root
# Allow/disallow preference changes (useful for demos)
ts.server.allowConfigChanges = true
# Enable the WebUI? Note: The API and multi-user sync server ui will remain available even if the WebUI is disabled
ts.server.enableWebUi = true
# 'true' to use the old, buggy/memory-leaking WebUI
ts.server.useOldWebUi = false
# 'true' to pretty print all JSON API responses
ts.server.prettyPrintApi = false
# List of blacklisted/whitelisted API endpoints/operation IDs
ts.server.disabledApiEndpoints = []
ts.server.enabledApiEndpoints = []
# Message to print in the console when the API has finished booting
ts.server.httpInitializedPrintMessage = ""
# Use external folder for static files
ts.server.useExternalStaticFiles = false
ts.server.externalStaticFilesFolder = ""
# Root storage dir
ts.server.rootDir = tachiserver-data
# Dir to store JVM patches
ts.server.patchesDir = ${ts.server.rootDir}/patches
####################### `android.files` (FilesConfigModule) #######################
# Storage dir for the emulated Android app
android.files.rootDir = ${ts.server.rootDir}/android-compat/appdata
android.files.rootDir = ${androidcompat.rootDir}/appdata
# External storage dir for the emulated Android app's
android.files.externalStorageDir = ${ts.server.rootDir}/android-compat/extappdata
android.files.externalStorageDir = ${androidcompat.rootDir}/extappdata
# Internal Android directories
android.files.dataDir = ${android.files.rootDir}/data
@@ -48,37 +24,16 @@ android.files.externalCacheDirs = [${android.files.externalStorageDir}/cache]
android.files.externalMediaDirs = [${android.files.externalStorageDir}/media]
android.files.downloadCacheDir = ${android.files.externalStorageDir}/downloadCache
android.files.packageDir = ${ts.server.rootDir}/android-compat/packages
android.files.packageDir = ${androidcompat.rootDir}/android-compat/packages
####################### `android.app` (ApplicationInfoConfigModule) #######################
# Emulated Android app package name
android.app.packageName = eu.kanade.tachiyomi
# Debug mode for the emulated Android app
android.app.debug = true
####################### `android.system` (SystemConfigModule) #######################
# Whether or not the emulated Android system is debuggable
android.system.isDebuggable = true
# Is the multi-user sync server enabled? Does not affect the single-user sync server included in the API.
ts.syncd.enable = false
# The URL of this server (displayed in the sync server web ui)
ts.syncd.baseUrl = "http://example.com"
# 'true' to disable the API and only enable the multi-user sync server
ts.syncd.syncOnlyMode = false
# The root directory to store synchronized data
ts.syncd.rootDir = ${ts.server.rootDir}/sync/accounts
# Location to store config files for the sandbox
ts.syncd.sandboxedConfig = ${ts.server.rootDir}/sync/sandboxed_config.config
# Recaptcha stuff for signup/login
ts.syncd.recaptcha.siteKey = ""
ts.syncd.recaptcha.secret = ""
# Sync server display name
ts.syncd.name = "Tachiyomi sync server"
# Header used to forward the IP to the multi-user sync server if the server is behind a reverse proxy
ts.syncd.ipHeader = ""
+11
View File
@@ -0,0 +1,11 @@
# Server: v0.X.Y-next + WebUI: rXXX
## TL;DR
- N/A
## Tachidesk-Server Changelog
- N/A
## Tachidesk-WebUI Changelog
- N/A
+557
View File
@@ -0,0 +1,557 @@
# Server: v0.6.4 + WebUI: r946
## TL;DR
- No new major features
- Bug fixes and changes for packaging
- Documentation changes
## Tachidesk-Server Changelog
- (r1087) v0.6.3 (by @AriaMoradi)
- (r1088) Save categories when manga is unfavorited ([#335](https://github.com/Suwayomi/Tachidesk-Server/pull/335) by @Syer10)
- (r1089) handle solid RAR archives ([#339](https://github.com/Suwayomi/Tachidesk-Server/pull/339)) cfso100@gmail.com
- (r1090) add support for changing downloads dir ([#343](https://github.com/Suwayomi/Tachidesk-Server/pull/343) by @AriaMoradi)
- (r1091) fix Applications dir dependency ([#344](https://github.com/Suwayomi/Tachidesk-Server/pull/344) by @AriaMoradi)
- (r1092) add support for alternative web interfaces ([#342](https://github.com/Suwayomi/Tachidesk-Server/pull/342) by @AriaMoradi)
- (r1093) Add displayValues json field for select filter ([#347](https://github.com/Suwayomi/Tachidesk-Server/pull/347) by @Syer10)
- (r1094) document manga endpoints ([#348](https://github.com/Suwayomi/Tachidesk-Server/pull/348) by @Syer10)
- (r1095) add ChapterCount to manga object in categoryMangas endpoint ([#349](https://github.com/Suwayomi/Tachidesk-Server/pull/349) by @abhijeetChawla)
- (r1096) document all endpoints ([#350](https://github.com/Suwayomi/Tachidesk-Server/pull/350) by @Syer10)
- (r1097) fix copymanga ([#354](https://github.com/Suwayomi/Tachidesk-Server/pull/354) by @AriaMoradi)
- (r1098) fix formatting by kotlinter (by @AriaMoradi)
- (r1099) bump WebUI (by @AriaMoradi)
- (r1100) fix WebUI release name (by @AriaMoradi)
- (r1101) Fix documentation errors ([#358](https://github.com/Suwayomi/scripts/pull/358) by @Syer10)
- (r1102) Docs improvements ([#359](https://github.com/Suwayomi/scripts/pull/359) by @Syer10)
- (r1103) Add linux-all.tar.gz & systemd service ([#366](https://github.com/Suwayomi/scripts/pull/366)) mahor1221@pm.me
- (r1104) Publish to Windows Package Managar (WinGet [#369](https://github.com/Suwayomi/scripts/pull/369)) 83997633+vedantmgoyal2009@users.noreply.github.com
- (r1105) Refactor scripts ([#370](https://github.com/Suwayomi/scripts/pull/370)) mahor1221@pm.me
- (r1106) Run workflow jobs toghether ([#371](https://github.com/Suwayomi/scripts/pull/371)) mahor1221@pm.me
- (r1107) Update gradle action ([#372](https://github.com/Suwayomi/scripts/pull/372)) mahor1221@pm.me
- (r1108) Improve DocumentationDsl, bugfix default values and add queryParams ([#378](https://github.com/Suwayomi/scripts/pull/378) by @Syer10)
- (r1109) Tidy up bundler script ([#380](https://github.com/Suwayomi/scripts/pull/380)) mahor1221@pm.me
- (r1110) Replace linux-all with linux-assets ([#381](https://github.com/Suwayomi/scripts/pull/381)) mahor1221@pm.me
- (r1111) Rename every instance of Tachidesk jar to Tachdidesk-Server.jar ([#384](https://github.com/Suwayomi/scripts/pull/384) by @AriaMoradi)
- (r1112) Fix mistakes from #384 ([#385](https://github.com/Suwayomi/scripts/pull/385) by @AriaMoradi)
## Tachidesk-WebUI Changelog
- (r943) fix default width ([#171](https://github.com/Suwayomi/Tachidesk-WebUI/pull/171) by @Robonau)
- (r944) added an update checker button for library ([#172](https://github.com/Suwayomi/Tachidesk-WebUI/pull/172) by @infix)
- (r945) fix download queue delete button ([#176](https://github.com/Suwayomi/Tachidesk-WebUI/pull/176) by @Kreach37)
- (r946) fix mangadex filters ([#177](https://github.com/Suwayomi/Tachidesk-WebUI/pull/177) by @Robonau)
# Server: v0.6.3 + WebUI: r942
## TL;DR
- Changes in Server
- Support for array search filter changes list
- Support for Tachiyomi extensions lib 1.3
- Changes in WebUI
- Better search filter support
- Fluid manga grid
- Library comfortable grid
- Sources view layouts
- Various other changes...
## Tachidesk-Server Changelog
- (r1074) v0.6.2 (by @AriaMoradi)
- (r1075) support array filter changes ([#304](https://github.com/Suwayomi/Tachidesk-Server/pull/304) by @AriaMoradi)
- (r1076) fix filterlist bugs ([#306](https://github.com/Suwayomi/Tachidesk-Server/pull/306) by @AriaMoradi)
- (r1077) Update README.md ([#305](https://github.com/Suwayomi/Tachidesk-Server/pull/305) by @mahor1221)
- (r1078) fix meta update changing all keys ([#314](https://github.com/Suwayomi/Tachidesk-Server/pull/314) by @AriaMoradi)
- (r1079) add support for tachiyomi extensions Lib 1.3 ([#316](https://github.com/Suwayomi/Tachidesk-Server/pull/316) by @AriaMoradi)
- (r1080) Fix sources list of one source throws an exception ([#308](https://github.com/Suwayomi/Tachidesk-Server/pull/308) by @Syer10)
- (r1081) Improve source handling, fix errors with uninitialized mangas in broken sources ([#319](https://github.com/Suwayomi/Tachidesk-Server/pull/319) by @Syer10)
- (r1082) Add thumbnail support for stub sources ([#320](https://github.com/Suwayomi/Tachidesk-Server/pull/320) by @Syer10)
- (r1083) update description for Tachidesk-Sorayomi ([#326](https://github.com/Suwayomi/Tachidesk-Server/pull/326) by @DattatreyaReddy)
- (r1084) Add last bit of code needed for Extensions Lib 1.3 ([#330](https://github.com/Suwayomi/Tachidesk-Server/pull/330) by @Syer10)
- (r1085) Add QuickJS, replaces Duktape for Extensions Lib 1.3 ([#331](https://github.com/Suwayomi/Tachidesk-Server/pull/331) by @Syer10)
- (r1086) fix auth not actually blocking requests ([#333](https://github.com/Suwayomi/Tachidesk-Server/pull/333) by @AriaMoradi)
## Tachidesk-WebUI Changelog
- (r930) Source filter scroll fix (array of filters on submit [#149](https://github.com/Suwayomi/Tachidesk-WebUI/pull/149) by @Robonau)
- (r931) fix manga badges setting menu that turns the update/download badges on and off ([#150](https://github.com/Suwayomi/Tachidesk-WebUI/pull/150) by @Robonau)
- (r932) move sorts to copy tachiyomi ([#151](https://github.com/Suwayomi/Tachidesk-WebUI/pull/151) by @Robonau)
- (r933) add comfortable grid option ([#152](https://github.com/Suwayomi/Tachidesk-WebUI/pull/152) by @Robonau)
- (r934) source layouts ([#153](https://github.com/Suwayomi/Tachidesk-WebUI/pull/153) by @Robonau)
- (r935) List layout ([#154](https://github.com/Suwayomi/Tachidesk-WebUI/pull/154) by @Robonau)
- (r936) in library badge to manga in sources ([#156](https://github.com/Suwayomi/Tachidesk-WebUI/pull/156) by @Robonau)
- (r937) mass search ([#157](https://github.com/Suwayomi/Tachidesk-WebUI/pull/157) by @Robonau)
- (r938) 18+ tag on source/extension cards ([#160](https://github.com/Suwayomi/Tachidesk-WebUI/pull/160) by @Robonau)
- (r939) fix search source click ([#164](https://github.com/Suwayomi/Tachidesk-WebUI/pull/164) by @Robonau)
- (r940) items per row setting ([#165](https://github.com/Suwayomi/Tachidesk-WebUI/pull/165) by @Robonau)
- (r941) fix the grid width thing ([#169](https://github.com/Suwayomi/Tachidesk-WebUI/pull/169) by @Robonau)
- (r942) unified library options ([#168](https://github.com/Suwayomi/Tachidesk-WebUI/pull/168) by @infix)
# Server: v0.6.2 + WebUI: r929
## TL;DR
- Changes in WebUI
- Moved search to Browse
- Support for Source Filters
- Better visuals for Download Queue
- A live version of WebUI is now available [at this link](https://tachidesk-webui-preview.github.io/).
## Tachidesk-Server Changelog
- (r1073) Refactor debian-packager.sh, rename launcher scripts ([#303](https://github.com/Suwayomi/Tachidesk-Server/pull/303) by @mahor1221)
## Tachidesk-WebUI Changelog
- (r912) show locale date, less confusing ([#131](https://github.com/Suwayomi/Tachidesk-WebUI/pull/131) by @AriaMoradi)
- (r913) fix links to work on a bare host ([#132](https://github.com/Suwayomi/Tachidesk-WebUI/pull/132) by @AriaMoradi)
- (r914) fix direct links ([#133](https://github.com/Suwayomi/Tachidesk-WebUI/pull/133) by @AriaMoradi)
- (r915) deploy to github pages (by @AriaMoradi)
- (r916) fix typo (by @AriaMoradi)
- (r917) better naming (by @AriaMoradi)
- (r918) update notice about github pages (by @AriaMoradi)
- (r919) move text (by @AriaMoradi)
- (r920) make all links work by catching 404 (by @AriaMoradi)
- (r921) fix scrolling 8px ([#135](https://github.com/Suwayomi/Tachidesk-WebUI/pull/135) by @Robonau)
- (r922) sorting ([#136](https://github.com/Suwayomi/Tachidesk-WebUI/pull/136) by @Robonau)
- (r923) Close button fix ([#141](https://github.com/Suwayomi/Tachidesk-WebUI/pull/141)) z14942744@gmail.com
- (r924) add NavBarContextProvider ([#128](https://github.com/Suwayomi/Tachidesk-WebUI/pull/128) by @abhijeetChawla)
- (r925) Resolved Merged Conflicts ([#127](https://github.com/Suwayomi/Tachidesk-WebUI/pull/127) by @abhijeetChawla)
- (r926) more Download Queue info ([#138](https://github.com/Suwayomi/Tachidesk-WebUI/pull/138) by @Robonau)
- (r927) Source filters, move search to SourceMangas ([#142](https://github.com/Suwayomi/Tachidesk-WebUI/pull/142) by @Robonau)
- (r928) Source genre sorts design ([#147](https://github.com/Suwayomi/Tachidesk-WebUI/pull/147) by @Robonau)
- (r929) Update LibraryOptions.tsx ([#146](https://github.com/Suwayomi/Tachidesk-WebUI/pull/146) by @Robonau)
# Server: v0.6.1 + WebUI: r911
## TL;DR
- msi and deb packages thanks to @mahor1221
- [Tachidesk-Flutter](https://github.com/Suwayomi/Tachidesk-Flutter) exists now!
## Tachidesk-Server Changelog
- (r1047) update (by @AriaMoradi)
- (r1048) bump version (by @AriaMoradi)
- (r1049) Update README.md (by @AriaMoradi)
- (r1050) Update README.md (by @AriaMoradi)
- (r1051) refactor getChapter ([#268](https://github.com/Suwayomi/Tachidesk-Server/pull/268) by @AriaMoradi)
- (r1052) Improve documentation with Http codes ([#261](https://github.com/Suwayomi/Tachidesk-Server/pull/261) by @Syer10)
- (r1053) Add Route to stop and reset the updater ([#260](https://github.com/Suwayomi/Tachidesk-Server/pull/260) by @ntbm)
- (r1054) ignore non image files ([#269](https://github.com/Suwayomi/Tachidesk-Server/pull/269) by @AriaMoradi)
- (r1055) fix compile erorr (by @AriaMoradi)
- (r1056) update dex2jar (by @AriaMoradi)
- (r1057) Update Gradle and Dependencies ([#281](https://github.com/Suwayomi/Tachidesk-Server/pull/281) by @Syer10)
- (r1058) Handlers must return a result ([#282](https://github.com/Suwayomi/Tachidesk-Server/pull/282) by @Syer10)
- (r1059) Allow app compilation on Java 18+ ([#286](https://github.com/Suwayomi/Tachidesk-Server/pull/286) by @Syer10)
- (r1060) Automated MSI package building ([#277](https://github.com/Suwayomi/Tachidesk-Server/pull/277) by @mahor1221)
- (r1061) Automated debian package building ([#287](https://github.com/Suwayomi/Tachidesk-Server/pull/287) by @mahor1221)
- (r1062) fix Debian package errors ([#288](https://github.com/Suwayomi/Tachidesk-Server/pull/288) by @mahor1221)
- (r1063) Fix build_push.yml Hopefully ([#289](https://github.com/Suwayomi/Tachidesk-Server/pull/289) by @mahor1221)
- (r1064) Improve windows-bundler.sh ([#290](https://github.com/Suwayomi/Tachidesk-Server/pull/290) by @mahor1221)
- (r1065) add Tachidesk-Flutter to readme ([#292](https://github.com/Suwayomi/Tachidesk-Server/pull/292)) @DattatreyaReddy)
- (r1066) no online fetch on backup ([#293](https://github.com/Suwayomi/Tachidesk-Server/pull/293) by @AriaMoradi)
- (r1067) auto-remove duplicate chapters ([#294](https://github.com/Suwayomi/Tachidesk-Server/pull/294) by @AriaMoradi)
- (r1068) remove gson ([#295](https://github.com/Suwayomi/Tachidesk-Server/pull/295) by @AriaMoradi)
## Tachidesk-WebUI Changelog
- (r894) migrate ReaderNavbar to Mui 5 ([#84](https://github.com/Suwayomi/Tachidesk-WebUI/pull/84) by @AriaMoradi)
- (r895) migrate SpinnerImage to Mui 5 ([#97](https://github.com/Suwayomi/Tachidesk-WebUI/pull/97) by @AriaMoradi)
- (r896) migrate VerticalPager to Mui 5 ([#94](https://github.com/Suwayomi/Tachidesk-WebUI/pull/94) by @AriaMoradi)
- (r897) migrate PagedPager to Mui 5 ([#93](https://github.com/Suwayomi/Tachidesk-WebUI/pull/93) by @AriaMoradi)
- (r898) MangaCard imges don't stretch now ([#110](https://github.com/Suwayomi/Tachidesk-WebUI/pull/110) by @abhijeetChawla)
- (r899) show correct title ([#111](https://github.com/Suwayomi/Tachidesk-WebUI/pull/111) by @AriaMoradi)
- (r900) migrate DoublePage to Mui 5 ([#88](https://github.com/Suwayomi/Tachidesk-WebUI/pull/88) by @AriaMoradi)
- (r901) migrate DoublePagedPager to Mui 5 ([#91](https://github.com/Suwayomi/Tachidesk-WebUI/pull/91) by @AriaMoradi)
- (r902) migrate Reader to Mui 5 ([#100](https://github.com/Suwayomi/Tachidesk-WebUI/pull/100) by @AriaMoradi)
- (r903) migrate HorizantalPager to Mui 5 ([#92](https://github.com/Suwayomi/Tachidesk-WebUI/pull/92) by @AriaMoradi)
- (r904) migrate PageNumber to Mui 5 ([#90](https://github.com/Suwayomi/Tachidesk-WebUI/pull/90) by @AriaMoradi)
- (r905) Chapter filter is woking ([#114](https://github.com/Suwayomi/Tachidesk-WebUI/pull/114) by @abhijeetChawla)
- (r906) added extension search ([#115](https://github.com/Suwayomi/Tachidesk-WebUI/pull/115) by @abhijeetChawla)
- (r907) cleanup ([#117](https://github.com/Suwayomi/Tachidesk-WebUI/pull/117) by @AriaMoradi)
- (r908) handle search shortcuts ([#116](https://github.com/Suwayomi/Tachidesk-WebUI/pull/116) by @AriaMoradi)
- (r909) Refactor for Removing unnecesary UseEffect ([#118](https://github.com/Suwayomi/Tachidesk-WebUI/pull/118) by @abhijeetChawla)
- (r910) refactor ChapterList ([#125](https://github.com/Suwayomi/Tachidesk-WebUI/pull/125) by @abhijeetChawla)
- (r911) refactor ChapterOptions ([#126](https://github.com/Suwayomi/Tachidesk-WebUI/pull/126) by @abhijeetChawla)
# Server: v0.6.0 + WebUI: r893
## TL;DR
- WebUI design went through a whole lot of changes, including
- Got rid of hamburger menu, now we have a custom mobile navbar
- Unread and Download count badges
- Back button so better electron experience
- There's a whole lot more that I'm too lazy to explore.
- Completely removed anime support
- Fixed category reordering
- Added support for search filters(Server side only)
- Added support for updating library(Server side only)
- A bunch of API breaking changes(hence why bumping to v0.6.0)!
## Tachidesk-Server Changelog
- (r996) cleanup (by @AriaMoradi)
- (r999) better cleaning algorithm (by @AriaMoradi)
- (r1007) remove anime support (by @AriaMoradi)
- (r1009) Fix tests ([#226](https://github.com/Suwayomi/Tachidesk-Server/pull/226) by @ntbm)
- (r1010) Expose unread and download count of Manga in category api ([#227](https://github.com/Suwayomi/Tachidesk-Server/pull/227) by @ntbm)
- (r1011) add Cache Header to Thumbnail Response for improved library performance ([#228](https://github.com/Suwayomi/Tachidesk-Server/pull/228) by @ntbm)
- (r1013) Fix unread and download counts casing ([#230](https://github.com/Suwayomi/Tachidesk-Server/pull/230) by @Syer10)
- (r1014) Fix broken test ([#231](https://github.com/Suwayomi/Tachidesk-Server/pull/231) by @ntbm)
- (r1016) Fix category reorder Endpoint. Added Test for Category Reorder ([#232](https://github.com/Suwayomi/Tachidesk-Server/pull/232) by @ntbm)
- (r1017) change windows bundle names (by @AriaMoradi)
- (r1018) improve tests (by @AriaMoradi)
- (r1019) allow injecting Sources (by @AriaMoradi)
- (r1020) update (by @AriaMoradi)
- (r1021) fix credit (by @AriaMoradi)
- (r1022) cleanup (by @AriaMoradi)
- (r1023) refactor (by @AriaMoradi)
- (r1024) refactor (by @AriaMoradi)
- (r1025) implement Source Filters (by @AriaMoradi)
- (r1026) ignore build artifacts generated by teting (by @AriaMoradi)
- (r1027) convert request type (by @AriaMoradi)
- (r1028) Update CONTRIBUTING.md (by @AriaMoradi)
- (r1029) stop supporting zero based image storage ([#242](https://github.com/Suwayomi/src/pull/242) by @AriaMoradi)
- (r1030) add manga data to download queue object ([#244](https://github.com/Suwayomi/src/pull/244) by @AriaMoradi)
- (r1031) Fix Manga Meta, add Manga Meta test ([#245](https://github.com/Suwayomi/src/pull/245) by @Syer10)
- (r1032) add pagination to recentChapters ([#246](https://github.com/Suwayomi/src/pull/246) by @AriaMoradi)
- (r1033) update (by @AriaMoradi)
- (r1034) Implement Update of Library/Category ([#235](https://github.com/Suwayomi/src/pull/235) by @ntbm)
- (r1035) update (by @AriaMoradi)
- (r1036) Mention the existence of Mahor's Tachidesk-GTK (by @AriaMoradi)
- (r1037) Add a Kotlin DSL for endpoint documentation ([#249](https://github.com/Suwayomi/Tachidesk-Server/pull/249) by @Syer10)
- (r1038) update (by @AriaMoradi)
- (r1039) update (by @AriaMoradi)
- (r1040) cleanup directory names ([#251](https://github.com/Suwayomi/Tachidesk-Server/pull/251) by @AriaMoradi)
- (r1041) Fix first page not being detected correctly ([#253](https://github.com/Suwayomi/Tachidesk-Server/pull/253) by @AriaMoradi)
- (r1042) Update README.md (by @AriaMoradi)
- (r1043) Update README.md (by @AriaMoradi)
- (r1044) migrate application directories ([#255](https://github.com/Suwayomi/Tachidesk-Server/pull/255) by @AriaMoradi)
- (r1045) add support for MultiSelectListPreference ([#258](https://github.com/Suwayomi/Tachidesk-Server/pull/258) by @AriaMoradi)
- (r1046) empty searchTerm support ([#259](https://github.com/Suwayomi/Tachidesk-Server/pull/259) by @AriaMoradi)
## Tachidesk-WebUI
- (r821) add Permanent sidebar for desktop widths([#46](https://github.com/Suwayomi/Tachidesk-WebUI/pull/46) by @abhijeetChawla)
- (r822) Fix Local Source being missing (by @AriaMoradi)
- (r823) fix the ugliness of bare messages (by @AriaMoradi)
- (r824) add pull request template (by @AriaMoradi)
- (r825) add Unread badges ([#48](https://github.com/Suwayomi/Tachidesk-WebUI/pull/48) by @ntbm)
- (r826) Back button implementation ([#47](https://github.com/Suwayomi/Tachidesk-WebUI/pull/47) by @abhijeetChawla)
- (r827) remove redundant '/manga' prefix from paths (by @AriaMoradi)
- (r828) refactor (by @AriaMoradi)
- (r829) put Sources and Extensions in the same screen (by @AriaMoradi)
- (r830) Set Fallback Image for broken Thumbnails ([#50](https://github.com/Suwayomi/Tachidesk-WebUI/pull/50) by @ntbm)
- (r833) Apply Api changes for unread badges ([#52](https://github.com/Suwayomi/Tachidesk-WebUI/pull/52) by @ntbm)
- (r834) add EmptyView to DownloadQueue, refactro strings ([#53](https://github.com/Suwayomi/Tachidesk-WebUI/pull/53) by @abhijeetChawla)
- (r835) Bottom navbar for mobile ([#51](https://github.com/Suwayomi/Tachidesk-WebUI/pull/51) by @abhijeetChawla)
- (r836) Implement Unread Filter for Library ([#54](https://github.com/Suwayomi/Tachidesk-WebUI/pull/54) by @ntbm)
- (r837) fix navbar broken logic (by @AriaMoradi)
- (r838) fix navbar (by @AriaMoradi)
- (r839) refactor (by @AriaMoradi)
- (r840) refactor (by @AriaMoradi)
- (r841) refactor (by @AriaMoradi)
- (r842) show different NavbarItems depending on device width (by @AriaMoradi)
- (r843) remove text decoration (by @AriaMoradi)
- (r844) fancy icon based on if path selected (by @AriaMoradi)
- (r845) custom Extension icon, google's version is shit (by @AriaMoradi)
- (r846) refactor (by @AriaMoradi)
- (r848) move info (by @AriaMoradi)
- (r849) add Search to Library ([#55](https://github.com/Suwayomi/Tachidesk-WebUI/pull/55) by @ntbm)
- (r850) add aspect ratio to the manga card. ([#56](https://github.com/Suwayomi/Tachidesk-WebUI/pull/56) by @abhijeetChawla)
- (r851) better wording (by @AriaMoradi)
- (r852) reorder nav buttons (by @AriaMoradi)
- (r853) nicer gradient (by @AriaMoradi)
- (r854) refactor MangaCard (by @AriaMoradi)
- (r855) closes #58 (by @AriaMoradi
- (r856) Add Resume Reading FAB Manga screen ([#59](https://github.com/Suwayomi/Tachidesk-WebUI/pull/59) by @abhijeetChawla)
- (r857) add filter and badge for `downloadCount` ([#62](https://github.com/Suwayomi/Tachidesk-WebUI/pull/62) by @abhijeetChawla)
- (r858) add issue template (by @AriaMoradi)
- (r859) Change color of navbar in light mode ([#65](https://github.com/Suwayomi/Tachidesk-WebUI/pull/65) by @abhijeetChawla)
- (r860) fix manga FAB margins ([#66](https://github.com/Suwayomi/Tachidesk-WebUI/pull/66) by @AriaMoradi)
- (r861) remove extra scrollbar on mobile ([#67](https://github.com/Suwayomi/Tachidesk-WebUI/pull/67) by @AriaMoradi)
- (r862) Fix Bad messages in Library Appbar search ([#70](https://github.com/Suwayomi/Tachidesk-WebUI/pull/70) by @ntbm)
- (r863) ban the style prop (by @AriaMoradi)
- (r864) Updates pagination update ([#68](https://github.com/Suwayomi/Tachidesk-WebUI/pull/68) by @AriaMoradi)
- (r865) make the whole chapter card into a button ([#73](https://github.com/Suwayomi/Tachidesk-WebUI/pull/73) by @AriaMoradi)
- (r866) fix chapter actions not working if manga is not fetched online ([#74](https://github.com/Suwayomi/Tachidesk-WebUI/pull/74) by @AriaMoradi)
- (r867) migrate some components to Mui5 new styling system ([#72](https://github.com/Suwayomi/Tachidesk-WebUI/pull/72) by @abhijeetChawla)
- (r868) load first page on read manga ([#76](https://github.com/Suwayomi/Tachidesk-WebUI/pull/76) by @AriaMoradi)
- (r869) Revert "migrate some components to Mui5 new styling system ([#72](https://github.com/Suwayomi/Tachidesk-WebUI/pull/72))" (by @AriaMoradi)
- (r870) migrate Backup to Mui 5 ([#106](https://github.com/Suwayomi/Tachidesk-WebUI/pull/106) by @AriaMoradi)
- (r871) migrate EmptyView to Mui 5 ([#95](https://github.com/Suwayomi/Tachidesk-WebUI/pull/95) by @AriaMoradi)
- (r872) migrate CategorySelect to Mui 5 ([#85](https://github.com/Suwayomi/Tachidesk-WebUI/pull/85) by @AriaMoradi)
- (r873) migrate LibraryOptions to Mui 5 ([#83](https://github.com/Suwayomi/Tachidesk-WebUI/pull/83) by @AriaMoradi)
- (r874) migrate ChapterCard.tsx to Mui 5 ([#80](https://github.com/Suwayomi/Tachidesk-WebUI/pull/80) by @AriaMoradi)
- (r875) migrate App.tsx to Mui 5 ([#79](https://github.com/Suwayomi/Tachidesk-WebUI/pull/79) by @AriaMoradi)
- (r876) migrate SourceConfigure to Mui 5 ([#103](https://github.com/Suwayomi/Tachidesk-WebUI/pull/103) by @AriaMoradi)
- (r877) migrate Settings to Mui 5 ([#102](https://github.com/Suwayomi/Tachidesk-WebUI/pull/102) by @AriaMoradi)
- (r878) migrate Updates to Mui 5 ([#104](https://github.com/Suwayomi/Tachidesk-WebUI/pull/104) by @AriaMoradi)
- (r879) Save tabs number in Url to persist tab when go to other paths ([#78](https://github.com/Suwayomi/Tachidesk-WebUI/pull/78) by @abhijeetChawla)
- (r880) migrate LangSelect to Mui 5 ([#86](https://github.com/Suwayomi/Tachidesk-WebUI/pull/86) by @AriaMoradi)
- (r881) migrate ExtensionCard.tsx to Mui 5 ([#81](https://github.com/Suwayomi/Tachidesk-WebUI/pull/81) by @AriaMoradi)
- (r882) migrate SingleSearch to Mui 5 ([#101](https://github.com/Suwayomi/Tachidesk-WebUI/pull/101) by @AriaMoradi)
- (r883) migrate LoadingPlaceholder to Mui 5 ([#96](https://github.com/Suwayomi/Tachidesk-WebUI/pull/96) by @AriaMoradi)
- (r884) migrate About to Mui 5 ([#105](https://github.com/Suwayomi/Tachidesk-WebUI/pull/105) by @AriaMoradi)
- (r885) migrate SourceCard to Mui 5 ([#82](https://github.com/Suwayomi/Tachidesk-WebUI/pull/82) by @AriaMoradi)
- (r886) migrate Manga to Mui 5 ([#99](https://github.com/Suwayomi/Tachidesk-WebUI/pull/99) by @AriaMoradi)
- (r887) migrate Browse to Mui 5 ([#98](https://github.com/Suwayomi/Tachidesk-WebUI/pull/98) by @AriaMoradi)
- (r888) migrate DesktopSideBar to Mui 5 ([#87](https://github.com/Suwayomi/Tachidesk-WebUI/pull/87) by @AriaMoradi)
- (r889) cleanup library ([#107](https://github.com/Suwayomi/Tachidesk-WebUI/pull/107) by @AriaMoradi)
- (r890) support for new searchTerm (by @AriaMoradi)
- (r891) Revert "support for new searchTerm" (by @AriaMoradi)
- (r892) add support for emptySearch ([#109](https://github.com/Suwayomi/Tachidesk-WebUI/pull/109) by @AriaMoradi)
- (r893) add support for MultiSelectListPreference ([#108](https://github.com/Suwayomi/Tachidesk-WebUI/pull/108) by @AriaMoradi)
# Server: v0.5.4 + WebUI: r820
## TL;DR
- Fixed ReadComicOnline, Toonily and possibly other sources not working
- Backup and Restore now includes Updates tab data
- Removed Anime support from WebUI, Anime support will also be removed from Tachidesk-Server in a future update
## Tachidesk-Server Changelog
- (r973) convert android.jar lib to a maven repo
- (r978) mimic Tachiyomi's behaviour more closely, fixes ReadComicOnline (EN)
- (r980) fix export chapter ordering, include new props in backup
- (r982) remove isNsfw annotation detection
- (r984) use correct time conversion units when doing backups
- (r989) Support using a CatalogueSource instead of only HttpSources ([#219](https://github.com/Suwayomi/Tachidesk-Server/pull/219) by @Syer10)
- (r991) Use a custom task to run electron ([#220](https://github.com/Suwayomi/Tachidesk-Server/pull/220) by @Syer10)
## Tachidesk-WebUI Changelog
- (r810) fix wrong strings in set Server Address dialog, fixes [#39](https://github.com/Suwayomi/Tachidesk-WebUI/issues/39)
- (r811) fix chapterFetch loop
- (r812) fix overlapping requests
- (r813) fix typo
- (r814) Better portrait support ([#41](https://github.com/Suwayomi/Tachidesk-WebUI/issues/41) by @minhe7735)
- (r815) fixes Reader navbar colors when in light mode ([#43](https://github.com/Suwayomi/Tachidesk-WebUI/issues/43) by @abhijeetChawla)
- (r816) default languages cleanup, force Local source enabled
- (r817) force Local source at LangSelect
- (r818) rename ExtensionLangSelect: generic name for generic use
- (r819) don't show anime anymore
- (r820) Remove Anime support
# Server: v0.5.3 + WebUI: r809
## TL;DR
- added support for a equivalent page to Tachiyomi's Updates tab
- fix launchers not working on macOS M1/arm64
## Tachidesk-Server Changelog
- (r956) fix macOS-arm64 bundle launchers not working
- (r957) Workaround StdLib issue and add KtLint to all modules ([#206](https://github.com/Suwayomi/Tachidesk-Server/pull/206) by @Syer10)
- (r960-r963) Add recently updated chapters(Updates) endpoint
## Tachidesk-WebUI Changelog
- (r808) fix chapter list not calling onlineFetch=true
- (r809) add support for Updates
# Server: v0.5.2 + WebUI: r807
## TL;DR
- Fixed Local source not working on Windows
- Fixed Chapter numbers being shown incorrectly
## Tachidesk-Server
### Public API
#### Non-breaking changes
- N/A
#### Breaking changes
- N/A
#### Bug fixes
- (r948) Fix ManaToki (KO) and NewToki (KO) (issue [#202](https://github.com/Suwayomi/Tachidesk-Server/issue/202))
- (r949) Local source: fix windows paths
### Private API
- (r941) Update BytecodeEditor to use Java NIO Paths ([#200](https://github.com/Suwayomi/Tachidesk-Server/pull/200) by @Syer10)
- (r942) Gradle Updates ([#199](https://github.com/Suwayomi/Tachidesk-Server/pull/199) by @Syer10)
## Tachidesk-WebUI
#### Visible changes
- (r804) update text positioning on Reader and Player ([#35](https://github.com/Suwayomi/Tachidesk-WebUI/pull/35) by @voltrare)
- (r806) Source card for Local source is different
- (r807) add Local source guide
#### Bug fixes
- (r805) fix chapter name
#### Internal changes
- N/A
# Server: v0.5.1 + WebUI: r803
## TL;DR
- Loading sources' manga list is at least twice as fast
- Added support for Tachiyomi's Local source
- Added BasicAuth support, now you can protect your Tachidesk instance if you are running it on a public server
- Added ability to turn off cache for image requests
## Tachidesk-Server
### Public API
#### Non-breaking changes
- (r915) add BasicAuth support
- (r918) add ability to delete downloaded chapters
- (r923-r930) add Local Source
- (r938) add ability to turn off cache for image requests
#### Breaking changes
- N/A
#### Bug fixes
- (r917) detect if a downloaded chapter is missing
### Private API
- (r913) remove expand char limit on MangaTable columns
- (r914) migrate to Javalin 4
- (r921) depricate zero based chapters
- (r937) add ChapterRecognition from tachiyomi, closes #10
## Tachidesk-WebUI
#### Visible changes
- (r790) nice looking progress percentage
- (r791) show a Delete button for downloaded chapters
- (r792) Update hover effect using more of Material-UI color pallete ([#29](https://github.com/Suwayomi/Tachidesk-WebUI/pull/29) by @voltrare)
- (r793) Optimize images ([#32](https://github.com/Suwayomi/Tachidesk-WebUI/pull/32) by @phanirithvij)
- (r794) try fix #30 ([#31](https://github.com/Suwayomi/Tachidesk-WebUI/pull/31) by @phanirithvij)
- (r795) fix viewing page number when the string is long
- (r796) show proper display name for source
- (r797) fail gracefully when a thumbnail has errors
- (r798) fix when a source fails to load mangas
- (r800) add Local source ([#31](https://github.com/Suwayomi/Tachidesk-WebUI/pull/31))
- (r803) add support for useCache
#### Bug fixes
- N/A
#### Internal changes
- N/A
# Server: v0.5.0 + WebUI: r789
## TL;DR
- You can now install APK extensions from the extensions page
- WebUI now comes with an updated Material Design looks and is faster a little bit.
- WebUI now shows Nsfw content by default, disable it in settings if you prefer to not see Nsfw stuff
- Added support for configuration of sources, this enables MangaDex, Komga, Cubari and many other sources
- Chapters in the Manga page and Sources in the source page now look nicer and will glow with mouse hover
## Tachidesk-Server
### Public API
#### Non-breaking changes
- (r888) add installing APK from external sources endpoint
#### Breaking changes
- (r877 [#188](https://github.com/Suwayomi/Tachidesk-Server/pull/188) by @Syer10) `MangaDataClass.genre` changed type to `List<String>`
#### Bug fixes
- (r899-r901) fix when an external apk is installed and it doesn't have the default tachiyomi-extensions name
- (r905) fix a bug where if two sources return the same URL, a false duplicate might be detected
### Private API
- (r887) the `run` task won't call `downloadWebUI` now
- (r902) cleanup print/ln instances
- (r906) better handling of uninstalling Extensions
## Tachidesk-WebUI
#### Visible changes
- (r770) add support for the new genre type
- (r771) set the default value of `showNsfw` to `true` so we won't have visual artifacts with a clean install
- (r774 [#21](https://github.com/Suwayomi/Tachidesk-WebUI/pull/21) by @voltrare) `ReaderNavbar.jsx`: Swap close and retract Navbar buttons
- (r775 [#23](https://github.com/Suwayomi/Tachidesk-WebUI/pull/23) by @voltrare) `yarn.lock`: Fixes version inconsistency after commit 9b866811b
- (r776 [#23](https://github.com/Suwayomi/Tachidesk-WebUI/pull/23) by @voltrare) add margin between Source and Extension cards, make the Search button look nicer
- (r777) add support for installing external APK files
- (r778) fix the makeToaster?
- (r779) Action button for installing external extension
- (r780 Suwayomi/Tachidesk-WebUI#25) add on hover, active effect to Chapter/Episode card
- (r782-r785) updating material-ui to v5 changed the theme
- (r785-r788) better `SourceCard` looks on mobile, move `SourceDataClass.isConfigurable` gear button to `SourceMangas`
- (r789) implement source configuration
#### Bug fixes
- N/A
#### Internal changes
- (r782-r785) update dependencies, migrate material-ui from v4 to v5
# Server: v0.4.9 + WebUI: r769
## Tachidesk-Server
### Public API
#### Non-breaking changes
- N/A
#### Breaking changes
- (r857) renamed: `SourceDataClass.isNSFW` -> `SourceDataClass.isNsfw`
#### Bug fixes
- N/A
### Private API
- (r850) Bump WebUI version to r767
- (r861) Bump WebUI version to r769
#### Non-code changes
- (r851) Add this changelog file and `CHANGELOG-TEMPLATE.md`
- (r852-r853) `CONTRIBUTING.md`: Add a note about this maintaining this file changelog
- (r855) `CONTRIBUTING.md`: text cleanup
- (r859) `CONTRIBUTING.md`: remove dumb rule
- (r862) `windows-bundler.sh`: update jre
- (r864) add linux and macOS bundler script and launcher scripts
- (r865) fix macOS bundler script and launcher scripts
- (r866) bump electron version to v14.0.0
- (r868) add linux and macOS bundlers to the publish workflow
- (r871) `publish.yml`: remove node module cache, won't need it anymore
- (r873) `publish.yml` and `build_push.yml`: fix oopsies
## Tachidesk-WebUI
#### Visible changes
- (r767-r769) Support for hiding NSFW content in settings screen, extensions screen, sources screen
#### Bug fixes
- N/A
#### Internal changes
- (r767) Remove some duplicate dependency declaration from `package.json`
#### Non-code changes
- (r42-r45) Change `README.md`: some links and stuff
- (r45-r765) Add all of the commit history from when WebUI was separated from Server, jumping from r45 to r765 (r45 is exactly the same as r765)
- (r766) Steal `.gitattributes` from Tachidesk-Server
- (r767) Dependency cleanup in `package.json`
# Server: v0.4.8 + WebUI: r41
## Tachidesk-Server
### Public API
#### Non-breaking changes
- Added support for serializing Search Filters
- `SourceDataClass` now has a `isNsfw` key
#### Breaking changes
- N/A
#### Bug fixes
- Fixed a bug where backup restore reversed chapter order
- Open Site feature now works properly (https://github.com/Suwayomi/Tachidesk-WebUI/issues/19)
### Private API
- Added `CloudflareInterceptor` from TachiWeb-Server
- Restoring backup for mangas in library(merging manga data) is now supported
## Tachidesk-WebUI
#### Visible changes
- Better looking manga card titles
- Better reader title, next, prev buttons
#### Bug fixes
- Open Site feature now works properly (https://github.com/Suwayomi/Tachidesk-WebUI/issues/19)
- Re-ordering categories now works
#### Internal changes
- N/A
+5
View File
@@ -0,0 +1,5 @@
# Code Of Conduct
- Don't be a dick.
# expanding the code of conduct!
The contents of this document is up for debate and improvement! Discussions on discord.
+56
View File
@@ -0,0 +1,56 @@
# Contributing
## Where should I start?
Checkout [This Kanban Board](https://github.com/Suwayomi/Tachidesk/projects/1) to see the rough development roadmap.
**Note 1:** Notify the developers on [Suwayomi discord](https://discord.gg/DDZdqZWaHA) (#tachidesk-server and #tachidesk-webui channels) or open a WIP pull request before starting if you decide to take on working on anything from/not from the roadmap in order to avoid parallel efforts on the same issue/feature.
**Note 2:** Your pull request will be squashed into a single commit.
### Project goals and vision
- Porting Tachiyomi and covering it's features
- Syncing with Tachiyomi, [main issue](https://github.com/Suwayomi/Tachidesk-Server/issues/159)
- Generally rejecting features that Tachiyomi(main app) doesn't have,
- Unless it's something that makes sense for desktop sizes or desktop form factor (keyboard + mouse)
- Additional/crazy features can go in forks and alternative clients
- [Tachidesk-WebUI](https://github.com/Suwayomi/Tachidesk-WebUI) should
- be responsive
- support both desktop and mobile form factors well
## How does Tachidesk-Server work?
This project has two components:
1. **Server:** contains the implementation of [tachiyomi's extensions library](https://github.com/tachiyomiorg/extensions-lib) and uses an Android compatibility library to run jar libraries converted from apk extensions. All this concludes to serving a REST API.
2. **WebUI:** A React SPA(`create-react-app`) project that works with the server to do the presentation located at https://github.com/Suwayomi/Tachidesk-WebUI
## Why a web app?
This structure is chosen to
- Achieve the maximum multi-platform-ness
- Gives the ability to access Tachidesk-Server from a remote client e.g., your phone, tablet or smart TV
- Ease development of user interfaces for Tachidesk
## Building from source
### Prerequisites
You need these software packages installed in order to build the project
- Java Development Kit and Java Runtime Environment version 8 or newer(both Oracle JDK and OpenJDK works)
### building the full-blown jar (Tachidesk-Server + Tachidesk-WebUI bundle)
Run `./gradlew server:downloadWebUI server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-Server-vX.Y.Z-rxxx.jar`.
### building without `webUI` bundled (server only)
Delete `server/src/main/resources/WebUI.zip` if exists from previous runs, then run `./gradlew server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-Server-vX.Y.Z-rxxx.jar`.
### building the Windows package
First Build the jar, then cd into the `scripts` directory and run `./windows-bundler.sh win32` or `./windows-bundler.sh win64` depending on the target architecture, the resulting built zip package file will be `server/build/Tachidesk-Server-vX.Y.Z-rxxx-winXX.zip`.
## Running in development mode
run `./gradlew :server:run --stacktrace` to run the server
## Running tests
run `./gradlew :server:test` to execute all tests
to test a specific class run `./gradlew :server:test --tests <package.with.classname>`
## Building the android-jar maven repository
Run `AndroidCompat/getAndroid.sh`(macOS/Linux) or `AndroidCompat/getAndroid.ps1`(Windows)
from project's root directory to download and rebuild the jar file from Google's repository,
then use `AndroidCompat/lib/android.jar` to manually create a maven repository inside the `android-jar` git branch.
Update the dependency declaration afterwards.
+135 -62
View File
@@ -1,100 +1,173 @@
![image](https://github.com/Suwayomi/Tachidesk/raw/master/server/src/main/resources/icon/faviconlogo.png)
# Tachidesk
A free and open source manga reader that runs extensions built for [Tachiyomi](https://tachiyomi.org/).
| Build | Stable | Preview | Support Server |
|-------|----------|---------|---------|
| ![CI](https://github.com/Suwayomi/Tachidesk/actions/workflows/build_push.yml/badge.svg) | [![stable release](https://img.shields.io/github/release/Suwayomi/Tachidesk.svg?maxAge=3600&label=download)](https://github.com/Suwayomi/Tachidesk/releases) | [![preview](https://img.shields.io/badge/dynamic/json?url=https://github.com/Suwayomi/Tachidesk-preview/raw/main/index.json&label=download&query=$.latest&color=blue)](https://github.com/Suwayomi/Tachidesk-preview/releases/latest) | [![Discord](https://img.shields.io/discord/801021177333940224.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/DDZdqZWaHA) |
Tachidesk is as multi-platform as you can get. Any platform that runs java and/or has a modern browser can run it.
## Table of Content
- [What is Tachidesk?](#what-is-tachidesk)
- [Tachidesk client projects](#tachidesk-client-projects)
* [Is this application usable? Should I test it?](#is-this-application-usable-should-i-test-it)
- [Downloading and Running the app](#downloading-and-running-the-app)
* [Using Operating System Specific Bundles](#using-operating-system-specific-bundles)
- [Launcher Scripts](#launcher-scripts)
+ [Windows](#windows)
+ [macOS](#macos)
+ [GNU/Linux](#gnulinux)
* [Other methods of getting Tachidesk](#other-methods-of-getting-tachidesk)
+ [Arch Linux](#arch-linux)
+ [Ubuntu-based distributions](#ubuntu-based-distributions)
+ [Docker](#docker)
* [Advanced Methods](#advanced-methods)
+ [Running the jar release directly](#running-the-jar-release-directly)
+ [Using Tachidesk Remotely](#using-tachidesk-remotely)
- [Syncing With Tachiyomi](#syncing-with-tachiyomi)
- [Troubleshooting and Support](#troubleshooting-and-support)
- [Contributing and Technical info](#contributing-and-technical-info)
- [Credit](#credit)
- [License](#license)
<!-- Generated with https://ecotrust-canada.github.io/markdown-toc/ -->
Ability to read and write Tachiyomi compatible backups and syncing is a planned feature.
# What is Tachidesk?
<img src="https://github.com/Suwayomi/Tachidesk/raw/master/server/src/main/resources/icon/faviconlogo.png" alt="drawing" width="200"/>
A free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org/).
Tachidesk is an independent Tachiyomi compatible software and is **not a Fork of** Tachiyomi.
`Tachidesk` is a general term used to describe the combination of Tachidesk-Server(this project) and one of our clients.
Think of it roughly like the concept of "distribution" in GNU/Linux distributions, in which Linux(Tachidesk-Server) is the kernel and the difference is which desktop environment(Tachidesk client) you get with it.
Tachidesk-Server is as multi-platform as you can get. Any platform that runs java and/or has a modern browser can run it. This includes Windows, Linux, macOS, chrome OS, etc. Follow [Downloading and Running the app](#downloading-and-running-the-app) for installation instructions.
Ability to sync with Tachiyomi is a planned feature.
# Tachidesk client projects
**You need a client/user interface app as a front-end for Tachidesk-Server, if you Directly Download Tachidesk-Server you'll get a bundled version of [Tachidesk-WebUI](https://github.com/Suwayomi/Tachidesk-WebUI) with it.**
Here's a list of known clients/user interfaces for Tachidesk-Server:
##### Actively Developed Cients
- [Tachidesk-WebUI](https://github.com/Suwayomi/Tachidesk-WebUI): The web/ElectronJS front-end that Tachidesk-Server is traditionally shipped with. Usually gets new features faster.
- [Tachidesk-JUI](https://github.com/Suwayomi/Tachidesk-JUI): The native desktop front-end for Tachidesk-Server. Currently the most advanced.
- [Tachidesk-qtui](https://github.com/Suwayomi/Tachidesk-qtui): A C++/Qt front-end for mobile devices(Android/linux), in super early stage of development.
- [Tachidesk-Sorayomi](https://github.com/Suwayomi/Tachidesk-Sorayomi): A Flutter front-end for Desktop(Linux, windows, etc.), Web and Android. UI and UX similar to Tachiyomi.
##### Inctive/Abandoned Cients
- [Equinox](https://github.com/Suwayomi/Equinox): A web user interface made with Vue.js, in super early stage of development.
- [Tachidesk-GTK](https://github.com/mahor1221/Tachidesk-GTK): A native Rust/GTK desktop client, in super early stage of development.
## Is this application usable? Should I test it?
Here is a list of current features:
- Installing and executing Tachiyomi's Extensions, So you'll get the same sources.
- A library to save your mangas and categories to put them into.
- Searching and browsing installed sources.
- A decent chapter reader.
- Ability to download Mangas for offline read(This partially works)
- Backup and restore support powered by Tachiyomi Legacy Backups
- Installing and executing Tachiyomi's Extensions, So you'll get the same sources
- A library to save your mangas and categories to put them into
- Searching and browsing installed sources
- Ability to download Manga for offline read
- Backup and restore support powered by Tachiyomi-compatible Backups
- Viewing latest updated chapters.
**Note:** Keep in mind that Tachidesk is alpha software and can break rarely and/or with each update, so you may have to delete your data to fix it. See [General troubleshooting](#general-troubleshooting) and [Support and help](#support-and-help) if it happens.
**Note:** These are capabilities of Tachidesk-Server, the actual working support is provided by each front-end app, checkout their respective readme for more info.
Anyways, for more info checkout [finished milestone #1](https://github.com/Suwayomi/Tachidesk/issues/2) and [milestone #2](https://github.com/Suwayomi/Tachidesk/projects/1) to see what's implemented in more detail.
# Downloading and Running the app
## Using Operating System Specific Bundles
To facilitate the use of Tachidesk we provide bundle releases that include The Java Runtime Environment, ElectronJS and 3 Tachidesk Launcher Scripts.
## Downloading and Running the app
### All Operating Systems
You should have The Java Runtime Environment(JRE) 8 or newer and a modern browser installed. Also an internet connection is required as almost everything this app does is downloading stuff.
If a bundle for your operating system or cpu architecture is not provided then refer to [Advanced Methods](#advanced-methods)
Download the latest "Stable" jar release from [the releases section](https://github.com/Suwayomi/Tachidesk/releases) or a preview jar build from [the preview branch](https://github.com/Suwayomi/Tachidesk/tree/preview).
#### Launcher Scripts
- `Tachidesk Electron Launcher`: Launches Tachidesk inside Electron as a desktop applicaton
- `Tachidesk Browser Launcher`: Launches Tachidesk in a browser window
- `Tachidesk Debug Launcher`: Launches Tachidesk with debug logs attached. If Tachidesk doesn't work for you, running this can give you insight into why.
Double click on the jar file or run `java -jar Tachidesk-vX.Y.Z-rxxx.jar` (or `java -jar Tachidesk-latest.jar` if you have the latest preview) from a Terminal/Command Prompt window to run the app which will open a new browser window automatically. Also the System Tray Icon is your friend if you need to open the browser window again or close Tachidesk.
**Node:** Linux launcher scripts are named a bit differently but work the same.
### Windows
Download the latest win32 release from [the releases section](https://github.com/Suwayomi/Tachidesk/releases).
Download the latest `win32`(Windows 32-bit) or `win64`(Windows 64-bit) release from [the releases section](https://github.com/Suwayomi/Tachidesk-Server/releases) or a preview one from [the preview repository](https://github.com/Suwayomi/Tachidesk-Server-preview/releases).
The Windows specific build has java bundled inside, so you don't have to install java to use it. Unzip `Tachidesk-vX.Y.Z-rxxx-win32.zip` and run `server.exe`. The rest works like the previous section.
Unzip the downloaded file and double click on one of the launcher scripts.
### macOS
Download the latest `macOS-x64`(older macOS systems) or `macOS-arm64`(Apple M1) release from [the releases section](https://github.com/Suwayomi/Tachidesk-Server/releases) or a preview one from [the preview repository](https://github.com/Suwayomi/Tachidesk-Server-preview/releases).
Unzip the downloaded file and double click on one of the launcher scripts.
### GNU/Linux
Download the latest `linux-x64`(x86_64) release from [the releases section](https://github.com/Suwayomi/Tachidesk-Server/releases) or a preview one from [the preview repository](https://github.com/Suwayomi/Tachidesk-Server-preview/releases).
`tar xvf` the downloaded file and double click on one of the launcher scripts or run them using the terminal.
## Other methods of getting Tachidesk
### Arch Linux
You can install Tachidesk from the AUR
You can install Tachidesk from the AUR:
```
yay -S tachidesk
```
### Debian/Ubuntu
Download the latest deb package from the release section or Install from the MPR
```
git clone https://mpr.makedeb.org/tachidesk-server.git
cd tachidesk-server
makedeb -si
```
### Ubuntu
```
sudo add-apt-repository ppa:suwayomi/tachidesk-server
sudo apt update
sudo apt install tachidesk-server
```
### Docker
Check [arbuilder's repo](https://github.com/arbuilder/Tachidesk-docker) out for more details and the dockerfile.
Check our Official Docker release [Tachidesk Container](https://github.com/orgs/Suwayomi/packages/container/package/tachidesk) for running Tachidesk Server in a docker container. Source code for our container is available at [docker-tachidesk](https://github.com/Suwayomi/docker-tachidesk). By default the server will be running on http://localhost:4567 open this url in your browser.
## General troubleshooting
If the app breaks try deleting the directory below and re-running the app (**This will delete all your data!**) and if the problem persists open an issue.
Install from the command line:
```
$ docker pull ghcr.io/suwayomi/tachidesk
```
Run Container from the command line:
```
$ docker run -p 4567:4567 ghcr.io/suwayomi/tachidesk
```
On Mac OS X : `/Users/<Account>/Library/Application Support/Tachidesk`
## Advanced Methods
### Running the jar release directly
In order to run the app you need the following:
- The jar release of Tachidesk-Server
- The Java Runtime Environment(JRE) 8 or newer
- A Browser like Google Chrome, Firefox, Edge, etc.
- ElectronJS (optional)
On Windows XP : `C:\Documents and Settings\<Account>\Application Data\Local Settings\Tachidesk`
Download the latest `.jar` release from [the releases section](https://github.com/Suwayomi/Tachidesk-Server/releases) or a preview jar build from [the preview repository](https://github.com/Suwayomi/Tachidesk-preview/releases).
On Windows 7 and later : `C:\Users\<Account>\AppData\Local\Tachidesk`
Make sure you have The Java Runtime Environment installed on your system, Double click on the jar file or run `java -jar Tachidesk-vX.Y.Z-rxxxx.jar` from a Terminal/Command Prompt window to run the app which will open a new browser window automatically.
On Unix/Linux : `/home/<account>/.local/share/Tachidesk`
### Using Tachidesk Remotely
You can run Tachidesk on your computer or a server and connect to it remotely through one of our clients or the bundled web interface with a web browser. This method of using Tachidesk is requires a bit of networking/firewall/port forwarding/server configuration/etc. knowledge on your side, if you can run a Minecraft server and configure it, then you are good to go.
## Support and help
Join Tachidesk's [discord server](https://discord.gg/WdPS74cz) to hang out with the community and receive support and help.
Check out [this wiki page](https://github.com/Suwayomi/Tachidesk-Server/wiki/Configuring-Tachidesk-Server) for a guide on configuring Tachidesk-Server.
## How does it work?
This project has two components:
1. **server:** contains the implementation of [tachiyomi's extensions library](https://github.com/tachiyomiorg/extensions-lib) and uses an Android compatibility library to run apk extensions. All this concludes to serving a REST API to `webUI`.
2. **webUI:** A react SPA project that works with the server to do the presentation.
If you face issues with your setup then we are happy to provide help, just join our discord server(a discord badge is on the top of the page, you are just a click clack away!).
## Building from source
### Prerequisite: Get Android stubs jar
#### Manual download
Download [android.jar](https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar) and put it under `AndroidCompat/lib`.
#### Automated download
Run `AndroidCompat/getAndroid.sh`(MacOS/Linux) or `AndroidCompat/getAndroid.ps1`(Windows) from project's root directory to download and rebuild the jar file from Google's repository.
### Prerequisite: Software dependencies
You need this software packages installed in order to build this project:
- Java Development Kit and Java Runtime Environment version 8 or newer(both Oracle JDK and OpenJDK works)
- Nodejs LTS or latest
- Yarn
### building the full-blown jar
Run `./gradlew :webUI:copyBuild server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-vX.Y.Z-rxxx.jar`.
### building without `webUI` bundled(server only)
Delete the `server/src/main/resources/react` directory if exists from previous runs, then run `./gradlew server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-vX.Y.Z-rxxx.jar`.
### building the Windows package
Run `./gradlew :server:windowsPackage` to build a server only bundle and `./gradlew :webUI:copyBuild :server:windowsPackage` to get a full bundle , the resulting built zip package file will be `server/build/Tachidesk-vX.Y.Z-rxxx-win32.zip`.
## Running for development purposes
### `server` module
Follow [Get Android stubs jar](#prerequisite-get-android-stubs-jar) then run `./gradlew :server:run --stacktrace` to run the server
### `webUI` module
How to do it is described in `webUI/react/README.md` but for short,
first cd into `webUI/react` then run `yarn` to install the node modules(do this only once)
then `yarn start` to start the development server, if a new browser window doesn't get opned automatically,
then open `http://127.0.0.1:3000` in a modern browser. This is a `create-react-app` project
and supports HMR and all the other goodies you'll need.
## Syncing With Tachiyomi
### The Tachidesk extension
- You can install the `Tachidesk` extension inside tachiyomi.
- The extension will load Tachidesk library.
- By manipulating filters you can browse your categories.
### Other methods
Checkout [this issue](https://github.com/Suwayomi/Tachidesk-Server/issues/159) for tracking progress.
## Troubleshooting and Support
See [this troubleshooting wiki page](https://github.com/Suwayomi/Tachidesk/wiki/Troubleshooting).
## Contributing and Technical info
See [CONTRIBUTING.md](./CONTRIBUTING.md).
## Credit
This project is a spiritual successor of [TachiWeb-Server](https://github.com/Tachiweb/TachiWeb-server), Many of the ideas and the groundwork adopted in this project comes from TachiWeb.
The `AndroidCompat` module was originally developed by [@null-dev](https://github.com/null-dev) for [TachiWeb-Server](https://github.com/Tachiweb/TachiWeb-server) and is licensed under `Apache License Version 2.0`.
The `AndroidCompat` module was originally developed by [@null-dev](https://github.com/null-dev) for [TachiWeb-Server](https://github.com/Tachiweb/TachiWeb-server) and is licensed under `Apache License Version 2.0` and `Copyright 2019 Andy Bao and contributors`.
Parts of [tachiyomi](https://github.com/tachiyomiorg/tachiyomi) is adopted into this codebase, also licensed under `Apache License Version 2.0`.
Parts of [tachiyomi](https://github.com/tachiyomiorg/tachiyomi) is adopted into this codebase, also licensed under `Apache License Version 2.0` and `Copyright 2015 Javier Tomás`.
You can obtain a copy of `Apache License Version 2.0` from http://www.apache.org/licenses/LICENSE-2.0
+57 -30
View File
@@ -1,23 +1,24 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jmailen.gradle.kotlinter.tasks.FormatTask
import org.jmailen.gradle.kotlinter.tasks.LintTask
plugins {
id("org.jetbrains.kotlin.jvm") version "1.4.21" apply false // Also in buildSrc Config.kt
id("java")
kotlin("jvm") version kotlinVersion
kotlin("plugin.serialization") version kotlinVersion
id("org.jmailen.kotlinter") version "3.8.0"
id("com.github.gmazzo.buildconfig") version "3.0.3" apply false
}
allprojects {
group = "ir.armor.tachidesk"
group = "suwayomi"
version = "1.0"
repositories {
jcenter()
mavenCentral()
maven("https://maven.google.com/")
google()
maven("https://jitpack.io")
maven("https://oss.sonatype.org/content/repositories/snapshots/")
maven("https://dl.bintray.com/inorichi/maven")
maven("https://dl.google.com/dl/android/maven2/")
maven("https://github.com/Suwayomi/Tachidesk-Server/raw/android-jar/")
}
}
@@ -28,61 +29,87 @@ val projects = listOf(
)
configure(projects) {
apply(plugin = "java")
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "org.jetbrains.kotlin.plugin.serialization")
apply(plugin = "org.jmailen.kotlinter")
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
tasks {
withType<KotlinCompile> {
dependsOn(formatKotlin)
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs = listOf(
"-Xopt-in=kotlin.RequiresOptIn",
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
"-Xopt-in=kotlinx.serialization.ExperimentalSerializationApi",
)
}
}
withType<LintTask> {
source(files("src/kotlin"))
}
withType<FormatTask> {
source(files("src/kotlin"))
}
}
dependencies {
// Kotlin
implementation(kotlin("stdlib", KotlinCompilerVersion.VERSION))
implementation(kotlin("stdlib", KotlinCompilerVersion.VERSION))
implementation(kotlin("reflect", version = "1.4.21"))
testImplementation(kotlin("test", version = "1.4.21"))
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
testImplementation(kotlin("test-junit5"))
// coroutines
val coroutinesVersion = "1.4.2"
val coroutinesVersion = "1.6.0"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
val kotlinSerializationVersion = "1.3.2"
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion")
// Dependency Injection
implementation("org.kodein.di:kodein-di-conf-jvm:7.1.0")
implementation("org.kodein.di:kodein-di-conf-jvm:7.10.0")
// Logging
implementation("org.slf4j:slf4j-api:1.7.30")
implementation("ch.qos.logback:logback-classic:1.2.3")
implementation("io.github.microutils:kotlin-logging:2.0.3")
implementation("org.slf4j:slf4j-api:1.7.32")
implementation("ch.qos.logback:logback-classic:1.2.6")
implementation("io.github.microutils:kotlin-logging:2.1.21")
// RxJava
// ReactiveX
implementation("io.reactivex:rxjava:1.3.8")
implementation("io.reactivex:rxkotlin:1.0.0")
implementation("com.jakewharton.rxrelay:rxrelay:1.2.0")
// JSoup
implementation("org.jsoup:jsoup:1.13.1")
// dependency both in AndroidCompat and extensions, version locked by Tachiyomi app/extensions
implementation("org.jsoup:jsoup:1.14.3")
// dependency of :AndroidCompat:Config
implementation("com.typesafe:config:1.4.0")
implementation("com.typesafe:config:1.4.1")
implementation("io.github.config4k:config4k:0.4.2")
// to get application content root
implementation("net.harawata:appdirs:1.2.0")
implementation("net.harawata:appdirs:1.2.1")
// dex2jar: https://github.com/DexPatcher/dex2jar/releases/tag/v2.1-20190905-lanchon
implementation("com.github.DexPatcher.dex2jar:dex-tools:v2.1-20190905-lanchon")
// dex2jar
val dex2jarVersion = "v35"
implementation("com.github.ThexXTURBOXx.dex2jar:dex-translator:$dex2jarVersion")
implementation("com.github.ThexXTURBOXx.dex2jar:dex-tools:$dex2jarVersion")
// APK parser
implementation("net.dongliu:apk-parser:2.6.10")
// dependency both in AndroidCompat and server, version locked by javalin
implementation("com.fasterxml.jackson.core:jackson-annotations:2.12.4")
}
}
+11
View File
@@ -0,0 +1,11 @@
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
dependencies {
implementation("net.lingala.zip4j:zip4j:2.9.0")
}
+34
View File
@@ -0,0 +1,34 @@
import java.io.BufferedReader
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
const val kotlinVersion = "1.6.10"
const val MainClass = "suwayomi.tachidesk.MainKt"
// should be bumped with each stable release
val tachideskVersion = System.getenv("ProductVersion") ?: "v0.6.4"
val webUIRevisionTag = System.getenv("WebUIRevision") ?: "r946"
val sorayomiRevisionTag = System.getenv("SorayomiRevision") ?: "0.1.5"
// counts commits on the master branch
val tachideskRevision = runCatching {
System.getenv("ProductRevision") ?: Runtime
.getRuntime()
.exec("git rev-list HEAD --count")
.let { process ->
process.waitFor()
val output = process.inputStream.use {
it.bufferedReader().use(BufferedReader::readText)
}
process.destroy()
"r" + output.trim()
}
}.getOrDefault("r0")
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+159 -110
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
+292
View File
@@ -0,0 +1,292 @@
#!/bin/bash
# Copyright (C) Contributors to the Suwayomi project
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
main() {
POSITIONAL_ARGS=()
OUTPUT_DIR=.
while [ "$#" -gt 0 ]; do
case "$1" in
-o|--output-dir)
OUTPUT_DIR="$(readlink -e "$2" || exit 1)"
shift
shift
;;
*)
POSITIONAL_ARGS+=("$1")
shift
;;
esac
done
# restore positional parameters
set -- "${POSITIONAL_ARGS[@]}"
OS="$1"
JAR="$(ls server/build/*.jar | tail -n1)"
RELEASE_NAME="$(echo "${JAR%.*}" | xargs basename)-$OS"
RELEASE_VERSION="$(tmp="${JAR%-*}"; echo "${tmp##*-}" | tr -d v)"
#RELEASE_REVISION_NUMBER="$(tmp="${JAR%.*}" && echo "${tmp##*-}" | tr -d r)"
local electron_version="v14.0.0"
# clean temporary directory on function return
trap "rm -rf $RELEASE_NAME/" RETURN
mkdir "$RELEASE_NAME/"
case "$OS" in
debian-all)
RELEASE="$RELEASE_NAME.deb"
make_deb_package
move_release_to_output_dir
;;
linux-assets)
RELEASE="$RELEASE_NAME.tar.gz"
copy_linux_package_assets_to "$RELEASE_NAME/"
tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/"
move_release_to_output_dir
;;
linux-x64)
JRE="OpenJDK8U-jre_x64_linux_hotspot_8u302b08.tar.gz"
JRE_URL="https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/$JRE"
ELECTRON="electron-$electron_version-linux-x64.zip"
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
download_jre_and_electron
RELEASE="$RELEASE_NAME.tar.gz"
make_linux_bundle
move_release_to_output_dir
;;
macOS-x64)
JRE="OpenJDK8U-jre_x64_mac_hotspot_8u302b08.tar.gz"
JRE_URL="https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/$JRE"
ELECTRON="electron-$electron_version-darwin-x64.zip"
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
download_jre_and_electron
RELEASE="$RELEASE_NAME.zip"
make_macos_bundle
move_release_to_output_dir
;;
macOS-arm64)
JRE="zulu8.56.0.23-ca-jre8.0.302-macosx_aarch64.tar.gz"
JRE_URL="https://cdn.azul.com/zulu/bin/$JRE"
ELECTRON="electron-$electron_version-darwin-arm64.zip"
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
download_jre_and_electron
RELEASE="$RELEASE_NAME.zip"
make_macos_bundle
move_release_to_output_dir
;;
windows-x86)
JRE="OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip"
JRE_URL="https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/$JRE"
ELECTRON="electron-$electron_version-win32-ia32.zip"
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
download_jre_and_electron
RELEASE="$RELEASE_NAME.zip"
make_windows_bundle
move_release_to_output_dir
RELEASE="$RELEASE_NAME.msi"
make_windows_package
move_release_to_output_dir
;;
windows-x64)
JRE="OpenJDK8U-jre_x64_windows_hotspot_8u302b08.zip"
JRE_URL="https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u302-b08/$JRE"
ELECTRON="electron-$electron_version-win32-x64.zip"
ELECTRON_URL="https://github.com/electron/electron/releases/download/$electron_version/$ELECTRON"
download_jre_and_electron
RELEASE="$RELEASE_NAME.zip"
make_windows_bundle
move_release_to_output_dir
RELEASE="$RELEASE_NAME.msi"
make_windows_package
move_release_to_output_dir
;;
*)
error $LINENO "Unsupported operating system: $OS" 2
;;
esac
}
move_release_to_output_dir() {
# clean up from possible previous runs
if [ -f "$OUTPUT_DIR/$RELEASE" ]; then
rm "$OUTPUT_DIR/$RELEASE"
fi
mv "$RELEASE" "$OUTPUT_DIR/"
}
download_jre_and_electron() {
if [ ! -f "$JRE" ]; then
curl -L "$JRE_URL" -o "$JRE"
fi
if [ ! -f "$ELECTRON" ]; then
curl -L "$ELECTRON_URL" -o "$ELECTRON"
fi
mkdir -p "$RELEASE_NAME/jre/"
local ext="${JRE##*.}"
local jre_dir
if [ "$ext" = "zip" ]; then
jre_dir="$(unzip "$JRE" | sed -n '2p' | cut -d: -f2 | xargs basename)"
mv "$jre_dir" "$RELEASE_NAME/jre"
else
# --strip-components=1: untar an archive without the root folder
tar xvf "$JRE" --strip-components=1 -C "$RELEASE_NAME/jre/"
fi
unzip "$ELECTRON" -d "$RELEASE_NAME/electron/"
}
copy_linux_package_assets_to() {
local output_dir
output_dir="$(readlink -e "$1" || exit 1)"
cp "scripts/resources/pkg/tachidesk-server-browser-launcher.sh" "$output_dir/"
cp "scripts/resources/pkg/tachidesk-server-debug-launcher.sh" "$output_dir/"
cp "scripts/resources/pkg/tachidesk-server-electron-launcher.sh" "$output_dir/"
cp "scripts/resources/pkg/tachidesk-server.desktop" "$output_dir/"
cp "scripts/resources/pkg/systemd"/* "$output_dir/"
cp "server/src/main/resources/icon/faviconlogo.png" \
"$output_dir/tachidesk-server.png"
}
make_linux_bundle() {
cp "$JAR" "$RELEASE_NAME/Tachidesk-Server.jar"
cp "scripts/resources/tachidesk-server-browser-launcher.sh" "$RELEASE_NAME/"
cp "scripts/resources/tachidesk-server-debug-launcher.sh" "$RELEASE_NAME/"
cp "scripts/resources/tachidesk-server-electron-launcher.sh" "$RELEASE_NAME/"
tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/"
}
make_macos_bundle() {
cp "$JAR" "$RELEASE_NAME/Tachidesk-Server.jar"
cp "scripts/resources/Tachidesk Browser Launcher.command" "$RELEASE_NAME/"
cp "scripts/resources/Tachidesk Debug Launcher.command" "$RELEASE_NAME/"
cp "scripts/resources/Tachidesk Electron Launcher.command" "$RELEASE_NAME/"
zip -9 -r "$RELEASE" "$RELEASE_NAME/"
}
# https://wiki.debian.org/SimplePackagingTutorial
# https://www.debian.org/doc/manuals/packaging-tutorial/packaging-tutorial.pdf
make_deb_package() {
local temp_dir
temp_dir="$(mktemp -d)"
trap "rm -rf $temp_dir" RETURN
cp "$JAR" "$RELEASE_NAME/Tachidesk-Server.jar"
tar -I "gzip" -cvf "$RELEASE_NAME.tar.gz" "$RELEASE_NAME/"
#behind $RELEASE_VERSION is underscore "_"
local upstream_source="tachidesk-server_$RELEASE_VERSION.orig.tar.gz"
mv "$RELEASE_NAME.tar.gz" "$temp_dir/$upstream_source"
cp -r "scripts/resources/deb/" "$RELEASE_NAME/debian/"
copy_linux_package_assets_to "$RELEASE_NAME/debian/"
sed -i "s/\$pkgver/$RELEASE_VERSION/" "$RELEASE_NAME/debian/changelog"
sed -i "s/\$pkgrel/1/" "$RELEASE_NAME/debian/changelog"
#behind $RELEASE_VERSION is hyphen "-"
local source_dir="tachidesk-server-$RELEASE_VERSION"
mv "$RELEASE_NAME/" "$temp_dir/$source_dir/"
sudo apt install devscripts build-essential dh-exec
cd "$temp_dir/$source_dir/"
dpkg-buildpackage --no-sign --build=all
cd -
local deb="tachidesk-server_$RELEASE_VERSION-1_all.deb"
mv "$temp_dir/$deb" "$RELEASE"
}
make_windows_bundle() {
## I disabled this section until someone find a solution to this error:
##E: Unable to correct problems, you have held broken packages.
##./bundler.sh: line 250: wine: command not found
## check if running under github actions
#if [ "$CI" = true ]; then
## change electron executable's icon
#sudo dpkg --add-architecture i386
#wget -qO - https://dl.winehq.org/wine-builds/winehq.key \
#| sudo apt-key add -
#sudo add-apt-repository ppa:cybermax-dexter/sdl2-backport
#sudo apt-add-repository "deb https://dl.winehq.org/wine-builds/ubuntu \
#$(lsb_release -cs) main"
#sudo apt install --install-recommends winehq-stable
#fi
## this script assumes that wine is installed here on out
#local rcedit="rcedit-x85.exe"
#local rcedit_url="https://github.com/electron/rcedit/releases/download/v0.1.1/$rcedit"
## change electron's icon
#if [ ! -f "$rcedit" ]; then
#curl -L "$rcedit_url" -o "$rcedit"
#fi
#local icon="server/src/main/resources/icon/faviconlogo.ico"
#WINEARCH=win32 wine "$rcedit" "$RELEASE_NAME/electron/electron.exe" \
# --set-icon "$icon"
cp "$JAR" "$RELEASE_NAME/Tachidesk-Server.jar"
cp "scripts/resources/Tachidesk Browser Launcher.bat" "$RELEASE_NAME"
cp "scripts/resources/Tachidesk Debug Launcher.bat" "$RELEASE_NAME"
cp "scripts/resources/Tachidesk Electron Launcher.bat" "$RELEASE_NAME"
zip -9 -r "$RELEASE" "$RELEASE_NAME"
}
make_windows_package() {
if [ "$CI" = true ]; then
sudo apt install -y wixl
fi
find "$RELEASE_NAME/jre" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref jre --component-group jre >"$RELEASE_NAME/jre.wxs"
find "$RELEASE_NAME/electron" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref electron --component-group electron >"$RELEASE_NAME/electron.wxs"
local icon="server/src/main/resources/icon/faviconlogo.ico"
local arch=${OS##*-}
wixl -D ProductVersion="$RELEASE_VERSION" -D SourceDir="$RELEASE_NAME" \
-D Icon="$icon" --arch "$arch" "scripts/resources/msi/tachidesk-server-$arch.wxs" \
"$RELEASE_NAME/jre.wxs" "$RELEASE_NAME/electron.wxs" -o "$RELEASE"
}
# Error handler
# set -u: Treat unset variables as an error when substituting.
# set -o pipefail: Prevents errors in pipeline from being masked.
# set -e: Immediatly exit if any command has a non-zero exit status.
# set -E: Inherit the trap ERR function before exiting by set.
#
# set -e is not recommended and unpredictable.
# see https://stackoverflow.com/questions/64786/error-handling-in-bash
# and http://mywiki.wooledge.org/BashFAO/105
set -uo pipefail
error() {
local parent_lineno="$1"
local message="$2"
local code="${3:-1}"
if [ -z "$message" ]; then
echo "$0: line $parent_lineno: exiting with status $code"
else
echo "$0: line $parent_lineno: $message: exiting with status $code"
fi
exit "$code"
}
trap 'error $LINENO ""' ERR
main "$@"; exit
@@ -0,0 +1 @@
start "" jre/bin/javaw -jar Tachidesk-Server.jar
+3
View File
@@ -0,0 +1,3 @@
cd "`dirname "$0"`"
./jre/Contents/Home/bin/java -jar Tachidesk-Server.jar
@@ -0,0 +1,7 @@
:: cleaner output
@echo off
jre\bin\java -Dsuwayomi.tachidesk.config.server.debugLogsEnabled=true -jar Tachidesk-Server.jar
:: Prevent cmd from closing when Tachidesk crashes
pause
+3
View File
@@ -0,0 +1,3 @@
cd "`dirname "$0"`"
./jre/Contents/Home/bin/java -Dsuwayomi.tachidesk.config.server.debugLogsEnabled=true -jar Tachidesk-Server.jar
@@ -0,0 +1 @@
jre\bin\javaw "-Dsuwayomi.tachidesk.config.server.webUIInterface=electron" "-Dsuwayomi.tachidesk.config.server.electronPath=electron/electron.exe" -jar Tachidesk-Server.jar
+3
View File
@@ -0,0 +1,3 @@
cd "`dirname "$0"`"
./jre/Contents/Home/bin/java "-Dsuwayomi.tachidesk.config.server.webUIInterface=electron" "-Dsuwayomi.tachidesk.config.server.electronPath=electron/Electron.app/Contents/MacOS/Electron" -jar Tachidesk-Server.jar

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