diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130cd..fb7f4a8a4 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 23a89bbb6..2c7e03473 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,7 +4,7 @@ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 0947cf71a..fe5866281 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,6 +2,8 @@ \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index d5d35ec44..470028385 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index daaa07686..a946cb636 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,7 +66,7 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' - implementation 'androidx.core:core-ktx:1.5.0-alpha05' + implementation 'androidx.core:core-ktx:1.5.0-beta01' implementation 'androidx.activity:activity-ktx:1.2.0-rc01' implementation 'androidx.fragment:fragment-ktx:1.3.0-rc01' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-rc01' @@ -79,8 +79,8 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.2.0-beta01' implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01' implementation 'androidx.preference:preference-ktx:1.1.1' - implementation 'androidx.work:work-runtime-ktx:2.5.0-beta02' - implementation 'com.google.android.material:material:1.3.0-beta01' + implementation 'androidx.work:work-runtime-ktx:2.5.0-rc01' + implementation 'com.google.android.material:material:1.3.0-rc01' //noinspection LifecycleAnnotationProcessorWithJava8 kapt 'androidx.lifecycle:lifecycle-compiler:2.3.0-rc01' @@ -89,7 +89,7 @@ dependencies { kapt 'androidx.room:room-compiler:2.2.6' implementation 'com.squareup.okhttp3:okhttp:4.9.0' - implementation 'com.squareup.okio:okio:2.9.0' + implementation 'com.squareup.okio:okio:2.10.0' implementation 'org.jsoup:jsoup:1.13.1' implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.0' @@ -97,7 +97,7 @@ dependencies { implementation 'org.koin:koin-android:2.2.2' implementation 'org.koin:koin-androidx-viewmodel:2.2.2' - implementation 'io.coil-kt:coil-base:1.1.0' + implementation 'io.coil-kt:coil-base:1.1.1' implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0' implementation 'com.tomclaw.cache:cache:1.0' diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt index 11ec6827d..683893bba 100644 --- a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt +++ b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt @@ -9,7 +9,6 @@ import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import org.koitharu.kotatsu.utils.ext.safe class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), KoinComponent { @@ -45,7 +44,7 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko return request?.url?.toString()?.let(::doRequest) } - private fun doRequest(url: String): WebResourceResponse? = safe { + private fun doRequest(url: String): WebResourceResponse? = runCatching { val request = Request.Builder() .url(url) .build() @@ -56,5 +55,5 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko ct?.charset()?.name() ?: "utf-8", response.body?.byteStream() ) - } + }.getOrNull() } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt index 91065155f..d1ffd108a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt @@ -4,7 +4,9 @@ import okhttp3.CookieJar import okhttp3.OkHttpClient import org.koin.android.ext.koin.androidContext import org.koin.core.qualifier.named +import org.koin.dsl.bind import org.koin.dsl.module +import org.koitharu.kotatsu.core.network.cookies.ClearableCookieJar import org.koitharu.kotatsu.core.network.cookies.PersistentCookieJar import org.koitharu.kotatsu.core.network.cookies.cache.SetCookieCache import org.koitharu.kotatsu.core.network.cookies.persistence.SharedPrefsCookiePersistor @@ -18,7 +20,7 @@ val networkModule SetCookieCache(), SharedPrefsCookiePersistor(androidContext()) ) - } + } bind ClearableCookieJar::class single(named(CacheUtils.QUALIFIER_HTTP)) { CacheUtils.createHttpCache(androidContext()) } single { OkHttpClient.Builder().apply { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt index 37d15b230..081fda67c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/UserAgentInterceptor.kt @@ -2,16 +2,22 @@ package org.koitharu.kotatsu.core.network import android.os.Build import okhttp3.Interceptor +import okhttp3.Response import org.koitharu.kotatsu.BuildConfig import java.util.* class UserAgentInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain) = chain.proceed( - chain.request().newBuilder() - .header(HEADER_USER_AGENT, userAgent) - .build() - ) + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + return chain.proceed( + if (request.header(HEADER_USER_AGENT) == null) { + request.newBuilder() + .header(HEADER_USER_AGENT, userAgent) + .build() + } else request + ) + } companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PersistentCookieJar.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PersistentCookieJar.kt index 5a61f4c6c..82dc45b86 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PersistentCookieJar.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PersistentCookieJar.kt @@ -35,7 +35,7 @@ class PersistentCookieJar( cache.addAll(persistor.loadAll()) } cache.addAll(cookies) - persistor.saveAll(filterPersistentCookies(cookies)) + persistor.saveAll(cookies.filter { it.persistent }) } @Synchronized @@ -48,11 +48,14 @@ class PersistentCookieJar( val it = cache.iterator() while (it.hasNext()) { val currentCookie = it.next() - if (isCookieExpired(currentCookie)) { - cookiesToRemove.add(currentCookie) - it.remove() - } else if (currentCookie.matches(url)) { - validCookies.add(currentCookie) + when { + currentCookie.isExpired() -> { + cookiesToRemove.add(currentCookie) + it.remove() + } + currentCookie.matches(url) -> { + validCookies.add(currentCookie) + } } } persistor.removeAll(cookiesToRemove) @@ -73,18 +76,8 @@ class PersistentCookieJar( private companion object { - fun filterPersistentCookies(cookies: List): List { - val persistentCookies: MutableList = ArrayList() - for (cookie in cookies) { - if (cookie.persistent) { - persistentCookies.add(cookie) - } - } - return persistentCookies - } - - fun isCookieExpired(cookie: Cookie): Boolean { - return cookie.expiresAt < System.currentTimeMillis() + fun Cookie.isExpired(): Boolean { + return expiresAt < System.currentTimeMillis() } } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt index 4fbfbdcbb..3886bc8b7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/ParserModule.kt @@ -19,7 +19,7 @@ val parserModule factory(named(MangaSource.HENCHAN)) { HenChanRepository(get()) } factory(named(MangaSource.YAOICHAN)) { YaoiChanRepository(get()) } factory(named(MangaSource.MANGATOWN)) { MangaTownRepository(get()) } - factory(named(MangaSource.MANGALIB)) { MangaLibRepository(get()) } + single(named(MangaSource.MANGALIB)) { MangaLibRepository(get()) } factory(named(MangaSource.NUDEMOON)) { NudeMoonRepository(get()) } factory(named(MangaSource.MANGAREAD)) { MangareadRepository(get()) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt index 83c1f2de1..e520c1a6e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/ChanRepository.kt @@ -56,7 +56,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe ).firstOrNull()?.text(), coverUrl = row.selectFirst("div.manga_images")?.selectFirst("img") ?.attr("src")?.withDomain(domain).orEmpty(), - tags = safe { + tags = runCatching { row.selectFirst("div.genre")?.select("a")?.mapToSet { MangaTag( title = it.text(), @@ -64,7 +64,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe source = source ) } - }.orEmpty(), + }.getOrNull().orEmpty(), source = source ) } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt index 0a8d02522..41a02faff 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/GroupleRepository.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.core.parser.site import androidx.collection.arraySetOf -import androidx.core.net.toUri +import okhttp3.HttpUrl.Companion.toHttpUrl import org.koitharu.kotatsu.base.domain.MangaLoaderContext import org.koitharu.kotatsu.core.exceptions.ParseException import org.koitharu.kotatsu.core.model.* @@ -53,7 +53,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) : }.parseHtml() val root = doc.body().getElementById("mangaBox") ?.selectFirst("div.tiles.row") ?: throw ParseException("Cannot find root") - val baseHost = root.baseUri().toUri().host + val baseHost = root.baseUri().toHttpUrl().host return root.select("div.tile").mapNotNull { node -> val imgDiv = node.selectFirst("div.img") ?: return@mapNotNull null val descDiv = node.selectFirst("div.desc") ?: return@mapNotNull null @@ -61,7 +61,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) : return@mapNotNull null //skip author } val href = imgDiv.selectFirst("a").attr("href")?.inContextOf(node) - if (href == null || href.toUri().host != baseHost) { + if (href == null || href.toHttpUrl().host != baseHost) { return@mapNotNull null // skip external links } val title = descDiv.selectFirst("h3")?.selectFirst("a")?.text() @@ -73,15 +73,15 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) : title = title, altTitle = descDiv.selectFirst("h4")?.text(), coverUrl = imgDiv.selectFirst("img.lazy")?.attr("data-original").orEmpty(), - rating = safe { + rating = runCatching { node.selectFirst("div.rating") ?.attr("title") ?.substringBefore(' ') ?.toFloatOrNull() ?.div(10f) - } ?: Manga.NO_RATING, + }.getOrNull() ?: Manga.NO_RATING, author = tileInfo?.selectFirst("a.person-link")?.text(), - tags = safe { + tags = runCatching { tileInfo?.select("a.element-link") ?.mapToSet { MangaTag( @@ -90,7 +90,7 @@ abstract class GroupleRepository(loaderContext: MangaLoaderContext) : source = source ) } - }.orEmpty(), + }.getOrNull().orEmpty(), state = when { node.selectFirst("div.tags") ?.selectFirst("span.mangaCompleted") != null -> MangaState.FINISHED diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt index 21d041768..201689d9b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/site/MangaLibRepository.kt @@ -80,14 +80,14 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) : val title = root.selectFirst("div.media-header__wrap")?.children() val info = root.selectFirst("div.media-content") val chaptersDoc = loaderContext.httpGet(manga.url + "?section=chapters").parseHtml() - val scripts = chaptersDoc.body().select("script") + val scripts = chaptersDoc.select("script") var chapters: ArrayList? = null scripts@ for (script in scripts) { val raw = script.html().lines() for (line in raw) { - if (line.startsWith("window.__CHAPTERS_DATA__")) { + if (line.startsWith("window.__DATA__")) { val json = JSONObject(line.substringAfter('=').substringBeforeLast(';')) - val list = json.getJSONArray("list") + val list = json.getJSONObject("chapters").getJSONArray("list") val total = list.length() chapters = ArrayList(total) for (i in 0 until total) { @@ -99,7 +99,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) : append("/c") append(item.getString("chapter_number")) append('/') - append(item.getJSONArray("teams").getJSONObject(0).optString("slug")) + append(item.optString("chapter_string")) } var name = item.getString("chapter_name") if (name.isNullOrBlank() || name == "null") { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 80d4b9b28..91f4a72dc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -149,6 +149,7 @@ class AppSettings private constructor(private val prefs: SharedPreferences) : const val KEY_SOURCES_HIDDEN = "sources_hidden" const val KEY_TRAFFIC_WARNING = "traffic_warning" const val KEY_PAGES_CACHE_CLEAR = "pages_cache_clear" + const val KEY_COOKIES_CLEAR = "cookies_clear" const val KEY_THUMBS_CACHE_CLEAR = "thumbs_cache_clear" const val KEY_SEARCH_HISTORY_CLEAR = "search_history_clear" const val KEY_UPDATES_FEED_CLEAR = "updates_feed_clear" diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index a131d35c7..5c56f9cf1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -17,7 +17,6 @@ import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.safe import java.io.IOException class DetailsViewModel( @@ -93,7 +92,7 @@ class DetailsViewModel( launchLoadingJob(Dispatchers.Default) { val original = localMangaRepository.getRemoteManga(manga) localMangaRepository.delete(manga) || throw IOException("Unable to delete file") - safe { + runCatching { historyRepository.deleteOrSwap(manga, original) } onMangaRemoved.postCall(manga) diff --git a/app/src/main/java/org/koitharu/kotatsu/download/DownloadService.kt b/app/src/main/java/org/koitharu/kotatsu/download/DownloadService.kt index 0b3c3d1b6..5d5fef624 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/DownloadService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/DownloadService.kt @@ -92,13 +92,13 @@ class DownloadService : BaseService() { var output: MangaZip? = null try { val repo = manga.source.repository - val cover = safe { + val cover = runCatching { imageLoader.execute( ImageRequest.Builder(this@DownloadService) .data(manga.coverUrl) .build() ).drawable - } + }.getOrNull() notification.setLargeIcon(cover) notification.update() val data = if (manga.chapters == null) repo.getDetails(manga) else manga diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt index 255c1a5c6..ee7a06df4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt @@ -9,7 +9,6 @@ import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.model.MangaTag import org.koitharu.kotatsu.utils.ext.getStringOrNull import org.koitharu.kotatsu.utils.ext.mapToSet -import org.koitharu.kotatsu.utils.ext.safe class MangaIndex(source: String?) { @@ -40,7 +39,7 @@ class MangaIndex(source: String?) { json.put("app_version", BuildConfig.VERSION_CODE) } - fun getMangaInfo(): Manga? = if (json.length() == 0) null else safe { + fun getMangaInfo(): Manga? = if (json.length() == 0) null else runCatching { val source = MangaSource.valueOf(json.getString("source")) Manga( id = json.getLong("id"), @@ -60,7 +59,7 @@ class MangaIndex(source: String?) { }, chapters = getChapters(json.getJSONObject("chapters"), source) ) - } + }.getOrNull() fun getCoverEntry(): String? = json.optString("cover_entry") diff --git a/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt index 34dd84e87..4948b9862 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt @@ -15,7 +15,6 @@ import org.koitharu.kotatsu.local.data.MangaZip import org.koitharu.kotatsu.utils.AlphanumComparator import org.koitharu.kotatsu.utils.ext.longHashCode import org.koitharu.kotatsu.utils.ext.readText -import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.sub import java.io.File import java.util.* @@ -37,7 +36,7 @@ class LocalMangaRepository(private val context: Context) : MangaRepository { } val files = getAvailableStorageDirs(context) .flatMap { x -> x.listFiles(filenameFilter)?.toList().orEmpty() } - return files.mapNotNull { x -> safe { getFromFile(x) } } + return files.mapNotNull { x -> runCatching { getFromFile(x) }.getOrNull() } } override suspend fun getDetails(manga: Manga) = if (manga.chapters == null) { @@ -128,9 +127,9 @@ class LocalMangaRepository(private val context: Context) : MangaRepository { } fun getRemoteManga(localManga: Manga): Manga? { - val file = safe { + val file = runCatching { Uri.parse(localManga.url).toFile() - } ?: return null + }.getOrNull() ?: return null val zip = ZipFile(file) val entry = zip.getEntry(MangaZip.INDEX_ENTRY) val index = entry?.let(zip::readText)?.let(::MangaIndex) ?: return null diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt index 4a3edd294..cb602772d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt @@ -22,7 +22,6 @@ import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.utils.MediaStoreCompat import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct -import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.sub import java.io.IOException @@ -49,7 +48,10 @@ class LocalListViewModel( list.isEmpty() -> listOf(EmptyState(R.string.text_local_holder)) else -> list.toUi(mode) } - }.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.asLiveDataDistinct( + viewModelScope.coroutineContext + Dispatchers.Default, + listOf(LoadingState) + ) init { onRefresh() @@ -94,7 +96,7 @@ class LocalListViewModel( withContext(Dispatchers.Default) { val original = repository.getRemoteManga(manga) repository.delete(manga) || throw IOException("Unable to delete file") - safe { + runCatching { historyRepository.deleteOrSwap(manga, original) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/PageLoader.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt index b918e66ec..1c16b6567 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui +package org.koitharu.kotatsu.reader.domain import android.graphics.Bitmap import android.graphics.BitmapFactory diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt index 4778febb5..a9cdaf2ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt @@ -5,7 +5,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader abstract class BasePageHolder( protected val binding: B, diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReader.kt index 12a768b9a..8d9fde1b1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReader.kt @@ -8,7 +8,7 @@ import androidx.viewbinding.ViewBinding import org.koin.android.ext.android.get import org.koin.androidx.viewmodel.ext.android.sharedViewModel import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt index f084b4ae6..495287e9f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt @@ -6,7 +6,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.utils.ext.resetTransformations import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt index 7bec0652d..b0c350d3c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt @@ -9,7 +9,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ResolvableException import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.utils.ext.launchAfter import org.koitharu.kotatsu.utils.ext.launchInstead import java.io.File diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt index b98ab2239..edf5b205b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt @@ -6,7 +6,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.standard.PageHolder class ReversedPageHolder( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt index ecaea29bf..aebb58b18 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt @@ -5,7 +5,7 @@ import android.view.ViewGroup import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter class ReversedPagesAdapter( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt index 08683dbb4..369bccf48 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt @@ -12,7 +12,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ResolvableException import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.BasePageHolder import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.utils.ext.getDisplayMessage diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt index aa27be5b2..553139c76 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt @@ -5,7 +5,7 @@ import android.view.ViewGroup import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter class PagesAdapter( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt index d05ce562e..34e3b4713 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt @@ -5,7 +5,7 @@ import android.view.ViewGroup import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageWebtoonBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter class WebtoonAdapter( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt index b50f21ee8..f7ac4b541 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt @@ -11,7 +11,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ResolvableException import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.ItemPageWebtoonBinding -import org.koitharu.kotatsu.reader.ui.PageLoader +import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.pager.BasePageHolder import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.utils.ext.getDisplayMessage diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchHelper.kt index 5ca13fad5..6f937b2eb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchHelper.kt @@ -7,7 +7,6 @@ import android.view.MenuItem import androidx.appcompat.widget.SearchView import org.koitharu.kotatsu.R import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity -import org.koitharu.kotatsu.utils.ext.safe import java.io.Closeable object SearchHelper { @@ -43,10 +42,10 @@ object SearchHelper { override fun onSuggestionSelect(position: Int) = false override fun onSuggestionClick(position: Int): Boolean { - val query = safe { + val query = runCatching { val c = view.suggestionsAdapter.getItem(position) as? Cursor c?.getString(c.getColumnIndex(SearchManager.SUGGEST_COLUMN_QUERY)) - } ?: return false + }.getOrNull() ?: return false view.setQuery(query, true) return true } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt index 45abfe9d2..ab6a635d8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt @@ -7,9 +7,11 @@ import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.koin.android.ext.android.get import org.koin.android.ext.android.inject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.network.cookies.ClearableCookieJar import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.local.data.Cache import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider @@ -71,6 +73,20 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach clearCache(preference, Cache.THUMBS) true } + AppSettings.KEY_COOKIES_CLEAR -> { + viewLifecycleScope.launch { + val cookieJar = get() + withContext(Dispatchers.IO) { + cookieJar.clear() + } + Snackbar.make( + listView ?: return@launch, + R.string.cookies_cleared, + Snackbar.LENGTH_SHORT + ).show() + } + true + } AppSettings.KEY_SEARCH_HISTORY_CLEAR -> { viewLifecycleScope.launch { MangaSuggestionsProvider.clearHistory(preference.context) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesAdapter.kt index 29ed9c3e8..29a76001b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesAdapter.kt @@ -9,18 +9,18 @@ import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.utils.ext.mapToSet -import org.koitharu.kotatsu.utils.ext.safe class SourcesAdapter( private val settings: AppSettings, private val onItemClickListener: OnListItemClickListener, ) : RecyclerView.Adapter() { - private val dataSet = MangaProviderFactory.getSources(settings, includeHidden = true).toMutableList() + private val dataSet = + MangaProviderFactory.getSources(settings, includeHidden = true).toMutableList() private val hiddenItems = settings.hiddenSources.mapNotNull { - safe { + runCatching { MangaSource.valueOf(it) - } + }.getOrNull() }.toMutableSet() override fun onCreateViewHolder( diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt index 9efae09da..1267734c7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt @@ -21,7 +21,6 @@ import org.koitharu.kotatsu.core.model.MangaChapter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.toBitmapOrNull import org.koitharu.kotatsu.utils.ext.toUriOrNull import java.util.concurrent.TimeUnit @@ -37,23 +36,23 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : private val repository by inject() private val settings by inject() - override suspend fun doWork(): Result = withContext(Dispatchers.Default) { + override suspend fun doWork(): Result { val trackSources = settings.trackSources if (trackSources.isEmpty()) { - return@withContext Result.success() + return Result.success() } val tracks = repository.getAllTracks( useFavourites = AppSettings.TRACK_FAVOURITES in trackSources, useHistory = AppSettings.TRACK_HISTORY in trackSources ) if (tracks.isEmpty()) { - return@withContext Result.success() + return Result.success() } var success = 0 for (track in tracks) { - val details = safe { + val details = runCatching { track.manga.source.repository.getDetails(track.manga) - } + }.getOrNull() val chapters = details?.chapters ?: continue when { track.knownChaptersCount == -1 -> { //first check @@ -125,7 +124,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : success++ } repository.cleanup() - if (success == 0) { + return if (success == 0) { Result.retry() } else { Result.success() diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt index ea806d4a1..14bfe4bbd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.utils.ext import android.content.res.Resources import android.util.Log import kotlinx.coroutines.delay -import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException @@ -12,15 +11,6 @@ import org.koitharu.kotatsu.core.exceptions.WrongPasswordException import java.io.FileNotFoundException import java.net.SocketTimeoutException -inline fun T.safe(action: T.() -> R?) = try { - this.action() -} catch (e: Throwable) { - if (BuildConfig.DEBUG) { - e.printStackTrace() - } - null -} - suspend inline fun T.retryUntilSuccess(maxAttempts: Int, action: T.() -> R): R { var attempts = maxAttempts while (true) { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt index fc11e622d..07fd92743 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt @@ -35,11 +35,11 @@ inline fun File.findParent(predicate: (File) -> Boolean): File? { return current } -fun File.getStorageName(context: Context): String = safe { +fun File.getStorageName(context: Context): String = runCatching { val manager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { manager.getStorageVolume(this)?.getDescription(context)?.let { - return@safe it + return@runCatching it } } when { @@ -47,6 +47,6 @@ fun File.getStorageName(context: Context): String = safe { Environment.isExternalStorageRemovable(this) -> context.getString(R.string.external_storage) else -> null } -} ?: context.getString(R.string.other_storage) +}.getOrNull() ?: context.getString(R.string.other_storage) fun Uri.toFileOrNull() = if (scheme == "file") path?.let(::File) else null \ No newline at end of file diff --git a/app/src/main/res/menu/opt_list_sheet.xml b/app/src/main/res/menu/opt_list_sheet.xml deleted file mode 100644 index 421f8a2c5..000000000 --- a/app/src/main/res/menu/opt_list_sheet.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fe09c4386..999c15302 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -190,4 +190,6 @@ Без звука Необходимо пройти CAPTCHA Resolve + Очистить куки + Все куки удалены \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 94444f5a1..a264fd016 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -192,4 +192,6 @@ Silent CAPTCHA is required Resolve + Clear cookies + All cookies was removed \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9aa5e9924..c67cfeafb 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -8,13 +8,6 @@ 10dp - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/pref_history.xml b/app/src/main/res/xml/pref_history.xml index 3c2f7ec14..e23be0ed6 100644 --- a/app/src/main/res/xml/pref_history.xml +++ b/app/src/main/res/xml/pref_history.xml @@ -16,8 +16,8 @@ app:iconSpaceReserved="false" /> + android:title="@string/cache" + app:iconSpaceReserved="false"> + + \ No newline at end of file