diff --git a/.gitignore b/.gitignore index 1132f314a..84d274f13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .gradle -.secrets /local.properties /.idea/workspace.xml .DS_Store diff --git a/README.md b/README.md index 2a9883b91..1960d4e2a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # Usage -https://github.com/keiyoushi/extensions/blob/main/README.md +[Getting started](https://keiyoushi.github.io/docs/guides/getting-started#adding-the-extension-repo) # Contributing diff --git a/src/all/komga/CHANGELOG.md b/src/all/komga/CHANGELOG.md deleted file mode 100644 index 759286187..000000000 --- a/src/all/komga/CHANGELOG.md +++ /dev/null @@ -1,383 +0,0 @@ -## 1.4.47 - -Minimum Komga version required: `0.151.0` - -### Feat - -* add support for AVIF and HEIF image types - -## 1.4.46 - -Minimum Komga version required: `0.151.0` - -### Feat - -* Update to extension-lib 1.4 - - Clicking on chapter WebView should now open the chapter/book page. - -## 1.3.45 - -Minimum Komga version required: `0.151.0` - -### Feat - -* Edit source display name - -## 1.3.44 - -Minimum Komga version required: `0.151.0` - -### Fix - -* Better date/time parsing - -## 1.3.43 - -Minimum Komga version required: `0.151.0` - -### Fix - -* Requests failing if address preference is saved with a trailing slash - -### Features - -* Add URL validation in the address preferences -* Use a URL-focused keyboard when available while editing the address preferences - -## 1.3.42 - -Minimum Komga version required: `0.151.0` - -### Fix - -* default sort broken since Komga 0.155.1 -* proper sort criteria for readlists - -## 1.3.41 - -Minimum Komga version required: `0.151.0` - -### Features - -* Improve how the status is displayed - -## 1.3.40 - -Minimum Komga version required: `0.151.0` - -### Features - -* Exclude from bulk update warnings - -## 1.2.39 - -Minimum Komga version required: `0.151.0` - -### Features - -* Prepend series name in front of books within readlists - -## 1.2.38 - -Minimum Komga version required: `0.113.0` - -### Features - -* Add `README.md` - -## 1.2.37 - -Minimum Komga version required: `0.113.0` - -### Features - -* In app link to `CHANGELOG.md` - -## 1.2.36 - -Minimum Komga version required: `0.113.0` - -### Features - -* Don't request conversion for JPEG XL images - -## 1.2.35 - -Minimum Komga version required: `0.113.0` - -### Features - -* Display the Translators of a book in the scanlator chapter field - -## 1.2.34 - -Minimum Komga version required: `0.113.0` - -### Fix - -* Loading of filter values could fail in some cases - -## 1.2.33 - -Minimum Komga version required: `0.113.0` - -### Fix - -* Open in WebView and Share options now open regular browser link instead of showing JSON -* Note that Komga cannot be viewed using System WebView since there is no login prompt - However, opening in a regular browser works. - -## 1.2.32 - -Minimum Komga version required: `0.113.0` - -### Fix - -* Source language, conventionally set to "en", is now changed to "all" -* Downloaded files, if any, will have to be moved to new location - - `Komga (EN)` to `Komga (ALL)` - - `Komga (3) (EN)` to `Komga (3) (ALL)` - -## 1.2.31 - -Minimum Komga version required: `0.113.0` - -### Refactor - -* replace Gson with kotlinx.serialization - -## 1.2.30 - -Minimum Komga version required: `0.113.0` - -### Features - -* display read list summary -* display aggregated tags on series -* search series by book tags - -## 1.2.29 - -Minimum Komga version required: `0.97.0` - -### Features - -* filter deleted series and books - -## 1.2.28 - -Minimum Komga version required: `0.97.0` - -### Fix - -* incorrect User Agent - -## 1.2.27 - -Minimum Komga version required: `0.97.0` - -### Fix - -* filter series by read or in progress - -## 1.2.26 - -Minimum Komga version required: `0.87.4` - -### Fix - -* show series with only in progress books when searching for unread only - -## 1.2.25 - -Minimum Komga version required: `0.87.4` - -### Fix - -* sort order for read list books - -## 1.2.24 - -Minimum Komga version required: `0.87.4` - -### Fix - -* only show series tags in the filter panel -* set URL properly on series and read lists, so restoring from a backup can work properly - - -## 1.2.23 - -Minimum Komga version required: `0.75.0` - -### Features - -* ignore DNS over HTTPS so it can reach IP addresses - -## 1.2.22 - -Minimum Komga version required: `0.75.0` - -### Features - -* add error logs and better catch exceptions - -## 1.2.21 - -Minimum Komga version required: `0.75.0` - -### Features - -* browse read lists (from the filter menu) -* filter by collection, respecting the collection's ordering - -## 1.2.20 - -Minimum Komga version required: `0.75.0` - -### Features - -* filter by authors, grouped by role - -## 1.2.19 - -Minimum Komga version required: `0.68.0` - -### Features - -* display Series authors -* display Series summary from books if no summary exists for Series - -## 1.2.18 - -Minimum Komga version required: `0.63.2` - -### Fix - -* use metadata.releaseDate or fileLastModified for chapter date - -## 1.2.17 - -Minimum Komga version required: `0.63.2` - -### Fix - -* list of collections for filtering could be empty in some conditions - -## 1.2.16 - -Minimum Komga version required: `0.59.0` - -### Features - -* filter by genres, tags and publishers - -## 1.2.15 - -Minimum Komga version required: `0.56.0` - -### Features - -* remove the 1000 chapters limit -* display series description and tags (genres + tags) - -## 1.2.14 - -Minimum Komga version required: `0.41.0` - -### Features - -* change chapter display name to use the display number instead of the sort number - -## 1.2.13 - -Minimum Komga version required: `0.41.0` - -### Features - -* compatibility for the upcoming version of Komga which have changes in the API (IDs are String instead of Long) - -## 1.2.12 - -Minimum Komga version required: `0.41.0` - -### Features - -* filter by collection - -## 1.2.11 - -Minimum Komga version required: `0.35.2` - -### Features - -* Set password preferences inputTypes - -## 1.2.10 - -Minimum Komga version required: `0.35.2` - -### Features - -* unread only filter (closes gotson/komga#180) -* prefix book titles with number (closes gotson/komga#169) - -## 1.2.9 - -Minimum Komga version required: `0.22.0` - -### Features - -* use SourceFactory to have multiple Komga servers (3 for the moment) - -## 1.2.8 - -Minimum Komga version required: `0.22.0` - -### Features - -* use book metadata title for chapter display name -* use book metadata sort number for chapter number - -## 1.2.7 - -### Features - -* use series metadata title for display name -* filter on series status - -## 1.2.6 - -### Features - -* Add support for AndroidX preferences - -## 1.2.5 - -### Features - -* add sort options in filter - -## 1.2.4 - -### Features - -* better handling of authentication - -## 1.2.3 - -### Features - -* filters by library - -## 1.2.2 - -### Features - -* request converted image from server if format is not supported - -## 1.2.1 - -### Features - -* first version diff --git a/src/all/komga/README.md b/src/all/komga/README.md deleted file mode 100644 index fa7ae9fc7..000000000 --- a/src/all/komga/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Komga - -Table of Content -- [FAQ](#FAQ) - - [Why do I see no manga?](#why-do-i-see-no-manga) - - [Where can I get more information about Komga?](#where-can-i-get-more-information-about-komga) - - [The Komga extension stopped working?](#the-komga-extension-stopped-working) - - [Can I add more than one Komga server or user?](#can-i-add-more-than-one-komga-server-or-user) - - [Can I test the Komga extension before setting up my own server?](#can-i-test-the-komga-extension-before-setting-up-my-own-server) -- [Guides](#Guides) - - [How do I add my Komga server to Tachiyomi?](#how-do-i-add-my-komga-server-to-tachiyomi) - -Don't find the question you are look for go check out our general FAQs and Guides over at [Extension FAQ](https://tachiyomi.org/help/faq/#extensions) or [Getting Started](https://tachiyomi.org/help/guides/getting-started/#installation) - -## FAQ - -### Why do I see no manga? -Komga is a self-hosted comic/manga media server. - -### Where can I get more information about Komga? -You can visit the [Komga](https://komga.org/) website for for more information. - -### The Komga extension stopped working? -Make sure that your Komga server and extension are on the newest version. - -### Can I add more than one Komga server or user? -Yes, currently you can add up to 3 different Komga instances to Tachiyomi. - -### Can I test the Komga extension before setting up my own server? -Yes, you can try it out with the DEMO server `https://demo.komga.org`, username `demo@komga.org` and password `komga-demo`. - -## Guides - -### How do I add my Komga server to Tachiyomi? -Go into the settings of the Komga extension from the Extension tab in Browse and fill in your server address and login details. diff --git a/src/all/komga/build.gradle b/src/all/komga/build.gradle index a6f23ba70..5800f78e0 100644 --- a/src/all/komga/build.gradle +++ b/src/all/komga/build.gradle @@ -1,12 +1,3 @@ -<<<<<<< HEAD -ext { - extName = 'Komga' - extClass = '.KomgaFactory' - extVersionCode = 50 -} - -apply from: "$rootDir/common.gradle" -======= ext { extName = 'Komga' extClass = '.KomgaFactory' @@ -18,4 +9,3 @@ apply from: "$rootDir/common.gradle" dependencies { implementation("org.apache.commons:commons-text:1.11.0") } ->>>>>>> d52b3e572 (Add Komga (#579)) diff --git a/src/all/komga/res/mipmap-hdpi/ic_launcher.png b/src/all/komga/res/mipmap-hdpi/ic_launcher.png old mode 100755 new mode 100644 diff --git a/src/all/komga/res/mipmap-mdpi/ic_launcher.png b/src/all/komga/res/mipmap-mdpi/ic_launcher.png old mode 100755 new mode 100644 diff --git a/src/all/komga/res/mipmap-xhdpi/ic_launcher.png b/src/all/komga/res/mipmap-xhdpi/ic_launcher.png old mode 100755 new mode 100644 diff --git a/src/all/komga/res/mipmap-xxhdpi/ic_launcher.png b/src/all/komga/res/mipmap-xxhdpi/ic_launcher.png old mode 100755 new mode 100644 diff --git a/src/all/komga/res/mipmap-xxxhdpi/ic_launcher.png b/src/all/komga/res/mipmap-xxxhdpi/ic_launcher.png old mode 100755 new mode 100644 diff --git a/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/Komga.kt b/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/Komga.kt index 63841ccb1..af808791e 100644 --- a/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/Komga.kt +++ b/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/Komga.kt @@ -9,10 +9,7 @@ import android.util.Log import android.widget.Button import android.widget.Toast import androidx.preference.EditTextPreference -<<<<<<< HEAD -======= import androidx.preference.ListPreference ->>>>>>> d52b3e572 (Add Komga (#579)) import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.AppInfo import eu.kanade.tachiyomi.extension.all.komga.dto.AuthorDto @@ -24,11 +21,6 @@ import eu.kanade.tachiyomi.extension.all.komga.dto.PageWrapperDto import eu.kanade.tachiyomi.extension.all.komga.dto.ReadListDto import eu.kanade.tachiyomi.extension.all.komga.dto.SeriesDto import eu.kanade.tachiyomi.network.GET -<<<<<<< HEAD -import eu.kanade.tachiyomi.network.asObservable -import eu.kanade.tachiyomi.network.await -======= ->>>>>>> d52b3e572 (Add Komga (#579)) import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.model.Filter @@ -42,20 +34,12 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import okhttp3.Credentials import okhttp3.Dns -<<<<<<< HEAD -import okhttp3.Headers -======= import okhttp3.HttpUrl.Companion.toHttpUrl ->>>>>>> d52b3e572 (Add Komga (#579)) import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response -<<<<<<< HEAD -import rx.Observable -======= import org.apache.commons.text.StringSubstitutor ->>>>>>> d52b3e572 (Add Komga (#579)) import rx.Single import rx.schedulers.Schedulers import uy.kohesive.injekt.Injekt @@ -65,10 +49,6 @@ import java.security.MessageDigest import java.util.Locale open class Komga(private val suffix: String = "") : ConfigurableSource, UnmeteredSource, HttpSource() { -<<<<<<< HEAD - override fun popularMangaRequest(page: Int): Request = - GET("$baseUrl/api/v1/series?page=${page - 1}&deleted=false&sort=metadata.titleSort,asc", headers) -======= override val name by lazy { "Komga${displayName.ifBlank { suffix }.let { if (it.isNotBlank()) " ($it)" else "" }}" } @@ -118,31 +98,23 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere "", FilterList(SeriesSort()), ) ->>>>>>> d52b3e572 (Add Komga (#579)) override fun popularMangaParse(response: Response): MangasPage = processSeriesPage(response) override fun latestUpdatesRequest(page: Int): Request = -<<<<<<< HEAD - GET("$baseUrl/api/v1/series/latest?page=${page - 1}&deleted=false", headers) -======= searchMangaRequest( page, "", FilterList(SeriesSort(Filter.Sort.Selection(2, false))), ) ->>>>>>> d52b3e572 (Add Komga (#579)) override fun latestUpdatesParse(response: Response): MangasPage = processSeriesPage(response) override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { -<<<<<<< HEAD -======= runCatching { fetchFilterOptions() } ->>>>>>> d52b3e572 (Add Komga (#579)) val collectionId = (filters.find { it is CollectionSelect } as? CollectionSelect)?.let { it.values[it.state].id } @@ -153,11 +125,7 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere else -> "series" } -<<<<<<< HEAD - val url = "$baseUrl/api/v1/$type?search=$query&page=${page - 1}&deleted=false".toHttpUrlOrNull()!!.newBuilder() -======= val url = "$baseUrl/api/v1/$type?search=$query&page=${page - 1}&deleted=false".toHttpUrl().newBuilder() ->>>>>>> d52b3e572 (Add Komga (#579)) filters.forEach { filter -> when (filter) { @@ -178,65 +146,29 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere } } is LibraryGroup -> { -<<<<<<< HEAD - val libraryToInclude = mutableListOf() - filter.state.forEach { content -> - if (content.state) { - libraryToInclude.add(content.id) - } - } -======= val libraryToInclude = filter.state.filter { it.state }.map { it.id } ->>>>>>> d52b3e572 (Add Komga (#579)) if (libraryToInclude.isNotEmpty()) { url.addQueryParameter("library_id", libraryToInclude.joinToString(",")) } } is StatusGroup -> { -<<<<<<< HEAD - val statusToInclude = mutableListOf() - filter.state.forEach { content -> - if (content.state) { - statusToInclude.add(content.name.uppercase(Locale.ROOT)) - } - } -======= val statusToInclude = filter.state.filter { it.state }.map { it.name.uppercase(Locale.ROOT) } ->>>>>>> d52b3e572 (Add Komga (#579)) if (statusToInclude.isNotEmpty()) { url.addQueryParameter("status", statusToInclude.joinToString(",")) } } is GenreGroup -> { -<<<<<<< HEAD - val genreToInclude = mutableListOf() - filter.state.forEach { content -> - if (content.state) { - genreToInclude.add(content.name) - } - } -======= val genreToInclude = filter.state.filter { it.state }.map { it.name } ->>>>>>> d52b3e572 (Add Komga (#579)) if (genreToInclude.isNotEmpty()) { url.addQueryParameter("genre", genreToInclude.joinToString(",")) } } is TagGroup -> { -<<<<<<< HEAD - val tagToInclude = mutableListOf() - filter.state.forEach { content -> - if (content.state) { - tagToInclude.add(content.name) - } - } -======= val tagToInclude = filter.state.filter { it.state }.map { it.name } ->>>>>>> d52b3e572 (Add Komga (#579)) if (tagToInclude.isNotEmpty()) { url.addQueryParameter("tag", tagToInclude.joinToString(",")) } @@ -253,34 +185,13 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere } } is AuthorGroup -> { -<<<<<<< HEAD - val authorToInclude = mutableListOf() - filter.state.forEach { content -> - if (content.state) { - authorToInclude.add(content.author) - } - } -======= val authorToInclude = filter.state.filter { it.state }.map { it.author } ->>>>>>> d52b3e572 (Add Komga (#579)) authorToInclude.forEach { url.addQueryParameter("author", "${it.name},${it.role}") } } is Filter.Sort -> { -<<<<<<< HEAD - var sortCriteria = when (filter.state?.index) { - 0 -> if (type == "series") "metadata.titleSort" else "name" - 1 -> "createdDate" - 2 -> "lastModifiedDate" - else -> "" - } - if (sortCriteria.isNotEmpty()) { - sortCriteria += "," + if (filter.state?.ascending!!) "asc" else "desc" - url.addQueryParameter("sort", sortCriteria) - } -======= val state = filter.state ?: return@forEach val sortCriteria = when (state.index) { @@ -291,47 +202,17 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere } + "," + if (state.ascending) "asc" else "desc" url.addQueryParameter("sort", sortCriteria) ->>>>>>> d52b3e572 (Add Komga (#579)) } else -> {} } } -<<<<<<< HEAD - return GET(url.toString(), headers) -======= return GET(url.build(), headers) ->>>>>>> d52b3e572 (Add Komga (#579)) } override fun searchMangaParse(response: Response): MangasPage = processSeriesPage(response) -<<<<<<< HEAD - override fun fetchMangaDetails(manga: SManga): Observable { - return client.newCall(GET(manga.url, headers)) - .asObservable() - .map { response -> - mangaDetailsParse(response).apply { initialized = true } - } - } - - override fun mangaDetailsRequest(manga: SManga): Request = - GET(manga.url.replaceFirst("api/v1/", "", ignoreCase = true), headers) - - override fun mangaDetailsParse(response: Response): SManga { - return response.body.use { body -> - if (response.fromReadList()) { - val readList = json.decodeFromString(body.string()) - readList.toSManga() - } else { - val series = json.decodeFromString(body.string()) - series.toSManga() - } - } - } - -======= override fun getMangaUrl(manga: SManga) = manga.url.replace("/api/v1", "") override fun mangaDetailsRequest(manga: SManga) = GET(manga.url) @@ -350,31 +231,19 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere override fun getChapterUrl(chapter: SChapter) = chapter.url.replace("/api/v1/books", "/book") ->>>>>>> d52b3e572 (Add Komga (#579)) override fun chapterListRequest(manga: SManga): Request = GET("${manga.url}/books?unpaged=true&media_status=READY&deleted=false", headers) override fun chapterListParse(response: Response): List { -<<<<<<< HEAD - val responseBody = response.body - val page = responseBody.use { json.decodeFromString>(it.string()).content } -======= val page = response.parseAs>().content ->>>>>>> d52b3e572 (Add Komga (#579)) val r = page.mapIndexed { index, book -> SChapter.create().apply { chapter_number = if (!response.fromReadList()) book.metadata.numberSort else index + 1F -<<<<<<< HEAD - name = "${if (!response.fromReadList()) "${book.metadata.number} - " else "${book.seriesTitle} ${book.metadata.number}: "}${book.metadata.title} (${book.size})" -======= ->>>>>>> d52b3e572 (Add Komga (#579)) url = "$baseUrl/api/v1/books/${book.id}" scanlator = book.metadata.authors.groupBy({ it.role }, { it.name })["translator"]?.joinToString() date_upload = book.metadata.releaseDate?.let { parseDate(it) } ?: parseDateTime(book.fileLastModified) -<<<<<<< HEAD -======= val values = hashMapOf( "title" to book.metadata.title, @@ -388,7 +257,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere val sub = StringSubstitutor(values, "{", "}") name = (if (!response.fromReadList()) "" else "${book.seriesTitle} ") + sub.replace(chapterNameTemplate) ->>>>>>> d52b3e572 (Add Komga (#579)) } } return r.sortedByDescending { it.chapter_number } @@ -398,13 +266,8 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere GET("${chapter.url}/pages") override fun pageListParse(response: Response): List { -<<<<<<< HEAD - val responseBody = response.body - val pages = responseBody.use { json.decodeFromString>(it.string()) } -======= val pages = response.parseAs>() ->>>>>>> d52b3e572 (Add Komga (#579)) return pages.map { val url = "${response.request.url}/${it.number}" + if (!supportedImageTypes.contains(it.mediaType)) { @@ -413,124 +276,13 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere "" } Page( -<<<<<<< HEAD - index = it.number - 1, -======= index = it.number, ->>>>>>> d52b3e572 (Add Komga (#579)) imageUrl = url, ) } } -<<<<<<< HEAD - override fun getMangaUrl(manga: SManga) = manga.url.replace("/api/v1", "") - - override fun getChapterUrl(chapter: SChapter) = chapter.url.replace("/api/v1/books", "/book") - - private fun processSeriesPage(response: Response): MangasPage { - val responseBody = response.body - return responseBody.use { body -> - if (response.fromReadList()) { - with(json.decodeFromString>(body.string())) { - MangasPage(content.map { it.toSManga() }, !last) - } - } else { - with(json.decodeFromString>(body.string())) { - MangasPage(content.map { it.toSManga() }, !last) - } - } - } - } - - private fun SeriesDto.toSManga(): SManga = - SManga.create().apply { - title = metadata.title - url = "$baseUrl/api/v1/series/$id" - thumbnail_url = "$url/thumbnail" - status = when { - metadata.status == "ENDED" && metadata.totalBookCount != null && booksCount < metadata.totalBookCount -> SManga.PUBLISHING_FINISHED - metadata.status == "ENDED" -> SManga.COMPLETED - metadata.status == "ONGOING" -> SManga.ONGOING - metadata.status == "ABANDONED" -> SManga.CANCELLED - metadata.status == "HIATUS" -> SManga.ON_HIATUS - else -> SManga.UNKNOWN - } - genre = (metadata.genres + metadata.tags + booksMetadata.tags).distinct().joinToString(", ") - description = metadata.summary.ifBlank { booksMetadata.summary } - booksMetadata.authors.groupBy { it.role }.let { map -> - author = map["writer"]?.map { it.name }?.distinct()?.joinToString() - artist = map["penciller"]?.map { it.name }?.distinct()?.joinToString() - } - } - - private fun ReadListDto.toSManga(): SManga = - SManga.create().apply { - title = name - description = summary - url = "$baseUrl/api/v1/readlists/$id" - thumbnail_url = "$url/thumbnail" - status = SManga.UNKNOWN - } - - private fun Response.fromReadList() = request.url.toString().contains("/api/v1/readlists") - - private fun parseDate(date: String?): Long = - if (date == null) { - 0 - } else { - try { - KomgaHelper.formatterDate.parse(date)?.time ?: 0 - } catch (ex: Exception) { - 0 - } - } - - private fun parseDateTime(date: String?): Long = - if (date == null) { - 0 - } else { - try { - KomgaHelper.formatterDateTime.parse(date)?.time ?: 0 - } catch (ex: Exception) { - try { - KomgaHelper.formatterDateTimeMilli.parse(date)?.time ?: 0 - } catch (ex: Exception) { - 0 - } - } - } - - override fun imageUrlParse(response: Response): String = "" - - private class TypeSelect : Filter.Select("Search for", arrayOf(TYPE_SERIES, TYPE_READLISTS)) - private class LibraryFilter(val id: String, name: String) : Filter.CheckBox(name, false) - private class LibraryGroup(libraries: List) : Filter.Group("Libraries", libraries) - private class CollectionSelect(collections: List) : Filter.Select("Collection", collections.toTypedArray()) - private class SeriesSort : Filter.Sort("Sort", arrayOf("Alphabetically", "Date added", "Date updated"), Selection(0, true)) - private class StatusFilter(name: String) : Filter.CheckBox(name, false) - private class StatusGroup(filters: List) : Filter.Group("Status", filters) - private class UnreadFilter : Filter.CheckBox("Unread", false) - private class InProgressFilter : Filter.CheckBox("In Progress", false) - private class ReadFilter : Filter.CheckBox("Read", false) - private class GenreFilter(genre: String) : Filter.CheckBox(genre, false) - private class GenreGroup(genres: List) : Filter.Group("Genres", genres) - private class TagFilter(tag: String) : Filter.CheckBox(tag, false) - private class TagGroup(tags: List) : Filter.Group("Tags", tags) - private class PublisherFilter(publisher: String) : Filter.CheckBox(publisher, false) - private class PublisherGroup(publishers: List) : Filter.Group("Publishers", publishers) - private class AuthorFilter(val author: AuthorDto) : Filter.CheckBox(author.name, false) - private class AuthorGroup(role: String, authors: List) : Filter.Group(role, authors) - - private data class CollectionFilterEntry( - val name: String, - val id: String? = null, - ) { - override fun toString() = name - } -======= override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() ->>>>>>> d52b3e572 (Add Komga (#579)) override fun getFilterList(): FilterList { val filters = try { @@ -546,31 +298,22 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere TagGroup(tags.map { TagFilter(it) }), PublisherGroup(publishers.map { PublisherFilter(it) }), ).also { list -> -<<<<<<< HEAD -======= if (collections.isEmpty() && libraries.isEmpty() && genres.isEmpty() && tags.isEmpty() && publishers.isEmpty()) { list.add(0, Filter.Header("Press 'Reset' to show filtering options")) list.add(1, Filter.Separator()) } ->>>>>>> d52b3e572 (Add Komga (#579)) list.addAll(authors.map { (role, authors) -> AuthorGroup(role, authors.map { AuthorFilter(it) }) }) list.add(SeriesSort()) } } catch (e: Exception) { -<<<<<<< HEAD - Log.e(LOG_TAG, "error while creating filter list", e) -======= Log.e(logTag, "error while creating filter list", e) ->>>>>>> d52b3e572 (Add Komga (#579)) emptyList() } return FilterList(filters) } -<<<<<<< HEAD -======= override fun setupPreferenceScreen(screen: PreferenceScreen) { if (suffix.isBlank()) { ListPreference(screen.context).apply { @@ -652,7 +395,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere }.also(screen::addPreference) } ->>>>>>> d52b3e572 (Add Komga (#579)) private var libraries = emptyList() private var collections = emptyList() private var genres = emptySet() @@ -660,77 +402,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere private var publishers = emptySet() private var authors = emptyMap>() // roles to list of authors -<<<<<<< HEAD - // keep the previous ID when lang was "en", so that preferences and manga bindings are not lost - override val id by lazy { - val key = "komga${if (suffix.isNotBlank()) " ($suffix)" else ""}/en/$versionId" - val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray()) - (0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE - } - - private val displayName by lazy { preferences.displayName } - final override val baseUrl by lazy { preferences.baseUrl } - private val username by lazy { preferences.username } - private val password by lazy { preferences.password } - private val json: Json by injectLazy() - - override fun headersBuilder(): Headers.Builder = - Headers.Builder() - .add("User-Agent", "TachiyomiKomga/${AppInfo.getVersionName()}") - - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - override val name = "Komga${displayName.ifBlank { suffix }.let { if (it.isNotBlank()) " ($it)" else "" }}" - override val lang = "all" - override val supportsLatest = true - private val LOG_TAG = "extension.all.komga${if (suffix.isNotBlank()) ".$suffix" else ""}" - - override val client: OkHttpClient = - network.client.newBuilder() - .authenticator { _, response -> - if (response.request.header("Authorization") != null) { - null // Give up, we've already failed to authenticate. - } else { - response.request.newBuilder() - .addHeader("Authorization", Credentials.basic(username, password)) - .build() - } - } - .dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing - .build() - - override fun setupPreferenceScreen(screen: PreferenceScreen) { - screen.addEditTextPreference( - title = "Source display name", - default = suffix, - summary = displayName.ifBlank { "Here you can change the source displayed suffix" }, - key = PREF_DISPLAYNAME, - ) - screen.addEditTextPreference( - title = "Address", - default = ADDRESS_DEFAULT, - summary = baseUrl.ifBlank { "The server address" }, - inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI, - validate = { it.toHttpUrlOrNull() != null }, - validationMessage = "The URL is invalid or malformed", - key = PREF_ADDRESS, - ) - screen.addEditTextPreference( - title = "Username", - default = USERNAME_DEFAULT, - summary = username.ifBlank { "The user account email" }, - key = PREF_USERNAME, - ) - screen.addEditTextPreference( - title = "Password", - default = PASSWORD_DEFAULT, - summary = if (password.isBlank()) "The user account password" else "*".repeat(password.length), - inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD, - key = PREF_PASSWORD, - ) -======= private class TypeSelect : Filter.Select("Search for", arrayOf(TYPE_SERIES, TYPE_READLISTS)) private class LibraryFilter(val id: String, name: String) : Filter.CheckBox(name, false) private class LibraryGroup(libraries: List) : Filter.Group("Libraries", libraries) @@ -755,7 +426,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere val id: String? = null, ) { override fun toString() = name ->>>>>>> d52b3e572 (Add Komga (#579)) } private fun PreferenceScreen.addEditTextPreference( @@ -817,125 +487,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere addPreference(preference) } -<<<<<<< HEAD - private val SharedPreferences.displayName - get() = getString(PREF_DISPLAYNAME, "")!! - - private val SharedPreferences.baseUrl - get() = getString(PREF_ADDRESS, ADDRESS_DEFAULT)!!.removeSuffix("/") - - private val SharedPreferences.username - get() = getString(PREF_USERNAME, USERNAME_DEFAULT)!! - - private val SharedPreferences.password - get() = getString(PREF_PASSWORD, PASSWORD_DEFAULT)!! - - init { - if (baseUrl.isNotBlank()) { - Single.fromCallable { - try { - client.newCall(GET("$baseUrl/api/v1/libraries", headers)).execute().use { response -> - libraries = try { - val responseBody = response.body - responseBody.use { json.decodeFromString(it.string()) } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for libraries filter", e) - emptyList() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading libraries for filters", e) - } - - try { - client.newCall(GET("$baseUrl/api/v1/collections?unpaged=true", headers)).execute().use { response -> - collections = try { - val responseBody = response.body - responseBody.use { json.decodeFromString>(it.string()).content } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for collections filter", e) - emptyList() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading collections for filters", e) - } - - try { - client.newCall(GET("$baseUrl/api/v1/genres", headers)).execute().use { response -> - genres = try { - val responseBody = response.body - responseBody.use { json.decodeFromString(it.string()) } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for genres filter", e) - emptySet() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading genres for filters", e) - } - - try { - client.newCall(GET("$baseUrl/api/v1/tags", headers)).execute().use { response -> - tags = try { - response.body.use { json.decodeFromString(it.string()) } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for tags filter", e) - emptySet() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading tags for filters", e) - } - - try { - client.newCall(GET("$baseUrl/api/v1/publishers", headers)).execute().use { response -> - publishers = try { - response.body.use { json.decodeFromString(it.string()) } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for publishers filter", e) - emptySet() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading publishers for filters", e) - } - - try { - client.newCall(GET("$baseUrl/api/v1/authors", headers)).execute().use { response -> - authors = try { - response.body - .use { json.decodeFromString>(it.string()) } - .groupBy { it.role } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while decoding JSON for authors filter", e) - emptyMap() - } - } - } catch (e: Exception) { - Log.e(LOG_TAG, "error while loading authors for filters", e) - } - } - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) - .subscribe( - {}, - { tr -> - Log.e(LOG_TAG, "error while doing initial calls", tr) - }, - ) - } - } - - companion object { - private const val PREF_DISPLAYNAME = "Source display name" - private const val PREF_ADDRESS = "Address" - private const val ADDRESS_DEFAULT = "" - private const val PREF_USERNAME = "Username" - private const val USERNAME_DEFAULT = "" - private const val PREF_PASSWORD = "Password" - private const val PASSWORD_DEFAULT = "" -======= private var fetchFiltersFailed = false private var fetchFiltersAttempts = 0 @@ -1054,7 +605,6 @@ open class Komga(private val suffix: String = "") : ConfigurableSource, Unmetere private const val PREF_PASSWORD = "Password" private const val PREF_CHAPTER_NAME_TEMPLATE = "Chapter name template" private const val PREF_CHAPTER_NAME_TEMPLATE_DEFAULT = "{number} - {title} ({size})" ->>>>>>> d52b3e572 (Add Komga (#579)) private val supportedImageTypes = listOf("image/jpeg", "image/png", "image/gif", "image/webp", "image/jxl", "image/heif", "image/avif") diff --git a/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/KomgaFactory.kt b/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/KomgaFactory.kt index 26428eb85..479c8d221 100644 --- a/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/KomgaFactory.kt +++ b/src/all/komga/src/eu/kanade/tachiyomi/extension/all/komga/KomgaFactory.kt @@ -4,15 +4,6 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceFactory class KomgaFactory : SourceFactory { -<<<<<<< HEAD - - override fun createSources(): List = - listOf( - Komga(), - Komga("2"), - Komga("3"), - ) -======= override fun createSources(): List { val firstKomga = Komga("") val komgaCount = firstKomga.preferences.getString(Komga.PREF_EXTRA_SOURCES_COUNT, Komga.PREF_EXTRA_SOURCES_DEFAULT)!!.toInt() @@ -20,5 +11,4 @@ class KomgaFactory : SourceFactory { // Komga(""), Komga("2"), Komga("3"), ... return listOf(firstKomga) + (0 until komgaCount).map { Komga("${it + 2}") } } ->>>>>>> d52b3e572 (Add Komga (#579)) } diff --git a/src/all/lanraragi/README.md b/src/all/lanraragi/README.md index 750ced24b..7f06442c0 100644 --- a/src/all/lanraragi/README.md +++ b/src/all/lanraragi/README.md @@ -24,11 +24,7 @@ You can visit the [LANraragi](https://github.com/Difegue/LANraragi) github page Make sure that your LANraragi server and extension are on the newest version. ### Can I add more than one LANraragi server or user? -<<<<<<< HEAD -No, currently there is only support for 1 instances in Tachiyomi, if you need more instances please open a feature request on [tachiyomi-extensions](https://github.com/tachiyomiorg/tachiyomi-extensions/issues/new/choose) repo. -======= No, currently there is only support for 1 instances in Tachiyomi, if you need more instances please open a feature request on [extensions](https://github.com/tachiyomiorg/extensions/issues/new/choose) repo. ->>>>>>> 4dac8de22 (Add LANraragi (#702)) ### Can I test the LANraragi extension before setting up my own server? Yes, you can try it out with the DEMO server `https://lrr.tvc-16.science`. diff --git a/src/all/lanraragi/build.gradle b/src/all/lanraragi/build.gradle index ba805505d..86b87431d 100644 --- a/src/all/lanraragi/build.gradle +++ b/src/all/lanraragi/build.gradle @@ -1,11 +1,7 @@ ext { extName = 'LANraragi' extClass = '.LANraragiFactory' -<<<<<<< HEAD - extVersionCode = 15 -======= extVersionCode = 16 ->>>>>>> 4dac8de22 (Add LANraragi (#702)) } apply from: "$rootDir/common.gradle" diff --git a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt index 20ec29759..3beacca72 100644 --- a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt +++ b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt @@ -6,10 +6,7 @@ import android.net.Uri import android.text.InputType import android.util.Base64 import android.widget.Toast -<<<<<<< HEAD -======= import androidx.preference.ListPreference ->>>>>>> 4dac8de22 (Add LANraragi (#702)) import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.ConfigurableSource @@ -276,11 +273,7 @@ open class LANraragi(private val suffix: String = "") : ConfigurableSource, Unme (0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE } -<<<<<<< HEAD - private val preferences: SharedPreferences by lazy { -======= internal val preferences: SharedPreferences by lazy { ->>>>>>> 4dac8de22 (Add LANraragi (#702)) Injekt.get().getSharedPreferences("source_$id", 0x0000) } @@ -290,8 +283,6 @@ open class LANraragi(private val suffix: String = "") : ConfigurableSource, Unme private fun getPrefCustomLabel(): String = preferences.getString(CUSTOM_LABEL_KEY, suffix)!!.ifBlank { suffix } override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) { -<<<<<<< HEAD -======= if (suffix == "1") { ListPreference(screen.context).apply { key = EXTRA_SOURCES_COUNT_KEY @@ -313,7 +304,6 @@ open class LANraragi(private val suffix: String = "") : ConfigurableSource, Unme } }.also(screen::addPreference) } ->>>>>>> 4dac8de22 (Add LANraragi (#702)) screen.addPreference(screen.editTextPreference(HOSTNAME_KEY, "Hostname", HOSTNAME_DEFAULT, baseUrl, refreshSummary = true)) screen.addPreference(screen.editTextPreference(APIKEY_KEY, "API Key", "", "Required if No-Fun Mode is enabled.", true)) screen.addPreference(screen.editTextPreference(CUSTOM_LABEL_KEY, "Custom Label", "", "Show the given label for the source instead of the default.")) @@ -490,13 +480,10 @@ open class LANraragi(private val suffix: String = "") : ConfigurableSource, Unme } companion object { -<<<<<<< HEAD -======= internal const val EXTRA_SOURCES_COUNT_KEY = "extraSourcesCount" internal const val EXTRA_SOURCES_COUNT_DEFAULT = "2" private val EXTRA_SOURCES_ENTRIES = (0..10).map { it.toString() }.toTypedArray() ->>>>>>> 4dac8de22 (Add LANraragi (#702)) private const val HOSTNAME_DEFAULT = "http://127.0.0.1:3000" private const val HOSTNAME_KEY = "hostname" private const val APIKEY_KEY = "apiKey" diff --git a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragiFactory.kt b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragiFactory.kt index e41e67af6..d34851dec 100644 --- a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragiFactory.kt +++ b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragiFactory.kt @@ -4,14 +4,6 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceFactory class LANraragiFactory : SourceFactory { -<<<<<<< HEAD - override fun createSources(): List = - listOf( - LANraragi("1"), - LANraragi("2"), - LANraragi("3"), - ) -======= override fun createSources(): List { val firstLrr = LANraragi("1") val lrrCount = firstLrr.preferences.getString(LANraragi.EXTRA_SOURCES_COUNT_KEY, LANraragi.EXTRA_SOURCES_COUNT_DEFAULT)!!.toInt() @@ -23,5 +15,4 @@ class LANraragiFactory : SourceFactory { } } } ->>>>>>> 4dac8de22 (Add LANraragi (#702)) }