From 3f96f34b8e0a336f5da412041524a64e7d1b10fa Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 17 May 2023 15:36:25 +0300 Subject: [PATCH 01/90] Improve pages thumbnails sheet --- .../utils/LoggingAdapterDataObserver.kt | 37 ++++ .../base/ui/widgets/BottomSheetHeaderBar.kt | 3 + .../ui/adapter/BookmarksGroupAdapter.kt | 5 + .../org/koitharu/kotatsu/core/AppModule.kt | 4 + .../kotatsu/details/ui/DetailsActivity.kt | 28 ++- .../kotatsu/list/ui/adapter/ListHeaderAD.kt | 8 +- .../list/ui/adapter/MangaListAdapter.kt | 5 + .../kotatsu/list/ui/model/LoadingFooter.kt | 17 +- .../koitharu/kotatsu/local/data/CbzFilter.kt | 6 + .../kotatsu/reader/domain/ChaptersLoader.kt | 4 + .../kotatsu/reader/domain/PageLoader.kt | 27 +-- .../kotatsu/reader/ui/ReaderActivity.kt | 28 ++- .../kotatsu/reader/ui/ReaderSliderListener.kt | 4 +- .../kotatsu/reader/ui/ReaderViewModel.kt | 4 +- .../reader/ui/thumbnails/MangaPageFetcher.kt | 112 ++++++++++++ .../ui/thumbnails/OnPageSelectListener.kt | 6 +- .../reader/ui/thumbnails/PageThumbnail.kt | 33 +++- .../ui/thumbnails/PagesThumbnailsSheet.kt | 164 +++++++++++------- .../ui/thumbnails/PagesThumbnailsViewModel.kt | 107 ++++++++++++ .../ui/thumbnails/adapter/PageThumbnailAD.kt | 82 +++------ .../adapter/PageThumbnailAdapter.kt | 61 +++++-- .../adapter/TargetScrollObserver.kt | 41 +++++ .../remotelist/ui/RemoteListViewModel.kt | 2 +- .../selector/ScrobblingSelectorViewModel.kt | 4 +- .../adapter/ScrobblerSelectorAdapter.kt | 2 + .../kotatsu/search/ui/SearchViewModel.kt | 2 +- .../search/ui/multi/MultiSearchViewModel.kt | 2 +- .../ui/multi/adapter/MultiSearchAdapter.kt | 5 + .../kotatsu/shelf/ui/adapter/ShelfAdapter.kt | 5 + .../tracker/ui/feed/adapter/FeedAdapter.kt | 5 + app/src/main/res/menu/popup_read.xml | 6 + 31 files changed, 632 insertions(+), 187 deletions(-) create mode 100644 app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt diff --git a/app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt b/app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt new file mode 100644 index 000000000..e4221be71 --- /dev/null +++ b/app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt @@ -0,0 +1,37 @@ +package org.koitharu.kotatsu.utils + +import android.util.Log +import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver + +class LoggingAdapterDataObserver( + private val tag: String, +) : AdapterDataObserver() { + + override fun onChanged() { + Log.d(tag, "onChanged()") + } + + override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { + Log.d(tag, "onItemRangeChanged(positionStart=$positionStart, itemCount=$itemCount)") + } + + override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) { + Log.d(tag, "onItemRangeChanged(positionStart=$positionStart, itemCount=$itemCount, payload=$payload)") + } + + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + Log.d(tag, "onItemRangeInserted(positionStart=$positionStart, itemCount=$itemCount)") + } + + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + Log.d(tag, "onItemRangeRemoved(positionStart=$positionStart, itemCount=$itemCount)") + } + + override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { + Log.d(tag, "onItemRangeMoved(fromPosition=$fromPosition, toPosition=$toPosition, itemCount=$itemCount)") + } + + override fun onStateRestorationPolicyChanged() { + Log.d(tag, "onStateRestorationPolicyChanged()") + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt index 80b5749bf..3f01e8769 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt @@ -70,6 +70,9 @@ class BottomSheetHeaderBar @JvmOverloads constructor( binding.toolbar.subtitle = value } + val isExpanded: Boolean + get() = binding.dragHandle.isGone + init { setBackgroundResource(R.drawable.sheet_toolbar_background) layoutTransition = LayoutTransition().apply { diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt index a73d0a0c1..a51a00ec2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt @@ -15,6 +15,7 @@ import org.koitharu.kotatsu.list.ui.adapter.errorStateListAD import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.parsers.model.Manga import kotlin.jvm.internal.Intrinsics @@ -54,6 +55,10 @@ class BookmarksGroupAdapter( oldItem.manga.id == newItem.manga.id } + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + else -> oldItem.javaClass == newItem.javaClass } } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt index 6797915b1..1797b4213 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt @@ -46,8 +46,10 @@ import org.koitharu.kotatsu.local.data.CbzFetcher import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.LocalStorageManager +import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.reader.ui.thumbnails.MangaPageFetcher import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider import org.koitharu.kotatsu.settings.backup.BackupObserver import org.koitharu.kotatsu.sync.domain.SyncController @@ -136,6 +138,7 @@ interface AppModule { @ApplicationContext context: Context, okHttpClient: OkHttpClient, mangaRepositoryFactory: MangaRepository.Factory, + pagesCache: PagesCache, ): ImageLoader { val httpClientFactory = { okHttpClient.newBuilder() @@ -162,6 +165,7 @@ interface AppModule { .add(SvgDecoder.Factory()) .add(CbzFetcher.Factory()) .add(FaviconFetcher.Factory(context, okHttpClient, mangaRepositoryFactory)) + .add(MangaPageFetcher.Factory(context, okHttpClient, pagesCache, mangaRepositoryFactory)) .build(), ).build() } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index d5ac27063..b2c3e08ae 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -43,6 +43,7 @@ import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState +import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet import org.koitharu.kotatsu.utils.ViewBadge import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat import org.koitharu.kotatsu.utils.ext.textAndVisible @@ -158,13 +159,28 @@ class DetailsActivity : else -> false } - override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) { - R.id.action_incognito -> { - openReader(isIncognitoMode = true) - true - } + override fun onMenuItemClick(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.action_incognito -> { + openReader(isIncognitoMode = true) + true + } - else -> false + R.id.action_pages_thumbs -> { + val history = viewModel.historyInfo.value?.history + PagesThumbnailsSheet.show( + fm = supportFragmentManager, + manga = viewModel.manga.value ?: return false, + chapterId = history?.chapterId + ?: viewModel.chapters.value?.firstOrNull()?.chapter?.id + ?: return false, + currentPage = history?.page ?: 0, + ) + true + } + + else -> false + } } override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt index 855c70c1f..feaa97b0d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt @@ -7,12 +7,14 @@ import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun listHeaderAD( - listener: ListHeaderClickListener, + listener: ListHeaderClickListener?, ) = adapterDelegateViewBinding( { inflater, parent -> ItemHeaderButtonBinding.inflate(inflater, parent, false) }, ) { - binding.buttonMore.setOnClickListener { - listener.onListHeaderClick(item, it) + if (listener != null) { + binding.buttonMore.setOnClickListener { + listener.onListHeaderClick(item, it) + } } bind { diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt index 1be69ef00..cabf3a0e1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt @@ -8,6 +8,7 @@ import org.koitharu.kotatsu.core.ui.DateTimeAgo import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListHeader2 import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.list.ui.model.MangaGridModel import org.koitharu.kotatsu.list.ui.model.MangaItemModel import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel @@ -60,6 +61,10 @@ open class MangaListAdapter( oldItem.dateTimeAgo == newItem.dateTimeAgo } + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + else -> oldItem.javaClass == newItem.javaClass } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt index 7a754dcc6..c7c336a7a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt @@ -1,6 +1,19 @@ package org.koitharu.kotatsu.list.ui.model -object LoadingFooter : ListModel { +class LoadingFooter @JvmOverloads constructor( + val key: Int = 0, +) : ListModel { - override fun equals(other: Any?): Boolean = other === LoadingFooter + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as LoadingFooter + + return key == other.key + } + + override fun hashCode(): Int { + return key + } } diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt index f74d30258..24e9f8a2d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.local.data +import android.net.Uri import java.io.File import java.io.FileFilter import java.io.FilenameFilter @@ -21,5 +22,10 @@ class CbzFilter : FileFilter, FilenameFilter { val ext = name.substringAfterLast('.', "").lowercase(Locale.ROOT) return ext == "cbz" || ext == "zip" } + + fun isUriSupported(uri: Uri): Boolean { + val scheme = uri.scheme?.lowercase(Locale.ROOT) + return scheme != null && scheme == "cbz" || scheme == "zip" + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt index ecd163e36..334efab8a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt @@ -63,6 +63,10 @@ class ChaptersLoader @Inject constructor( return chapterPages.size(chapterId) } + fun last() = chapterPages.last() + + fun first() = chapterPages.first() + fun snapshot() = chapterPages.toList() private suspend fun loadChapter(manga: Manga, chapterId: Long): List { diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt index a4ba27794..e4f5c1269 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -25,6 +25,7 @@ import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource @@ -42,9 +43,6 @@ import javax.inject.Inject import kotlin.coroutines.AbstractCoroutineContextElement import kotlin.coroutines.CoroutineContext -private const val PROGRESS_UNDEFINED = -1f -private const val PREFETCH_LIMIT_DEFAULT = 10 - @ActivityRetainedScoped class PageLoader @Inject constructor( lifecycle: ActivityRetainedLifecycle, @@ -179,7 +177,7 @@ class PageLoader @Inject constructor( val pageUrl = getPageUrl(page) check(pageUrl.isNotBlank()) { "Cannot obtain full image url" } val uri = Uri.parse(pageUrl) - return if (uri.scheme == "cbz") { + return if (CbzFilter.isUriSupported(uri)) { runInterruptible(Dispatchers.IO) { ZipFile(uri.schemeSpecificPart) }.use { zip -> @@ -191,13 +189,7 @@ class PageLoader @Inject constructor( } } } else { - val request = Request.Builder() - .url(pageUrl) - .get() - .header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8") - .cacheControl(CommonHeaders.CACHE_CONTROL_NO_STORE) - .tag(MangaSource::class.java, page.source) - .build() + val request = createPageRequest(page, pageUrl) okHttp.newCall(request).await().use { response -> check(response.isSuccessful) { "Invalid response: ${response.code} ${response.message} at $pageUrl" @@ -218,6 +210,19 @@ class PageLoader @Inject constructor( override fun handleException(context: CoroutineContext, exception: Throwable) { exception.printStackTraceDebug() } + } + + companion object { + + private const val PROGRESS_UNDEFINED = -1f + private const val PREFETCH_LIMIT_DEFAULT = 10 + fun createPageRequest(page: MangaPage, pageUrl: String) = Request.Builder() + .url(pageUrl) + .get() + .header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8") + .cacheControl(CommonHeaders.CACHE_CONTROL_NO_STORE) + .tag(MangaSource::class.java, page.source) + .build() } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index e9a314b48..b3deab1df 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -40,8 +40,8 @@ import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.databinding.ActivityReaderBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter -import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.ui.config.ReaderConfigBottomSheet +import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState import org.koitharu.kotatsu.reader.ui.thumbnails.OnPageSelectListener import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet @@ -180,17 +180,13 @@ class ReaderActivity : } R.id.action_pages_thumbs -> { - val pages = viewModel.getCurrentChapterPages() - if (!pages.isNullOrEmpty()) { - PagesThumbnailsSheet.show( - supportFragmentManager, - pages, - title?.toString().orEmpty(), - readerManager.currentReader?.getCurrentState()?.page ?: -1, - ) - } else { - return false - } + val state = viewModel.getCurrentState() ?: return false + PagesThumbnailsSheet.show( + supportFragmentManager, + viewModel.manga ?: return false, + state.chapterId, + state.page, + ) } R.id.action_bookmark -> { @@ -259,17 +255,19 @@ class ReaderActivity : } override fun onChapterChanged(chapter: MangaChapter) { - viewModel.switchChapter(chapter.id) + viewModel.switchChapter(chapter.id, 0) } - override fun onPageSelected(page: MangaPage) { + override fun onPageSelected(page: ReaderPage) { lifecycleScope.launch(Dispatchers.Default) { val pages = viewModel.content.value?.pages ?: return@launch - val index = pages.indexOfFirst { it.id == page.id } + val index = pages.indexOfFirst { it.chapterId == page.chapterId && it.id == page.id } if (index != -1) { withContext(Dispatchers.Main) { readerManager.currentReader?.switchPageTo(index, true) } + } else { + viewModel.switchChapter(page.chapterId, page.index) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt index bd959969d..50e87a4d9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.reader.ui import com.google.android.material.slider.Slider +import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.reader.ui.thumbnails.OnPageSelectListener class ReaderSliderListener( @@ -41,6 +42,7 @@ class ReaderSliderListener( private fun switchPageToIndex(index: Int) { val pages = viewModel.getCurrentChapterPages() val page = pages?.getOrNull(index) ?: return - pageSelectListener.onPageSelected(page) + val chapterId = viewModel.getCurrentState()?.chapterId ?: return + pageSelectListener.onPageSelected(ReaderPage(page, index, chapterId)) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index da7f04e5b..c4d6bdc5b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -237,13 +237,13 @@ class ReaderViewModel @Inject constructor( }?.toMangaPage() } - fun switchChapter(id: Long) { + fun switchChapter(id: Long, page: Int) { val prevJob = loadingJob loadingJob = launchLoadingJob(Dispatchers.Default) { prevJob?.cancelAndJoin() content.postValue(ReaderContent(emptyList(), null)) chaptersLoader.loadSingleChapter(mangaData.requireValue(), id) - content.postValue(ReaderContent(chaptersLoader.snapshot(), ReaderState(id, 0, 0))) + content.postValue(ReaderContent(chaptersLoader.snapshot(), ReaderState(id, page, 0))) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt new file mode 100644 index 000000000..3246d0a99 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt @@ -0,0 +1,112 @@ +package org.koitharu.kotatsu.reader.ui.thumbnails + +import android.content.Context +import androidx.core.net.toUri +import coil.ImageLoader +import coil.decode.DataSource +import coil.decode.ImageSource +import coil.fetch.FetchResult +import coil.fetch.Fetcher +import coil.fetch.SourceResult +import coil.request.Options +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runInterruptible +import okhttp3.OkHttpClient +import okio.Path.Companion.toOkioPath +import okio.buffer +import okio.source +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.local.data.CbzFilter +import org.koitharu.kotatsu.local.data.PagesCache +import org.koitharu.kotatsu.local.data.util.withExtraCloseable +import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.parsers.util.await +import org.koitharu.kotatsu.parsers.util.mimeType +import org.koitharu.kotatsu.reader.domain.PageLoader +import java.util.zip.ZipFile + +class MangaPageFetcher( + private val context: Context, + private val okHttpClient: OkHttpClient, + private val pagesCache: PagesCache, + private val options: Options, + private val page: MangaPage, + private val mangaRepositoryFactory: MangaRepository.Factory, +) : Fetcher { + + override suspend fun fetch(): FetchResult { + val repo = mangaRepositoryFactory.create(page.source) + val pageUrl = repo.getPageUrl(page) + pagesCache.get(pageUrl)?.let { file -> + return SourceResult( + source = ImageSource( + file = file.toOkioPath(), + metadata = MangaPageMetadata(page), + ), + mimeType = null, + dataSource = DataSource.DISK, + ) + } + return loadPage(pageUrl) + } + + private suspend fun loadPage(pageUrl: String): SourceResult { + val uri = pageUrl.toUri() + return if (CbzFilter.isUriSupported(uri)) { + val zip = runInterruptible(Dispatchers.IO) { ZipFile(uri.schemeSpecificPart) } + val entry = runInterruptible(Dispatchers.IO) { zip.getEntry(uri.fragment) } + return SourceResult( + source = ImageSource( + source = zip.getInputStream(entry).source().withExtraCloseable(zip).buffer(), + context = context, + metadata = MangaPageMetadata(page), + ), + mimeType = null, + dataSource = DataSource.DISK, + ) + } else { + val request = PageLoader.createPageRequest(page, pageUrl) + okHttpClient.newCall(request).await().use { response -> + check(response.isSuccessful) { + "Invalid response: ${response.code} ${response.message} at $pageUrl" + } + val body = checkNotNull(response.body) { + "Null response" + } + val mimeType = response.mimeType + val file = body.use { + pagesCache.put(pageUrl, it.source()) + } + SourceResult( + source = ImageSource( + file = file.toOkioPath(), + metadata = MangaPageMetadata(page), + ), + mimeType = mimeType, + dataSource = DataSource.NETWORK, + ) + } + } + } + + class Factory( + private val context: Context, + private val okHttpClient: OkHttpClient, + private val pagesCache: PagesCache, + private val mangaRepositoryFactory: MangaRepository.Factory, + ) : Fetcher.Factory { + + override fun create(data: MangaPage, options: Options, imageLoader: ImageLoader): Fetcher { + return MangaPageFetcher( + okHttpClient = okHttpClient, + pagesCache = pagesCache, + options = options, + page = data, + context = context, + mangaRepositoryFactory = mangaRepositoryFactory, + ) + } + } + + class MangaPageMetadata(val page: MangaPage) : ImageSource.Metadata() +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt index 38db30b5e..3b6281c64 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.reader.ui.thumbnails -import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.reader.ui.pager.ReaderPage fun interface OnPageSelectListener { - fun onPageSelected(page: MangaPage) -} \ No newline at end of file + fun onPageSelected(page: ReaderPage) +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt index 22c5ddad5..f413b9615 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt @@ -1,11 +1,34 @@ package org.koitharu.kotatsu.reader.ui.thumbnails import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -data class PageThumbnail( - val number: Int, +class PageThumbnail( val isCurrent: Boolean, val repository: MangaRepository, - val page: MangaPage -) \ No newline at end of file + val page: ReaderPage, +) : ListModel { + + val number + get() = page.index + 1 + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as PageThumbnail + + if (isCurrent != other.isCurrent) return false + if (repository != other.repository) return false + return page == other.page + } + + override fun hashCode(): Int { + var result = isCurrent.hashCode() + result = 31 * result + repository.hashCode() + result = 31 * result + page.hashCode() + return result + } + +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index 0d9ca8b22..80aee22e9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -5,38 +5,40 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.ui.BaseBottomSheet +import org.koitharu.kotatsu.base.ui.list.BoundsScrollListener import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.base.ui.list.ScrollListenerInvalidationObserver import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar -import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages -import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.databinding.SheetPagesBinding import org.koitharu.kotatsu.list.ui.MangaListSpanResolver -import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.reader.domain.PageLoader +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.reader.ui.ReaderActivity +import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter -import org.koitharu.kotatsu.utils.ext.getParcelableCompat -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope +import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.TargetScrollObserver +import org.koitharu.kotatsu.utils.LoggingAdapterDataObserver +import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @AndroidEntryPoint class PagesThumbnailsSheet : BaseBottomSheet(), - OnListItemClickListener, + OnListItemClickListener, BottomSheetHeaderBar.OnExpansionChangeListener { - @Inject - lateinit var mangaRepositoryFactory: MangaRepository.Factory - - @Inject - lateinit var pageLoader: PageLoader + private val viewModel by viewModels() @Inject lateinit var coil: ImageLoader @@ -44,27 +46,13 @@ class PagesThumbnailsSheet : @Inject lateinit var settings: AppSettings - private lateinit var thumbnails: List + private var thumbnailsAdapter: PageThumbnailAdapter? = null private var spanResolver: MangaListSpanResolver? = null - private var currentPageIndex = -1 - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val pages = arguments?.getParcelableCompat(ARG_PAGES)?.pages - if (pages.isNullOrEmpty()) { - dismissAllowingStateLoss() - return - } - currentPageIndex = requireArguments().getInt(ARG_CURRENT, currentPageIndex) - val repository = mangaRepositoryFactory.create(pages.first().source) - thumbnails = pages.mapIndexed { i, x -> - PageThumbnail( - number = i + 1, - isCurrent = i == currentPageIndex, - repository = repository, - page = x, - ) - } + private var scrollListener: ScrollListener? = null + + private val spanSizeLookup = SpanSizeLookup() + private val listCommitCallback = Runnable { + spanSizeLookup.invalidateCache() } override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetPagesBinding { @@ -73,74 +61,116 @@ class PagesThumbnailsSheet : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - spanResolver = MangaListSpanResolver(view.resources) with(binding.headerBar) { - title = arguments?.getString(ARG_TITLE) + title = viewModel.title subtitle = null addOnExpansionChangeListener(this@PagesThumbnailsSheet) } - + thumbnailsAdapter = PageThumbnailAdapter( + coil = coil, + lifecycleOwner = viewLifecycleOwner, + clickListener = this@PagesThumbnailsSheet, + ) with(binding.recyclerView) { addItemDecoration( SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)), ) - adapter = PageThumbnailAdapter( - dataSet = thumbnails, - coil = coil, - scope = viewLifecycleScope, - loader = pageLoader, - clickListener = this@PagesThumbnailsSheet, - ) + adapter = thumbnailsAdapter addOnLayoutChangeListener(spanResolver) spanResolver?.setGridSize(settings.gridSize / 100f, this) - if (currentPageIndex > 0) { - val offset = resources.getDimensionPixelOffset(R.dimen.preferred_grid_width) - (layoutManager as GridLayoutManager).scrollToPositionWithOffset(currentPageIndex, offset) - } + addOnScrollListener(ScrollListener().also { scrollListener = it }) + (layoutManager as GridLayoutManager).spanSizeLookup = spanSizeLookup + thumbnailsAdapter?.registerAdapterDataObserver( + ScrollListenerInvalidationObserver(this, checkNotNull(scrollListener)), + ) + thumbnailsAdapter?.registerAdapterDataObserver(TargetScrollObserver(this)) + thumbnailsAdapter?.registerAdapterDataObserver(LoggingAdapterDataObserver("THUMB")) + } + viewModel.thumbnails.observe(viewLifecycleOwner) { + thumbnailsAdapter?.setItems(it, listCommitCallback) + } + viewModel.branch.observe(viewLifecycleOwner) { + onExpansionStateChanged(binding.headerBar, binding.headerBar.isExpanded) } + viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) } override fun onDestroyView() { - super.onDestroyView() spanResolver = null + scrollListener = null + thumbnailsAdapter = null + spanSizeLookup.invalidateCache() + super.onDestroyView() } - override fun onItemClick(item: MangaPage, view: View) { - ( - (parentFragment as? OnPageSelectListener) - ?: (activity as? OnPageSelectListener) - )?.run { - onPageSelected(item) - dismiss() - } + override fun onItemClick(item: PageThumbnail, view: View) { + val listener = (parentFragment as? OnPageSelectListener) ?: (activity as? OnPageSelectListener) + if (listener != null) { + listener.onPageSelected(item.page) + } else { + val state = ReaderState(item.page.chapterId, item.page.index, 0) + val intent = ReaderActivity.newIntent(view.context, viewModel.manga, state) + startActivity(intent, scaleUpActivityOptionsOf(view).toBundle()) + } + dismiss() } override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { if (isExpanded) { - headerBar.subtitle = resources.getQuantityString( - R.plurals.pages, - thumbnails.size, - thumbnails.size, - ) + headerBar.subtitle = viewModel.branch.value } else { headerBar.subtitle = null } } + private inner class ScrollListener : BoundsScrollListener(3, 3) { + + override fun onScrolledToStart(recyclerView: RecyclerView) { + viewModel.loadPrevChapter() + } + + override fun onScrolledToEnd(recyclerView: RecyclerView) { + viewModel.loadNextChapter() + } + } + + private inner class SpanSizeLookup : GridLayoutManager.SpanSizeLookup() { + + init { + isSpanIndexCacheEnabled = true + isSpanGroupIndexCacheEnabled = true + } + + override fun getSpanSize(position: Int): Int { + val total = + (binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1 + return when (thumbnailsAdapter?.getItemViewType(position)) { + PageThumbnailAdapter.ITEM_TYPE_THUMBNAIL -> 1 + else -> total + } + } + + fun invalidateCache() { + invalidateSpanGroupIndexCache() + invalidateSpanIndexCache() + } + } + companion object { - private const val ARG_PAGES = "pages" - private const val ARG_TITLE = "title" - private const val ARG_CURRENT = "current" + const val ARG_MANGA = "manga" + const val ARG_CURRENT_PAGE = "current" + const val ARG_CHAPTER_ID = "chapter_id" private const val TAG = "PagesThumbnailsSheet" - fun show(fm: FragmentManager, pages: List, title: String, currentPage: Int) = + fun show(fm: FragmentManager, manga: Manga, chapterId: Long, currentPage: Int = -1) { PagesThumbnailsSheet().withArgs(3) { - putParcelable(ARG_PAGES, ParcelableMangaPages(pages)) - putString(ARG_TITLE, title) - putInt(ARG_CURRENT, currentPage) + putParcelable(ARG_MANGA, ParcelableManga(manga, true)) + putLong(ARG_CHAPTER_ID, chapterId) + putInt(ARG_CURRENT_PAGE, currentPage) }.show(fm, TAG) + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt new file mode 100644 index 000000000..00401578b --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -0,0 +1,107 @@ +package org.koitharu.kotatsu.reader.ui.thumbnails + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.list.ui.model.ListHeader +import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter +import org.koitharu.kotatsu.parsers.util.SuspendLazy +import org.koitharu.kotatsu.reader.data.filterChapters +import org.koitharu.kotatsu.reader.domain.ChaptersLoader +import org.koitharu.kotatsu.utils.ext.emitValue +import javax.inject.Inject + +@HiltViewModel +class PagesThumbnailsViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, + mangaRepositoryFactory: MangaRepository.Factory, + private val chaptersLoader: ChaptersLoader, +) : BaseViewModel() { + + private val currentPageIndex: Int = savedStateHandle[PagesThumbnailsSheet.ARG_CURRENT_PAGE] ?: -1 + private val initialChapterId: Long = savedStateHandle[PagesThumbnailsSheet.ARG_CHAPTER_ID] ?: 0L + val manga = requireNotNull(savedStateHandle.get(PagesThumbnailsSheet.ARG_MANGA)).manga + + private val repository = mangaRepositoryFactory.create(manga.source) + private val mangaDetails = SuspendLazy { + repository.getDetails(manga).let { + chaptersLoader.chapters.clear() + val b = manga.chapters?.find { ch -> ch.id == initialChapterId }?.branch + branch.emitValue(b) + it.getChapters(b)?.forEach { ch -> + chaptersLoader.chapters.put(ch.id, ch) + } + it.filterChapters(b) + } + } + private var loadingJob: Job? = null + private var loadingPrevJob: Job? = null + private var loadingNextJob: Job? = null + + val thumbnails = MutableLiveData>() + val branch = MutableLiveData() + val title = manga.title + + init { + loadingJob = launchJob(Dispatchers.Default) { + chaptersLoader.loadSingleChapter(mangaDetails.get(), initialChapterId) + updateList() + } + } + + fun loadPrevChapter() { + if (loadingJob?.isActive == true || loadingPrevJob?.isActive == true) { + return + } + loadingPrevJob = loadPrevNextChapter(isNext = false) + } + + fun loadNextChapter() { + if (loadingJob?.isActive == true || loadingNextJob?.isActive == true) { + return + } + loadingNextJob = loadPrevNextChapter(isNext = true) + } + + private fun loadPrevNextChapter(isNext: Boolean): Job = launchLoadingJob(Dispatchers.Default) { + val currentId = (if (isNext) chaptersLoader.last() else chaptersLoader.first()).chapterId + chaptersLoader.loadPrevNextChapter(mangaDetails.get(), currentId, isNext) + updateList() + } + + private suspend fun updateList() { + val snapshot = chaptersLoader.snapshot() + val mangaChapters = mangaDetails.tryGet().getOrNull()?.chapters.orEmpty() + val hasPrevChapter = snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id + val hasNextChapter = snapshot.lastOrNull()?.chapterId != mangaChapters.lastOrNull()?.id + val pages = buildList(snapshot.size + chaptersLoader.chapters.size() + 2) { + if (hasPrevChapter) { + add(LoadingFooter(-1)) + } + var previousChapterId = 0L + for (page in snapshot) { + if (page.chapterId != previousChapterId) { + chaptersLoader.chapters[page.chapterId]?.let { + add(ListHeader(it.name, 0, null)) + } + previousChapterId = page.chapterId + } + this += PageThumbnail( + isCurrent = page.chapterId == initialChapterId && page.index == currentPageIndex, + repository = repository, + page = page, + ) + } + if (hasNextChapter) { + add(LoadingFooter(1)) + } + } + thumbnails.emitValue(pages) + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt index 7d2c6c3bd..3ec91573f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt @@ -1,91 +1,63 @@ package org.koitharu.kotatsu.reader.ui.thumbnails.adapter -import android.graphics.drawable.Drawable +import androidx.lifecycle.LifecycleOwner import coil.ImageLoader -import coil.request.ImageRequest import coil.size.Scale import coil.size.Size import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ItemPageThumbBinding -import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.reader.domain.PageLoader +import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail import org.koitharu.kotatsu.utils.ext.decodeRegion -import org.koitharu.kotatsu.utils.ext.isLowRamDevice -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.utils.ext.disposeImageRequest +import org.koitharu.kotatsu.utils.ext.enqueueWith +import org.koitharu.kotatsu.utils.ext.newImageRequest import org.koitharu.kotatsu.utils.ext.setTextColorAttr +import org.koitharu.kotatsu.utils.ext.source import com.google.android.material.R as materialR fun pageThumbnailAD( coil: ImageLoader, - scope: CoroutineScope, - loader: PageLoader, - clickListener: OnListItemClickListener, -) = adapterDelegateViewBinding( + lifecycleOwner: LifecycleOwner, + clickListener: OnListItemClickListener, +) = adapterDelegateViewBinding( { inflater, parent -> ItemPageThumbBinding.inflate(inflater, parent, false) }, ) { - var job: Job? = null + val gridWidth = itemView.context.resources.getDimensionPixelSize(R.dimen.preferred_grid_width) val thumbSize = Size( width = gridWidth, height = (gridWidth / 13f * 18f).toInt(), ) - suspend fun loadPageThumbnail(item: PageThumbnail): Drawable? = withContext(Dispatchers.Default) { - item.page.preview?.let { url -> - coil.execute( - ImageRequest.Builder(context) - .data(url) - .tag(item.page.source) - .size(thumbSize) - .scale(Scale.FILL) - .allowRgb565(true) - .build(), - ).drawable - }?.let { drawable -> - return@withContext drawable - } - val file = loader.loadPage(item.page, force = false) - coil.execute( - ImageRequest.Builder(context) - .data(file) - .size(thumbSize) - .decodeRegion(0) - .allowRgb565(isLowRamDevice(context)) - .build(), - ).drawable - } - - binding.root.setOnClickListener { - clickListener.onItemClick(item.page, itemView) - } + val clickListenerAdapter = AdapterDelegateClickListenerAdapter(this, clickListener) + binding.root.setOnClickListener(clickListenerAdapter) + binding.root.setOnLongClickListener(clickListenerAdapter) bind { - job?.cancel() - binding.imageViewThumb.setImageDrawable(null) + val data: Any = item.page.preview?.takeUnless { it.isEmpty() } ?: item.page.toMangaPage() + binding.imageViewThumb.newImageRequest(lifecycleOwner, data)?.run { + placeholder(R.drawable.ic_placeholder) + fallback(R.drawable.ic_placeholder) + error(R.drawable.ic_error_placeholder) + size(thumbSize) + scale(Scale.FILL) + allowRgb565(true) + decodeRegion(0) + source(item.page.source) + enqueueWith(coil) + } with(binding.textViewNumber) { setBackgroundResource(if (item.isCurrent) R.drawable.bg_badge_accent else R.drawable.bg_badge_empty) setTextColorAttr(if (item.isCurrent) materialR.attr.colorOnTertiary else android.R.attr.textColorPrimary) text = (item.number).toString() } - job = scope.launch { - val drawable = runCatchingCancellable { - loadPageThumbnail(item) - }.getOrNull() - binding.imageViewThumb.setImageDrawable(drawable) - } } onViewRecycled { - job?.cancel() - job = null - binding.imageViewThumb.setImageDrawable(null) + binding.imageViewThumb.disposeImageRequest() } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt index b293d2865..4fffe12e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt @@ -1,23 +1,60 @@ package org.koitharu.kotatsu.reader.ui.thumbnails.adapter +import androidx.lifecycle.LifecycleOwner +import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader -import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter -import kotlinx.coroutines.CoroutineScope +import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.reader.domain.PageLoader +import org.koitharu.kotatsu.list.ui.adapter.listHeaderAD +import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD +import org.koitharu.kotatsu.list.ui.model.ListHeader +import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail class PageThumbnailAdapter( - dataSet: List, coil: ImageLoader, - scope: CoroutineScope, - loader: PageLoader, - clickListener: OnListItemClickListener -) : ListDelegationAdapter>() { + lifecycleOwner: LifecycleOwner, + clickListener: OnListItemClickListener, +) : AsyncListDifferDelegationAdapter(DiffCallback()) { init { - delegatesManager.addDelegate(pageThumbnailAD(coil, scope, loader, clickListener)) - setItems(dataSet) + delegatesManager.addDelegate(ITEM_TYPE_THUMBNAIL, pageThumbnailAD(coil, lifecycleOwner, clickListener)) + .addDelegate(ITEM_TYPE_HEADER, listHeaderAD(null)) + .addDelegate(ITEM_LOADING, loadingFooterAD()) } -} \ No newline at end of file + + private class DiffCallback : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel): Boolean { + return when { + oldItem is PageThumbnail && newItem is PageThumbnail -> { + oldItem.page == newItem.page + } + + oldItem is ListHeader && newItem is ListHeader -> { + oldItem.textRes == newItem.textRes && + oldItem.text == newItem.text && + oldItem.dateTimeAgo == newItem.dateTimeAgo + } + + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + + else -> oldItem.javaClass == newItem.javaClass + } + } + + override fun areContentsTheSame(oldItem: ListModel, newItem: ListModel): Boolean { + return oldItem == newItem + } + } + + companion object { + + const val ITEM_TYPE_THUMBNAIL = 0 + const val ITEM_TYPE_HEADER = 1 + const val ITEM_LOADING = 2 + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt new file mode 100644 index 000000000..bc27e4a01 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt @@ -0,0 +1,41 @@ +package org.koitharu.kotatsu.reader.ui.thumbnails.adapter + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter +import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail + +class TargetScrollObserver( + private val recyclerView: RecyclerView, +) : RecyclerView.AdapterDataObserver() { + + private var isScrollToCurrentPending = true + + private val layoutManager: LinearLayoutManager + get() = recyclerView.layoutManager as LinearLayoutManager + + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + if (isScrollToCurrentPending) { + postScroll() + } + } + + private fun postScroll() { + recyclerView.post { + scrollToTarget() + } + } + + private fun scrollToTarget() { + val adapter = recyclerView.adapter ?: return + if (recyclerView.computeVerticalScrollRange() == 0) { + return + } + val snapshot = (adapter as? AsyncListDifferDelegationAdapter<*>)?.items ?: return + val target = snapshot.indexOfFirst { it is PageThumbnail && it.isCurrent } + if (target in snapshot.indices) { + layoutManager.scrollToPositionWithOffset(target, 0) + isScrollToCurrentPending = false + } + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index 0f2f18880..6601551db 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -85,7 +85,7 @@ class RemoteListViewModel @Inject constructor( list.toUi(this, mode, tagHighlighter) when { error != null -> add(error.toErrorFooter()) - hasNext -> add(LoadingFooter) + hasNext -> add(LoadingFooter()) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt index de9c2898c..495a68883 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt @@ -58,7 +58,7 @@ class ScrobblingSelectorViewModel @Inject constructor( ) { list, error, isHasNextPage -> if (list.isNotEmpty()) { if (isHasNextPage) { - list + LoadingFooter + list + LoadingFooter() } else { list } @@ -66,7 +66,7 @@ class ScrobblingSelectorViewModel @Inject constructor( listOf( when { error != null -> errorHint(error) - isHasNextPage -> LoadingFooter + isHasNextPage -> LoadingFooter() else -> emptyResultsHint() }, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt index e3d7af6c6..9ed58c8e4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt @@ -9,6 +9,7 @@ import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.ui.selector.model.ScrobblerHint import kotlin.jvm.internal.Intrinsics @@ -34,6 +35,7 @@ class ScrobblerSelectorAdapter( oldItem === newItem -> true oldItem is ScrobblerManga && newItem is ScrobblerManga -> oldItem.id == newItem.id oldItem is ScrobblerHint && newItem is ScrobblerHint -> oldItem.textPrimary == newItem.textPrimary + oldItem is LoadingFooter && newItem is LoadingFooter -> oldItem.key == newItem.key else -> false } } diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index 8ce2d3d90..f6e1571f7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -65,7 +65,7 @@ class SearchViewModel @Inject constructor( list.toUi(result, mode, tagHighlighter) when { error != null -> result += error.toErrorFooter() - hasNext -> result += LoadingFooter + hasNext -> result += LoadingFooter() } result } diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index 72e6f777d..83c99f126 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -72,7 +72,7 @@ class MultiSearchViewModel @Inject constructor( }, ) - loading -> list + LoadingFooter + loading -> list + LoadingFooter() else -> list } }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt index 179957661..05ff6f427 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt @@ -14,6 +14,7 @@ import org.koitharu.kotatsu.list.ui.adapter.errorStateListAD import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.search.ui.multi.MultiSearchListModel import kotlin.jvm.internal.Intrinsics @@ -54,6 +55,10 @@ class MultiSearchAdapter( oldItem.source == newItem.source } + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + else -> oldItem.javaClass == newItem.javaClass } } diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt index e96a9735f..0043cd052 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt @@ -16,6 +16,7 @@ import org.koitharu.kotatsu.list.ui.adapter.errorStateListAD import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel import kotlin.jvm.internal.Intrinsics @@ -62,6 +63,10 @@ class ShelfAdapter( oldItem.key == newItem.key } + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + else -> oldItem.javaClass == newItem.javaClass } } diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt index b35158c6e..a0ddea045 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt @@ -13,6 +13,7 @@ import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.adapter.relatedDateItemAD import org.koitharu.kotatsu.list.ui.model.ListModel +import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem import kotlin.jvm.internal.Intrinsics @@ -44,6 +45,10 @@ class FeedAdapter( oldItem == newItem } + oldItem is LoadingFooter && newItem is LoadingFooter -> { + oldItem.key == newItem.key + } + else -> oldItem.javaClass == newItem.javaClass } diff --git a/app/src/main/res/menu/popup_read.xml b/app/src/main/res/menu/popup_read.xml index 7feb8133b..256f2ef54 100644 --- a/app/src/main/res/menu/popup_read.xml +++ b/app/src/main/res/menu/popup_read.xml @@ -6,4 +6,10 @@ android:id="@+id/action_incognito" android:icon="@drawable/ic_incognito" android:title="@string/incognito_mode" /> + + + From 96c89a716eddcdf882bbaddd05c854ef92484607 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Fri, 19 May 2023 14:19:02 +0300 Subject: [PATCH 02/90] Refactoring --- app/build.gradle | 2 +- app/proguard-rules.pro | 2 +- .../kotatsu/tracker/domain/TrackerTest.kt | 4 +- .../LoggingAdapterDataObserver.kt | 2 +- .../org/koitharu/kotatsu/util/ext/DebugExt.kt | 3 + .../koitharu/kotatsu/utils/ext/DebugExt.kt | 3 - .../java/org/koitharu/kotatsu/KotatsuApp.kt | 4 +- .../koitharu/kotatsu/base/ui/BaseService.kt | 5 - .../bookmarks/domain/BookmarksRepository.kt | 6 +- .../kotatsu/bookmarks/ui/BookmarksActivity.kt | 10 +- .../kotatsu/bookmarks/ui/BookmarksFragment.kt | 34 +++--- .../ui/BookmarksSelectionDecoration.kt | 5 +- .../bookmarks/ui/BookmarksViewModel.kt | 8 +- .../bookmarks/ui/adapter/BookmarkListAD.kt | 16 +-- .../bookmarks/ui/adapter/BookmarksAdapter.kt | 6 +- .../bookmarks/ui/adapter/BookmarksGroupAD.kt | 18 ++-- .../ui/adapter/BookmarksGroupAdapter.kt | 4 +- .../kotatsu/browser/BrowserActivity.kt | 34 +++--- .../browser/cloudflare/CloudFlareDialog.kt | 25 ++--- .../org/koitharu/kotatsu/core/AppModule.kt | 14 +-- .../kotatsu/core/backup/BackupRepository.kt | 2 +- .../kotatsu/core/backup/BackupZipOutput.kt | 7 +- .../koitharu/kotatsu/core/db/MangaDatabase.kt | 2 +- .../kotatsu/core/db/entity/EntityMapping.kt | 2 +- .../exceptions/resolve/DialogErrorObserver.kt | 4 +- .../core/exceptions/resolve/ErrorObserver.kt | 4 +- .../exceptions/resolve/ExceptionResolver.kt | 6 +- .../resolve/SnackbarErrorObserver.kt | 4 +- .../core/github/AppUpdateRepository.kt | 6 +- .../koitharu/kotatsu/core/logs/FileLogger.kt | 8 +- .../org/koitharu/kotatsu/core/model/Manga.kt | 2 +- .../core/model/parcelable/Parcelable.kt | 4 +- .../model/parcelable/ParcelableMangaTags.kt | 6 +- .../core/network/CommonHeadersInterceptor.kt | 2 +- .../kotatsu/core/network/DoHManager.kt | 10 +- .../kotatsu/core/network/SSLBypass.kt | 2 +- .../network/cookies/PreferencesCookieJar.kt | 2 +- .../koitharu/kotatsu/core/os/NetworkState.kt | 4 +- .../kotatsu/core/os/ShortcutsUpdater.kt | 10 +- .../{utils => core/os}/VoiceInputContract.kt | 2 +- .../parser}/MangaDataRepository.kt | 7 +- .../domain => core/parser}/MangaIntent.kt | 8 +- .../core/parser/MangaLoaderContextImpl.kt | 2 +- .../core/parser/RemoteMangaRepository.kt | 4 +- .../kotatsu/core/prefs/AppSettings.kt | 12 +-- .../kotatsu/core/prefs/SourceSettings.kt | 6 +- .../{base => core}/ui/AlertDialogFragment.kt | 27 +++-- .../kotatsu/{base => core}/ui/BaseActivity.kt | 16 +-- .../{base => core}/ui/BaseBottomSheet.kt | 28 +++-- .../kotatsu/{base => core}/ui/BaseFragment.kt | 30 ++++-- .../ui/BaseFullscreenActivity.kt | 4 +- .../ui/BasePreferenceFragment.kt | 7 +- .../koitharu/kotatsu/core/ui/BaseService.kt | 5 + .../{base => core}/ui/BaseViewModel.kt | 8 +- .../ui/CoroutineIntentService.kt | 4 +- .../ui/DefaultActivityLifecycleCallbacks.kt | 2 +- .../ui/dialog/AppBottomSheetDialog.kt | 4 +- .../ui/dialog/CheckBoxAlertDialog.kt | 4 +- .../ui/{ => dialog}/ErrorDetailsDialog.kt | 19 ++-- .../ui/dialog/RecyclerViewAlertDialog.kt | 2 +- .../dialog/RememberSelectionDialogListener.kt | 4 +- .../ui/dialog/StorageSelectDialog.kt | 4 +- .../ui/dialog/TwoButtonsAlertDialog.kt | 2 +- .../ui}/image/CoilImageGetter.kt | 2 +- .../ui}/image/CoverSizeResolver.kt | 8 +- .../ui}/image/FaviconFallbackDrawable.kt | 9 +- .../ui}/image/RegionBitmapDecoder.kt | 8 +- .../ui}/image/TrimTransformation.kt | 10 +- .../AdapterDelegateClickListenerAdapter.kt | 2 +- .../ui/list/BoundsScrollListener.kt | 2 +- .../ui/list/FitHeightGridLayoutManager.kt | 4 +- .../ui/list/FitHeightLinearLayoutManager.kt | 4 +- .../ui/list/ListSelectionController.kt | 6 +- .../ui/list/NestedScrollStateHandle.kt | 2 +- .../ui/list/OnListItemClickListener.kt | 2 +- .../ui/list/OnTipCloseListener.kt | 2 +- .../ui/list/PaginationScrollListener.kt | 4 +- .../ScrollListenerInvalidationObserver.kt | 2 +- .../ui/list/SectionedSelectionController.kt | 4 +- .../decor/AbstractDividerItemDecoration.kt | 6 +- .../decor/AbstractSelectionItemDecoration.kt | 6 +- .../ui/list/decor/SpacingItemDecoration.kt | 2 +- .../list/decor/TypedSpacingItemDecoration.kt | 6 +- .../ui/list/fastscroll/BubbleAnimator.kt | 6 +- .../list/fastscroll/FastScrollRecyclerView.kt | 4 +- .../ui/list/fastscroll/FastScroller.kt | 13 ++- .../ui/list/fastscroll/ScrollbarAnimator.kt | 4 +- .../core/ui/{ => model}/DateTimeAgo.kt | 10 +- .../kotatsu/core/ui/{ => model}/SortOrder.kt | 4 +- .../ui/util/ActionModeDelegate.kt | 2 +- .../ui/util/ActionModeListener.kt | 4 +- .../ui/util/ActivityRecreationHandle.kt | 4 +- .../ui/util/BaseActivityEntryPoint.kt | 2 +- .../ui/util/CollapseActionViewCallback.kt | 2 +- .../ui/util/CountedBooleanLiveData.kt | 4 +- .../ui/util/DefaultTextWatcher.kt | 2 +- .../ui/util/RecyclerViewOwner.kt | 4 +- .../ui/util/ReversibleAction.kt | 5 +- .../ui/util/ReversibleActionObserver.kt | 3 +- .../ui/util}/ReversibleHandle.kt | 8 +- .../ui/util/ShrinkOnScrollBehavior.kt | 2 +- .../ui/util/SpanSizeResolver.kt | 2 +- .../ui/util/StatusBarDimHelper.kt | 6 +- .../ui/util/WindowInsetsDelegate.kt | 2 +- .../ui/widgets/BottomSheetHeaderBar.kt | 8 +- .../ui/widgets/CheckableImageView.kt | 4 +- .../{base => core}/ui/widgets/ChipsView.kt | 8 +- .../ui/widgets/CoverImageView.kt | 4 +- .../HideBottomNavigationOnScrollBehavior.kt | 6 +- .../ui/widgets/ListItemTextView.kt | 4 +- .../ui/widgets/SegmentedBarView.kt | 14 ++- .../ui/widgets/SelectableTextView.kt | 4 +- .../{base => core}/ui/widgets/ShapeView.kt | 2 +- .../ui/widgets/SlidingBottomNavigationView.kt | 8 +- .../ui/widgets/TwoLinesItemView.kt | 4 +- .../ui/widgets/WindowInsetHolder.kt | 2 +- .../util}/AlphanumComparator.kt | 4 +- .../{utils => core/util}/BufferedObserver.kt | 4 +- .../{utils => core/util}/CancellableSource.kt | 2 +- .../{utils => core/util}/CompositeMutex.kt | 2 +- .../{utils => core/util}/EditTextValidator.kt | 6 +- .../kotatsu/{utils => core/util}/FileSize.kt | 8 +- .../{utils => core/util}/FlowLiveData.kt | 2 +- .../util}/GoneOnInvisibleListener.kt | 2 +- .../{utils => core/util}/GridTouchHelper.kt | 3 +- .../{utils => core/util}/IdlingDetector.kt | 2 +- .../util}/IncognitoModeIndicator.kt | 6 +- .../{utils => core/util}/MediatorStateFlow.kt | 2 +- .../util}/RecyclerViewScrollCallback.kt | 4 +- .../util}/RetainedLifecycleCoroutineScope.kt | 2 +- .../util}/ScreenOrientationHelper.kt | 8 +- .../{utils => core/util}/ShareHelper.kt | 2 +- .../{utils => core/util}/SingleLiveEvent.kt | 2 +- .../util}/TaggedActivityResult.kt | 4 +- .../kotatsu/{utils => core/util}/Throttler.kt | 2 +- .../kotatsu/{utils => core/util}/ViewBadge.kt | 2 +- .../{utils => core/util}/WorkManagerHelper.kt | 2 +- .../util}/WorkServiceStopHelper.kt | 4 +- .../util/ext/Android.kt} | 8 +- .../{utils => core/util}/ext/Bundle.kt | 2 +- .../ext/CoilExt.kt => core/util/ext/Coil.kt} | 7 +- .../util/ext/Collections.kt} | 3 +- .../util/ext/Coroutines.kt} | 2 +- .../CursorExt.kt => core/util/ext/Cursor.kt} | 4 +- .../ext/DateExt.kt => core/util/ext/Date.kt} | 6 +- .../util/ext/Display.kt} | 2 +- .../ext/FileExt.kt => core/util/ext/File.kt} | 2 +- .../ext/FlowExt.kt => core/util/ext/Flow.kt} | 2 +- .../util/ext/Fragment.kt} | 2 +- .../util/ext/Graphics.kt} | 4 +- .../ext/HttpExt.kt => core/util/ext/Http.kt} | 2 +- .../kotatsu/{utils => core/util}/ext/IO.kt | 6 +- .../InsetsExt.kt => core/util/ext/Insets.kt} | 2 +- .../util/ext/LiveData.kt} | 4 +- .../util/ext/LocaleList.kt} | 6 +- .../{utils => core/util}/ext/Network.kt | 2 +- .../OtherExt.kt => core/util/ext/Other.kt} | 2 +- .../util/ext/Preferences.kt} | 4 +- .../util/ext/Primitive.kt} | 2 +- .../kotatsu/core/util/ext/RecyclerView.kt | 81 ++++++++++++++ .../util/ext/Resources.kt} | 2 +- .../StringExt.kt => core/util/ext/String.kt} | 3 +- .../util/ext/TextView.kt} | 2 +- .../ThemeExt.kt => core/util/ext/Theme.kt} | 2 +- .../util/ext/Throwable.kt} | 15 +-- .../ext/ViewExt.kt => core/util/ext/View.kt} | 66 +----------- .../{utils => core/util}/ext/ViewModel.kt | 2 +- .../progress/ImageRequestIndicatorListener.kt | 2 +- .../progress/IntPercentLabelFormatter.kt | 2 +- .../util}/progress/PausingProgressJob.kt | 2 +- .../util}/progress/ProgressDeferred.kt | 4 +- .../util}/progress/ProgressJob.kt | 4 +- .../util}/progress/ProgressResponseBody.kt | 2 +- .../util}/progress/TimeLeftEstimator.kt | 2 +- .../details/service/MangaPrefetchService.kt | 8 +- .../details/ui/ChaptersBottomSheetMediator.kt | 4 +- .../kotatsu/details/ui/ChaptersFragment.kt | 29 ++--- .../kotatsu/details/ui/DetailsActivity.kt | 78 +++++++------- .../kotatsu/details/ui/DetailsFragment.kt | 76 ++++++------- .../kotatsu/details/ui/DetailsMenuProvider.kt | 2 +- .../kotatsu/details/ui/DetailsViewModel.kt | 14 +-- .../details/ui/MangaDetailsDelegate.kt | 8 +- .../kotatsu/details/ui/adapter/BranchAD.kt | 6 +- .../details/ui/adapter/BranchesAdapter.kt | 2 +- .../details/ui/adapter/ChapterListItemAD.kt | 12 ++- .../details/ui/adapter/ChaptersAdapter.kt | 4 +- .../ui/adapter/ChaptersSelectionDecoration.kt | 4 +- .../details/ui/scrobbling/ScrobblingInfoAD.kt | 6 +- .../scrobbling/ScrobblingInfoBottomSheet.kt | 41 +++---- .../download/ui/list/DownloadItemAD.kt | 10 +- .../download/ui/list/DownloadItemListener.kt | 2 +- .../download/ui/list/DownloadsActivity.kt | 18 ++-- .../download/ui/list/DownloadsAdapter.kt | 2 +- .../ui/list/DownloadsSelectionDecoration.kt | 6 +- .../download/ui/list/DownloadsViewModel.kt | 14 +-- .../ui/worker/DownloadNotificationFactory.kt | 4 +- .../ui/worker/DownloadStartedObserver.kt | 2 +- .../download/ui/worker/DownloadWorker.kt | 20 ++-- .../download/ui/worker/PausingReceiver.kt | 2 +- .../explore/domain/ExploreRepository.kt | 8 +- .../kotatsu/explore/ui/ExploreFragment.kt | 28 ++--- .../kotatsu/explore/ui/ExploreViewModel.kt | 10 +- .../explore/ui/adapter/ExploreAdapter.kt | 2 +- .../ui/adapter/ExploreAdapterDelegates.kt | 16 +-- .../favourites/domain/FavouritesRepository.kt | 4 +- .../favourites/ui/FavouritesActivity.kt | 5 +- .../categories/CategoriesSelectionCallback.kt | 6 +- .../CategoriesSelectionDecoration.kt | 10 +- .../categories/FavouriteCategoriesActivity.kt | 38 +++---- .../FavouriteCategoriesListListener.kt | 4 +- .../FavouritesCategoriesViewModel.kt | 8 +- .../ui/categories/adapter/CategoryAD.kt | 10 +- .../edit/FavouritesCategoryEditActivity.kt | 62 +++++------ .../edit/FavouritesCategoryEditViewModel.kt | 6 +- .../select/FavouriteCategoriesBottomSheet.kt | 14 +-- .../select/MangaCategoriesViewModel.kt | 4 +- .../select/adapter/MangaCategoriesAdapter.kt | 4 +- .../select/adapter/MangaCategoryAD.kt | 6 +- .../ui/list/FavouritesListFragment.kt | 15 +-- .../ui/list/FavouritesListMenuProvider.kt | 2 +- .../ui/list/FavouritesListViewModel.kt | 4 +- .../history/domain/HistoryRepository.kt | 4 +- .../kotatsu/history/ui/HistoryActivity.kt | 7 +- .../kotatsu/history/ui/HistoryListAdapter.kt | 4 +- .../kotatsu/history/ui/HistoryListFragment.kt | 13 +-- .../history/ui/HistoryListViewModel.kt | 12 +-- .../ui/util/ReadingProgressDrawable.kt | 9 +- .../history/ui/util/ReadingProgressView.kt | 2 +- .../kotatsu/image/ui/ImageActivity.kt | 14 +-- .../kotatsu/list/ui/ListModeBottomSheet.kt | 19 ++-- .../kotatsu/list/ui/MangaListFragment.kt | 70 ++++++------ .../kotatsu/list/ui/MangaListViewModel.kt | 8 +- .../list/ui/MangaSelectionDecoration.kt | 6 +- .../kotatsu/list/ui/adapter/EmptyHintAD.kt | 8 +- .../list/ui/adapter/EmptyStateListAD.kt | 8 +- .../kotatsu/list/ui/adapter/ErrorFooterAD.kt | 6 +- .../list/ui/adapter/ErrorStateListAD.kt | 6 +- .../kotatsu/list/ui/adapter/ListHeader2AD.kt | 6 +- .../kotatsu/list/ui/adapter/ListHeaderAD.kt | 2 +- .../ui/adapter/MangaDetailsClickListener.kt | 2 +- .../list/ui/adapter/MangaGridItemAD.kt | 12 +-- .../list/ui/adapter/MangaListAdapter.kt | 2 +- .../ui/adapter/MangaListDetailedItemAD.kt | 14 +-- .../list/ui/adapter/MangaListItemAD.kt | 12 +-- .../list/ui/adapter/RelatedDateItemAD.kt | 4 +- .../list/ui/filter/FilterAdapterDelegates.kt | 10 +- .../list/ui/filter/FilterBottomSheet.kt | 19 ++-- .../list/ui/filter/FilterCoordinator.kt | 12 +-- .../kotatsu/list/ui/model/ListHeader.kt | 6 +- .../kotatsu/list/ui/model/ListHeader2.kt | 7 +- .../list/ui/model/ListModelConversionExt.kt | 4 +- .../list/ui/model/MangaListDetailedModel.kt | 2 +- .../kotatsu/local/data/LocalStorageManager.kt | 4 +- .../koitharu/kotatsu/local/data/MangaIndex.kt | 3 +- .../koitharu/kotatsu/local/data/PagesCache.kt | 16 +-- .../data/importer/SingleMangaImporter.kt | 4 +- .../local/data/input/LocalMangaDirInput.kt | 13 ++- .../local/data/input/LocalMangaZipInput.kt | 36 +++---- .../local/data/output/LocalMangaDirOutput.kt | 4 +- .../local/data/output/LocalMangaZipOutput.kt | 4 +- .../local/domain/LocalMangaRepository.kt | 11 +- .../kotatsu/local/ui/ImportDialogFragment.kt | 8 +- .../koitharu/kotatsu/local/ui/ImportWorker.kt | 6 +- .../local/ui/LocalChaptersRemoveService.kt | 6 +- .../kotatsu/local/ui/LocalListFragment.kt | 17 +-- .../kotatsu/local/ui/LocalListViewModel.kt | 8 +- .../main/ui/MainActionButtonBehavior.kt | 4 +- .../koitharu/kotatsu/main/ui/MainActivity.kt | 83 +++++++------- .../kotatsu/main/ui/MainNavigationDelegate.kt | 6 +- .../koitharu/kotatsu/main/ui/MainViewModel.kt | 6 +- .../kotatsu/main/ui/owners/BottomNavOwner.kt | 2 +- .../main/ui/owners/NoModalBottomSheetOwner.kt | 2 +- .../main/ui/protect/AppProtectHelper.kt | 5 +- .../main/ui/protect/ProtectActivity.kt | 32 +++--- .../main/ui/protect/ProtectViewModel.kt | 6 +- .../kotatsu/reader/domain/PageLoader.kt | 8 +- .../kotatsu/reader/ui/ChaptersBottomSheet.kt | 16 +-- .../kotatsu/reader/ui/PageSaveHelper.kt | 4 +- .../kotatsu/reader/ui/ReaderActivity.kt | 102 +++++++++--------- .../reader/ui/ReaderControlDelegate.kt | 2 +- .../kotatsu/reader/ui/ReaderInfoBarView.kt | 8 +- .../kotatsu/reader/ui/ReaderViewModel.kt | 20 ++-- .../colorfilter/ColorFilterConfigActivity.kt | 46 ++++---- .../colorfilter/ColorFilterConfigViewModel.kt | 8 +- .../ui/config/ReaderConfigBottomSheet.kt | 20 ++-- .../reader/ui/pager/BaseReaderAdapter.kt | 2 +- .../reader/ui/pager/BaseReaderFragment.kt | 9 +- .../reader/ui/pager/PageHolderDelegate.kt | 2 +- .../pager/reversed/ReversedReaderFragment.kt | 29 +++-- .../reader/ui/pager/standard/PageHolder.kt | 7 +- .../ui/pager/standard/PagerReaderFragment.kt | 29 +++-- .../reader/ui/pager/webtoon/WebtoonHolder.kt | 6 +- .../ui/pager/webtoon/WebtoonImageView.kt | 2 +- .../ui/pager/webtoon/WebtoonReaderFragment.kt | 27 +++-- .../ui/pager/webtoon/WebtoonRecyclerView.kt | 7 +- .../ui/thumbnails/PagesThumbnailsSheet.kt | 29 +++-- .../ui/thumbnails/PagesThumbnailsViewModel.kt | 4 +- .../ui/thumbnails/adapter/PageThumbnailAD.kt | 16 +-- .../adapter/PageThumbnailAdapter.kt | 2 +- .../remotelist/ui/RemoteListFragment.kt | 11 +- .../remotelist/ui/RemoteListViewModel.kt | 10 +- .../scrobbling/anilist/data/ScoreFormat.kt | 2 +- .../scrobbling/common/domain/Scrobbler.kt | 8 +- .../ui/config/ScrobblerConfigActivity.kt | 30 +++--- .../ui/config/ScrobblerConfigViewModel.kt | 14 +-- .../ui/config/adapter/ScrobblingMangaAD.kt | 10 +- .../config/adapter/ScrobblingMangaAdapter.kt | 2 +- .../selector/ScrobblingSelectorBottomSheet.kt | 36 +++---- .../selector/ScrobblingSelectorViewModel.kt | 16 +-- .../ui/selector/adapter/ScrobblerHintAD.kt | 6 +- .../ScrobblerMangaSelectionDecoration.kt | 2 +- .../adapter/ScrobblerSelectorAdapter.kt | 2 +- .../ui/selector/adapter/ScrobblingMangaAD.kt | 10 +- .../shikimori/data/ShikimoriRepository.kt | 2 +- .../search/domain/MangaSearchRepository.kt | 2 +- .../kotatsu/search/ui/MangaListActivity.kt | 10 +- .../kotatsu/search/ui/SearchActivity.kt | 18 ++-- .../kotatsu/search/ui/SearchFragment.kt | 4 +- .../kotatsu/search/ui/SearchViewModel.kt | 4 +- .../search/ui/multi/MultiSearchActivity.kt | 26 ++--- .../search/ui/multi/MultiSearchViewModel.kt | 12 +-- .../ui/multi/adapter/MultiSearchAdapter.kt | 2 +- .../ui/multi/adapter/SearchResultsAD.kt | 12 +-- .../ui/suggestion/SearchSuggestionFragment.kt | 17 ++- .../SearchSuggestionItemCallback.kt | 6 +- .../suggestion/SearchSuggestionViewModel.kt | 6 +- .../adapter/SearchSuggestionSourceAD.kt | 10 +- .../adapter/SearchSuggestionTagsAD.kt | 4 +- .../adapter/SearchSuggestionsMangaListAD.kt | 12 +-- .../suggestion/model/SearchSuggestionItem.kt | 15 +-- .../search/ui/widget/SearchEditText.kt | 4 +- .../settings/AppearanceSettingsFragment.kt | 12 +-- .../settings/ContentSettingsFragment.kt | 12 +-- .../kotatsu/settings/DomainValidator.kt | 2 +- .../settings/HistorySettingsFragment.kt | 10 +- .../NotificationSettingsLegacyFragment.kt | 3 +- .../settings/ReaderSettingsFragment.kt | 4 +- .../kotatsu/settings/RootSettingsFragment.kt | 4 +- .../settings/ServicesSettingsFragment.kt | 8 +- .../kotatsu/settings/SettingsActivity.kt | 18 ++-- .../settings/SourceSettingsFragment.kt | 16 +-- .../settings/SuggestionsSettingsFragment.kt | 4 +- .../kotatsu/settings/SyncSettingsFragment.kt | 2 +- .../settings/about/AboutSettingsFragment.kt | 4 +- .../settings/about/AboutSettingsViewModel.kt | 6 +- .../kotatsu/settings/about/AppUpdateDialog.kt | 2 +- .../settings/backup/BackupDialogFragment.kt | 13 ++- .../settings/backup/BackupSettingsFragment.kt | 12 ++- .../settings/backup/BackupViewModel.kt | 4 +- .../settings/backup/RestoreDialogFragment.kt | 15 ++- .../settings/backup/RestoreViewModel.kt | 6 +- .../newsources/NewSourcesDialogFragment.kt | 9 +- .../newsources/NewSourcesViewModel.kt | 6 +- .../settings/onboard/OnboardDialogFragment.kt | 13 ++- .../settings/onboard/OnboardViewModel.kt | 6 +- .../onboard/adapter/SourceLocaleAD.kt | 4 +- .../settings/protect/ProtectSetupActivity.kt | 44 ++++---- .../settings/protect/ProtectSetupViewModel.kt | 6 +- .../settings/sources/SourcesListFragment.kt | 31 +++--- .../settings/sources/SourcesListViewModel.kt | 15 ++- .../adapter/SourceConfigAdapterDelegates.kt | 16 +-- .../sources/adapter/SourceConfigListener.kt | 2 +- .../sources/auth/SourceAuthActivity.kt | 36 +++---- .../kotatsu/settings/tools/ToolsFragment.kt | 18 ++-- .../kotatsu/settings/tools/ToolsViewModel.kt | 2 +- .../settings/tools/views/MemoryUsageView.kt | 6 +- .../tracker/TrackerSettingsFragment.kt | 9 +- .../tracker/TrackerSettingsViewModel.kt | 4 +- .../TrackerCategoriesConfigAdapter.kt | 2 +- .../TrackerCategoriesConfigSheet.kt | 10 +- .../TrackerCategoriesConfigViewModel.kt | 6 +- .../tracker/categories/TrackerCategoryAD.kt | 4 +- .../settings/utils/ActivityListPreference.kt | 2 +- .../settings/utils/EditTextBindListener.kt | 4 +- .../settings/utils/RingtonePickContract.kt | 2 +- .../settings/utils/SliderPreference.kt | 2 +- .../kotatsu/shelf/domain/ShelfRepository.kt | 2 +- .../kotatsu/shelf/ui/ShelfFragment.kt | 24 ++--- .../kotatsu/shelf/ui/ShelfMenuProvider.kt | 4 +- .../shelf/ui/ShelfSelectionCallback.kt | 8 +- .../kotatsu/shelf/ui/ShelfViewModel.kt | 8 +- .../kotatsu/shelf/ui/adapter/ShelfAdapter.kt | 6 +- .../kotatsu/shelf/ui/adapter/ShelfGroupAD.kt | 14 +-- .../shelf/ui/config/ShelfSettingsActivity.kt | 12 +-- .../config/ShelfSettingsAdapterDelegates.kt | 2 +- .../shelf/ui/config/ShelfSettingsViewModel.kt | 6 +- .../ui/config/size/ShelfSizeBottomSheet.kt | 18 ++-- .../domain/SuggestionRepository.kt | 2 +- .../suggestions/domain/TagsBlacklist.kt | 2 +- .../suggestions/ui/SuggestionsActivity.kt | 7 +- .../suggestions/ui/SuggestionsFragment.kt | 14 +-- .../suggestions/ui/SuggestionsViewModel.kt | 4 +- .../suggestions/ui/SuggestionsWorker.kt | 24 ++--- .../koitharu/kotatsu/sync/data/SyncAuthApi.kt | 2 +- .../kotatsu/sync/data/SyncSettings.kt | 2 +- .../kotatsu/sync/domain/SyncController.kt | 2 +- .../kotatsu/sync/domain/SyncHelper.kt | 8 +- .../kotatsu/sync/ui/SyncAuthActivity.kt | 48 ++++----- .../kotatsu/sync/ui/SyncAuthViewModel.kt | 6 +- .../kotatsu/sync/ui/SyncHostDialogFragment.kt | 20 ++-- .../ui/favourites/FavouritesSyncAdapter.kt | 4 +- .../sync/ui/history/HistorySyncAdapter.kt | 4 +- .../kotatsu/tracker/ui/feed/FeedFragment.kt | 24 ++--- .../tracker/ui/feed/FeedMenuProvider.kt | 2 +- .../kotatsu/tracker/ui/feed/FeedViewModel.kt | 10 +- .../tracker/ui/feed/adapter/FeedAdapter.kt | 2 +- .../tracker/ui/feed/adapter/FeedItemAD.kt | 12 +-- .../tracker/ui/updates/UpdatesActivity.kt | 6 +- .../tracker/ui/updates/UpdatesViewModel.kt | 4 +- .../kotatsu/tracker/work/TrackWorker.kt | 10 +- .../kotatsu/utils/ext/LayoutManagerExt.kt | 19 ---- .../widget/recent/RecentListFactory.kt | 4 +- .../widget/shelf/ShelfConfigActivity.kt | 20 ++-- .../widget/shelf/ShelfConfigViewModel.kt | 4 +- .../kotatsu/widget/shelf/ShelfListFactory.kt | 4 +- .../shelf/adapter/CategorySelectAdapter.kt | 4 +- .../shelf/adapter/CategorySelectItemAD.kt | 6 +- .../res/layout-w600dp/activity_categories.xml | 2 +- .../main/res/layout-w600dp/activity_main.xml | 2 +- .../res/layout-w600dp/fragment_details.xml | 4 +- .../main/res/layout-w600dp/fragment_tools.xml | 4 +- .../main/res/layout/activity_categories.xml | 2 +- app/src/main/res/layout/activity_details.xml | 4 +- app/src/main/res/layout/activity_main.xml | 4 +- .../main/res/layout/activity_search_multi.xml | 2 +- app/src/main/res/layout/dialog_import.xml | 6 +- app/src/main/res/layout/dialog_list_mode.xml | 2 +- app/src/main/res/layout/fragment_chapters.xml | 2 +- app/src/main/res/layout/fragment_details.xml | 4 +- app/src/main/res/layout/fragment_feed.xml | 4 +- app/src/main/res/layout/fragment_list.xml | 4 +- .../main/res/layout/fragment_list_simple.xml | 2 +- app/src/main/res/layout/fragment_shelf.xml | 2 +- app/src/main/res/layout/fragment_tools.xml | 4 +- app/src/main/res/layout/item_bookmark.xml | 4 +- .../main/res/layout/item_checkable_new.xml | 4 +- app/src/main/res/layout/item_color_scheme.xml | 6 +- app/src/main/res/layout/item_header_2.xml | 2 +- app/src/main/res/layout/item_manga_grid.xml | 2 +- .../res/layout/item_manga_list_details.xml | 2 +- app/src/main/res/layout/item_page_thumb.xml | 2 +- .../item_search_suggestion_manga_grid.xml | 2 +- .../layout/item_search_suggestion_tags.xml | 6 +- app/src/main/res/layout/item_storage.xml | 4 +- .../main/res/layout/layout_memory_usage.xml | 2 +- app/src/main/res/layout/sheet_base.xml | 4 +- app/src/main/res/layout/sheet_chapters.xml | 4 +- .../res/layout/sheet_favorite_categories.xml | 4 +- app/src/main/res/layout/sheet_filter.xml | 2 +- app/src/main/res/layout/sheet_pages.xml | 2 +- .../main/res/layout/sheet_reader_config.xml | 10 +- .../res/layout/sheet_scrobbling_selector.xml | 4 +- .../{utils => util}/CompositeMutexTest.kt | 3 +- 453 files changed, 2009 insertions(+), 1975 deletions(-) rename app/src/debug/java/org/koitharu/kotatsu/{utils => util}/LoggingAdapterDataObserver.kt (97%) create mode 100644 app/src/debug/java/org/koitharu/kotatsu/util/ext/DebugExt.kt delete mode 100644 app/src/debug/java/org/koitharu/kotatsu/utils/ext/DebugExt.kt delete mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/BaseService.kt rename app/src/main/java/org/koitharu/kotatsu/{utils => core/os}/VoiceInputContract.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base/domain => core/parser}/MangaDataRepository.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base/domain => core/parser}/MangaIntent.kt (83%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/AlertDialogFragment.kt (54%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BaseActivity.kt (92%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BaseBottomSheet.kt (73%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BaseFragment.kt (53%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BaseFullscreenActivity.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BasePreferenceFragment.kt (88%) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/BaseViewModel.kt (87%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/CoroutineIntentService.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/DefaultActivityLifecycleCallbacks.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/AppBottomSheetDialog.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/CheckBoxAlertDialog.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/core/ui/{ => dialog}/ErrorDetailsDialog.kt (80%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/RecyclerViewAlertDialog.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/RememberSelectionDialogListener.kt (85%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/StorageSelectDialog.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/dialog/TwoButtonsAlertDialog.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/ui}/image/CoilImageGetter.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/ui}/image/CoverSizeResolver.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/ui}/image/FaviconFallbackDrawable.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/ui}/image/RegionBitmapDecoder.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/ui}/image/TrimTransformation.kt (91%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/AdapterDelegateClickListenerAdapter.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/BoundsScrollListener.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/FitHeightGridLayoutManager.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/FitHeightLinearLayoutManager.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/ListSelectionController.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/NestedScrollStateHandle.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/OnListItemClickListener.kt (79%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/OnTipCloseListener.kt (59%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/PaginationScrollListener.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/ScrollListenerInvalidationObserver.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/SectionedSelectionController.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/decor/AbstractDividerItemDecoration.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/decor/AbstractSelectionItemDecoration.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/decor/SpacingItemDecoration.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/decor/TypedSpacingItemDecoration.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/fastscroll/BubbleAnimator.kt (92%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/fastscroll/FastScrollRecyclerView.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/fastscroll/FastScroller.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/list/fastscroll/ScrollbarAnimator.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/core/ui/{ => model}/DateTimeAgo.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/core/ui/{ => model}/SortOrder.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ActionModeDelegate.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ActionModeListener.kt (78%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ActivityRecreationHandle.kt (86%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/BaseActivityEntryPoint.kt (86%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/CollapseActionViewCallback.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/CountedBooleanLiveData.kt (92%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/DefaultTextWatcher.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/RecyclerViewOwner.kt (72%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ReversibleAction.kt (56%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ReversibleActionObserver.kt (86%) rename app/src/main/java/org/koitharu/kotatsu/{base/domain => core/ui/util}/ReversibleHandle.kt (70%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/ShrinkOnScrollBehavior.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/SpanSizeResolver.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/StatusBarDimHelper.kt (92%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/util/WindowInsetsDelegate.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/BottomSheetHeaderBar.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/CheckableImageView.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/ChipsView.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/CoverImageView.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/HideBottomNavigationOnScrollBehavior.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/ListItemTextView.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/SegmentedBarView.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/SelectableTextView.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/ShapeView.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/SlidingBottomNavigationView.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/TwoLinesItemView.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{base => core}/ui/widgets/WindowInsetHolder.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/AlphanumComparator.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/BufferedObserver.kt (64%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/CancellableSource.kt (90%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/CompositeMutex.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/EditTextValidator.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/FileSize.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/FlowLiveData.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/GoneOnInvisibleListener.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/GridTouchHelper.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/IdlingDetector.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/IncognitoModeIndicator.kt (89%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/MediatorStateFlow.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/RecyclerViewScrollCallback.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/RetainedLifecycleCoroutineScope.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ScreenOrientationHelper.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ShareHelper.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/SingleLiveEvent.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/TaggedActivityResult.kt (63%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/Throttler.kt (88%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ViewBadge.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/WorkManagerHelper.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/WorkServiceStopHelper.kt (91%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/AndroidExt.kt => core/util/ext/Android.kt} (95%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ext/Bundle.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/CoilExt.kt => core/util/ext/Coil.kt} (92%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/CollectionExt.kt => core/util/ext/Collections.kt} (95%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/CoroutineExt.kt => core/util/ext/Coroutines.kt} (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/CursorExt.kt => core/util/ext/Cursor.kt} (92%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/DateExt.kt => core/util/ext/Date.kt} (89%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/DisplayExt.kt => core/util/ext/Display.kt} (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/FileExt.kt => core/util/ext/File.kt} (98%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/FlowExt.kt => core/util/ext/Flow.kt} (96%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/FragmentExt.kt => core/util/ext/Fragment.kt} (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/GraphicsExt.kt => core/util/ext/Graphics.kt} (85%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/HttpExt.kt => core/util/ext/Http.kt} (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ext/IO.kt (80%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/InsetsExt.kt => core/util/ext/Insets.kt} (83%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/LiveDataExt.kt => core/util/ext/LiveData.kt} (88%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/LocaleListExt.kt => core/util/ext/LocaleList.kt} (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ext/Network.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/OtherExt.kt => core/util/ext/Other.kt} (77%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/PreferencesExt.kt => core/util/ext/Preferences.kt} (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/PrimitiveExt.kt => core/util/ext/Primitive.kt} (81%) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/ResourcesExt.kt => core/util/ext/Resources.kt} (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/StringExt.kt => core/util/ext/String.kt} (89%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/TextViewExt.kt => core/util/ext/TextView.kt} (97%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/ThemeExt.kt => core/util/ext/Theme.kt} (96%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/ThrowableExt.kt => core/util/ext/Throwable.kt} (90%) rename app/src/main/java/org/koitharu/kotatsu/{utils/ext/ViewExt.kt => core/util/ext/View.kt} (65%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/ext/ViewModel.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/ImageRequestIndicatorListener.kt (93%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/IntPercentLabelFormatter.kt (88%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/PausingProgressJob.kt (92%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/ProgressDeferred.kt (87%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/ProgressJob.kt (85%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/ProgressResponseBody.kt (96%) rename app/src/main/java/org/koitharu/kotatsu/{utils => core/util}/progress/TimeLeftEstimator.kt (96%) delete mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/ext/LayoutManagerExt.kt rename app/src/test/java/org/koitharu/kotatsu/{utils => util}/CompositeMutexTest.kt (92%) diff --git a/app/build.gradle b/app/build.gradle index aa5621fc1..99d288a1d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,7 +59,7 @@ android { } lint { abortOnError true - disable 'MissingTranslation', 'PrivateResource', 'NotifyDataSetChanged' + disable 'MissingTranslation', 'PrivateResource', 'NotifyDataSetChanged', 'SetJavaScriptEnabled' } testOptions { unitTests.includeAndroidResources true diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 791a045d4..a81d9ac31 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -8,7 +8,7 @@ public static void checkParameterIsNotNull(...); public static void checkNotNullParameter(...); } --keep public class ** extends org.koitharu.kotatsu.base.ui.BaseFragment +-keep public class ** extends org.koitharu.kotatsu.core.ui.BaseFragment -keep class org.koitharu.kotatsu.core.db.entity.* { *; } -dontwarn okhttp3.internal.platform.** -dontwarn org.conscrypt.** diff --git a/app/src/androidTest/java/org/koitharu/kotatsu/tracker/domain/TrackerTest.kt b/app/src/androidTest/java/org/koitharu/kotatsu/tracker/domain/TrackerTest.kt index 37b5ebf02..5e38b4d15 100644 --- a/app/src/androidTest/java/org/koitharu/kotatsu/tracker/domain/TrackerTest.kt +++ b/app/src/androidTest/java/org/koitharu/kotatsu/tracker/domain/TrackerTest.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.tracker.domain import androidx.test.ext.junit.runners.AndroidJUnit4 import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import javax.inject.Inject import junit.framework.TestCase.* import kotlinx.coroutines.test.runTest import org.junit.Before @@ -11,8 +10,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.koitharu.kotatsu.SampleData -import org.koitharu.kotatsu.base.domain.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.parsers.model.Manga +import javax.inject.Inject @HiltAndroidTest @RunWith(AndroidJUnit4::class) diff --git a/app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt b/app/src/debug/java/org/koitharu/kotatsu/util/LoggingAdapterDataObserver.kt similarity index 97% rename from app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt rename to app/src/debug/java/org/koitharu/kotatsu/util/LoggingAdapterDataObserver.kt index e4221be71..07ae3c4bb 100644 --- a/app/src/debug/java/org/koitharu/kotatsu/utils/LoggingAdapterDataObserver.kt +++ b/app/src/debug/java/org/koitharu/kotatsu/util/LoggingAdapterDataObserver.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.util import android.util.Log import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver diff --git a/app/src/debug/java/org/koitharu/kotatsu/util/ext/DebugExt.kt b/app/src/debug/java/org/koitharu/kotatsu/util/ext/DebugExt.kt new file mode 100644 index 000000000..acaab0f0c --- /dev/null +++ b/app/src/debug/java/org/koitharu/kotatsu/util/ext/DebugExt.kt @@ -0,0 +1,3 @@ +package org.koitharu.kotatsu.util.ext + +fun Throwable.printStackTraceDebug() = printStackTrace() diff --git a/app/src/debug/java/org/koitharu/kotatsu/utils/ext/DebugExt.kt b/app/src/debug/java/org/koitharu/kotatsu/utils/ext/DebugExt.kt deleted file mode 100644 index e00bb6a83..000000000 --- a/app/src/debug/java/org/koitharu/kotatsu/utils/ext/DebugExt.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.koitharu.kotatsu.utils.ext - -fun Throwable.printStackTraceDebug() = printStackTrace() \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt index 95d48afa2..b8a5ac19d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt +++ b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt @@ -20,12 +20,12 @@ import org.acra.ktx.initAcra import org.acra.sender.HttpSender import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.WorkServiceStopHelper +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.reader.domain.PageLoader -import org.koitharu.kotatsu.utils.WorkServiceStopHelper -import org.koitharu.kotatsu.utils.ext.processLifecycleScope import javax.inject.Inject @HiltAndroidApp diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseService.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseService.kt deleted file mode 100644 index 05e07729e..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseService.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.koitharu.kotatsu.base.ui - -import androidx.lifecycle.LifecycleService - -abstract class BaseService : LifecycleService() \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt index feeac4519..0c439a6bc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt @@ -5,7 +5,6 @@ import androidx.room.withTransaction import dagger.Reusable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import org.koitharu.kotatsu.base.domain.ReversibleHandle import org.koitharu.kotatsu.bookmarks.data.BookmarkEntity import org.koitharu.kotatsu.bookmarks.data.toBookmark import org.koitharu.kotatsu.bookmarks.data.toBookmarks @@ -14,9 +13,10 @@ import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toManga +import org.koitharu.kotatsu.core.ui.util.ReversibleHandle +import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.mapItems -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt index 1bcc16d2e..5f2f952bd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt @@ -3,16 +3,14 @@ package org.koitharu.kotatsu.bookmarks.ui import android.content.Context import android.content.Intent import android.os.Bundle -import android.view.ViewGroup import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.graphics.Insets -import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.fragment.app.commit import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner @@ -24,10 +22,10 @@ class BookmarksActivity : SnackbarOwner { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override val snackbarHost: CoordinatorLayout - get() = binding.root + get() = viewBinding.root override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -43,7 +41,7 @@ class BookmarksActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt index 06b3dbb36..e76ee3ed0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt @@ -16,19 +16,21 @@ import coil.ImageLoader import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.reverseAsync -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration -import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.bookmarks.data.ids import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksGroupAdapter import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.ui.util.reverseAsync +import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener @@ -37,8 +39,6 @@ import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity -import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import javax.inject.Inject @AndroidEntryPoint @@ -56,12 +56,12 @@ class BookmarksFragment : private var adapter: BookmarksGroupAdapter? = null private var selectionController: SectionedSelectionController? = null - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): FragmentListSimpleBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentListSimpleBinding { return FragmentListSimpleBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListSimpleBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) selectionController = SectionedSelectionController( activity = requireActivity(), owner = this, @@ -77,7 +77,7 @@ class BookmarksFragment : ) binding.recyclerView.adapter = adapter binding.recyclerView.setHasFixedSize(true) - val spacingDecoration = SpacingItemDecoration(view.resources.getDimensionPixelOffset(R.dimen.grid_spacing)) + val spacingDecoration = SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)) binding.recyclerView.addItemDecoration(spacingDecoration) viewModel.content.observe(viewLifecycleOwner, ::onListChanged) @@ -114,7 +114,7 @@ class BookmarksFragment : override fun onFastScrollStop(fastScroller: FastScroller) = Unit override fun onSelectionChanged(controller: SectionedSelectionController, count: Int) { - binding.recyclerView.invalidateNestedItemDecorations() + requireViewBinding().recyclerView.invalidateNestedItemDecorations() } override fun onCreateActionMode( @@ -149,10 +149,10 @@ class BookmarksFragment : ): AbstractSelectionItemDecoration = BookmarksSelectionDecoration(requireContext()) override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, ) - binding.recyclerView.fastScroller.updateLayoutParams { + requireViewBinding().recyclerView.fastScroller.updateLayoutParams { bottomMargin = insets.bottom } } diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt index 025acb882..85886eed8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt @@ -4,8 +4,8 @@ import android.content.Context import android.view.View import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.bookmarks.domain.Bookmark +import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration -import org.koitharu.kotatsu.utils.ext.getItem class BookmarksSelectionDecoration(context: Context) : MangaSelectionDecoration(context) { @@ -14,5 +14,4 @@ class BookmarksSelectionDecoration(context: Context) : MangaSelectionDecoration( val item = holder.getItem(Bookmark::class.java) ?: return RecyclerView.NO_ID return item.pageId } - -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt index ced4e03cc..614691d49 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt @@ -7,17 +7,17 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt index 1ffa3bac3..886aba926 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt @@ -4,16 +4,16 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.bookmarks.domain.Bookmark +import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.decodeRegion +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemBookmarkBinding -import org.koitharu.kotatsu.utils.ext.decodeRegion -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.image.CoverSizeResolver fun bookmarkListAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt index 2f3022b8e..d47bbb785 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt @@ -4,8 +4,8 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.bookmarks.domain.Bookmark +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener class BookmarksAdapter( coil: ImageLoader, @@ -13,7 +13,7 @@ class BookmarksAdapter( clickListener: OnListItemClickListener, ) : AsyncListDifferDelegationAdapter( DiffCallback(), - bookmarkListAD(coil, lifecycleOwner, clickListener) + bookmarkListAD(coil, lifecycleOwner, clickListener), ) { private class DiffCallback : DiffUtil.ItemCallback() { @@ -27,4 +27,4 @@ class BookmarksAdapter( } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt index a4d33d0eb..df737ff54 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt @@ -6,20 +6,20 @@ import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup +import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.util.ext.clearItemDecorations +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemBookmarksGroupBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.clearItemDecorations -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.image.CoverSizeResolver fun bookmarksGroupAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt index a51a00ec2..31ab12fd7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt @@ -5,10 +5,10 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD import org.koitharu.kotatsu.list.ui.adapter.errorStateListAD diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt index 55f4e193b..f84ca4899 100644 --- a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt @@ -12,10 +12,10 @@ import androidx.core.graphics.Insets import androidx.core.view.isVisible import androidx.core.view.updatePadding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.network.CommonHeadersInterceptor +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability import org.koitharu.kotatsu.databinding.ActivityBrowserBinding -import org.koitharu.kotatsu.utils.ext.catchingWebViewUnavailability import com.google.android.material.R as materialR @SuppressLint("SetJavaScriptEnabled") @@ -32,13 +32,13 @@ class BrowserActivity : BaseActivity(), BrowserCallback setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } - with(binding.webView.settings) { + with(viewBinding.webView.settings) { javaScriptEnabled = true userAgentString = CommonHeadersInterceptor.userAgentChrome } - binding.webView.webViewClient = BrowserClient(this) - binding.webView.webChromeClient = ProgressChromeClient(binding.progressBar) - onBackPressedCallback = WebViewBackPressedCallback(binding.webView) + viewBinding.webView.webViewClient = BrowserClient(this) + viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar) + onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView) onBackPressedDispatcher.addCallback(onBackPressedCallback) if (savedInstanceState != null) { return @@ -51,18 +51,18 @@ class BrowserActivity : BaseActivity(), BrowserCallback intent?.getStringExtra(EXTRA_TITLE) ?: getString(R.string.loading_), url, ) - binding.webView.loadUrl(url) + viewBinding.webView.loadUrl(url) } } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - binding.webView.saveState(outState) + viewBinding.webView.saveState(outState) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) - binding.webView.restoreState(savedInstanceState) + viewBinding.webView.restoreState(savedInstanceState) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -73,14 +73,14 @@ class BrowserActivity : BaseActivity(), BrowserCallback override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { android.R.id.home -> { - binding.webView.stopLoading() + viewBinding.webView.stopLoading() finishAfterTransition() true } R.id.action_browser -> { val intent = Intent(Intent.ACTION_VIEW) - intent.data = Uri.parse(binding.webView.url) + intent.data = Uri.parse(viewBinding.webView.url) try { startActivity(Intent.createChooser(intent, item.title)) } catch (_: ActivityNotFoundException) { @@ -92,22 +92,22 @@ class BrowserActivity : BaseActivity(), BrowserCallback } override fun onPause() { - binding.webView.onPause() + viewBinding.webView.onPause() super.onPause() } override fun onResume() { super.onResume() - binding.webView.onResume() + viewBinding.webView.onResume() } override fun onDestroy() { super.onDestroy() - binding.webView.destroy() + viewBinding.webView.destroy() } override fun onLoadingStateChanged(isLoading: Boolean) { - binding.progressBar.isVisible = isLoading + viewBinding.progressBar.isVisible = isLoading } override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) { @@ -120,10 +120,10 @@ class BrowserActivity : BaseActivity(), BrowserCallback } override fun onWindowInsetsChanged(insets: Insets) { - binding.appbar.updatePadding( + viewBinding.appbar.updatePadding( top = insets.top, ) - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, bottom = insets.bottom, diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt b/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt index 34f02003c..0a1284448 100644 --- a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt @@ -1,10 +1,8 @@ package org.koitharu.kotatsu.browser.cloudflare -import android.annotation.SuppressLint import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.webkit.CookieManager import android.webkit.WebSettings @@ -14,13 +12,13 @@ import androidx.fragment.app.setFragmentResult import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import okhttp3.Headers -import org.koitharu.kotatsu.base.ui.AlertDialogFragment import org.koitharu.kotatsu.browser.WebViewBackPressedCallback import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.CommonHeadersInterceptor import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar +import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.FragmentCloudflareBinding -import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @AndroidEntryPoint @@ -39,14 +37,13 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud url = requireArguments().getString(ARG_URL).orEmpty() } - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentCloudflareBinding.inflate(inflater, container, false) - @SuppressLint("SetJavaScriptEnabled") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentCloudflareBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) with(binding.webView.settings) { javaScriptEnabled = true cacheMode = WebSettings.LOAD_DEFAULT @@ -64,8 +61,8 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud } override fun onDestroyView() { - binding.webView.stopLoading() - binding.webView.destroy() + requireViewBinding().webView.stopLoading() + requireViewBinding().webView.destroy() onBackPressedCallback = null super.onDestroyView() } @@ -76,18 +73,18 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud override fun onDialogCreated(dialog: AlertDialog) { super.onDialogCreated(dialog) - onBackPressedCallback = WebViewBackPressedCallback(binding.webView).also { + onBackPressedCallback = WebViewBackPressedCallback(requireViewBinding().webView).also { dialog.onBackPressedDispatcher.addCallback(it) } } override fun onResume() { super.onResume() - binding.webView.onResume() + requireViewBinding().webView.onResume() } override fun onPause() { - binding.webView.onPause() + requireViewBinding().webView.onPause() super.onPause() } @@ -97,7 +94,7 @@ class CloudFlareDialog : AlertDialogFragment(), Cloud } override fun onPageLoaded() { - bindingOrNull()?.progressBar?.isInvisible = true + viewBinding?.progressBar?.isInvisible = true } override fun onCheckPassed() { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt index 1797b4213..6e53e3736 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt @@ -26,7 +26,6 @@ import kotlinx.coroutines.flow.asSharedFlow import okhttp3.CookieJar import okhttp3.OkHttpClient import org.koitharu.kotatsu.BuildConfig -import org.koitharu.kotatsu.base.ui.util.ActivityRecreationHandle import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.cache.MemoryContentCache import org.koitharu.kotatsu.core.cache.StubContentCache @@ -41,6 +40,12 @@ import org.koitharu.kotatsu.core.parser.MangaLoaderContextImpl import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.favicon.FaviconFetcher import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.image.CoilImageGetter +import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle +import org.koitharu.kotatsu.core.util.IncognitoModeIndicator +import org.koitharu.kotatsu.core.util.ext.activityManager +import org.koitharu.kotatsu.core.util.ext.connectivityManager +import org.koitharu.kotatsu.core.util.ext.isLowRamDevice import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.CbzFetcher import org.koitharu.kotatsu.local.data.LocalManga @@ -53,11 +58,6 @@ import org.koitharu.kotatsu.reader.ui.thumbnails.MangaPageFetcher import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider import org.koitharu.kotatsu.settings.backup.BackupObserver import org.koitharu.kotatsu.sync.domain.SyncController -import org.koitharu.kotatsu.utils.IncognitoModeIndicator -import org.koitharu.kotatsu.utils.ext.activityManager -import org.koitharu.kotatsu.utils.ext.connectivityManager -import org.koitharu.kotatsu.utils.ext.isLowRamDevice -import org.koitharu.kotatsu.utils.image.CoilImageGetter import org.koitharu.kotatsu.widget.WidgetUpdater import java.util.concurrent.TimeUnit import javax.inject.Singleton @@ -159,7 +159,7 @@ interface AppModule { .transformationDispatcher(Dispatchers.Default) .diskCache(diskCacheFactory) .logger(if (BuildConfig.DEBUG) DebugLogger() else null) - .allowRgb565(isLowRamDevice(context)) + .allowRgb565(context.isLowRamDevice()) .components( ComponentRegistry.Builder() .add(SvgDecoder.Factory()) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt index 9d80b7af4..f02602cef 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt @@ -7,7 +7,7 @@ import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.parsers.util.json.JSONIterator import org.koitharu.kotatsu.parsers.util.json.mapJSON -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import javax.inject.Inject private const val PAGE_SIZE = 10 diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt b/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt index 8a6217d04..c06f45a76 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt @@ -5,10 +5,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible import okio.Closeable import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.format import org.koitharu.kotatsu.core.zip.ZipOutput -import org.koitharu.kotatsu.utils.ext.format import java.io.File -import java.util.* +import java.util.Date +import java.util.Locale import java.util.zip.Deflater class BackupZipOutput(val file: File) : Closeable { @@ -42,4 +43,4 @@ suspend fun BackupZipOutput(context: Context): BackupZipOutput = runInterruptibl append(".bk.zip") } BackupZipOutput(File(dir, filename)) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt index d390e80dd..5378e420e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt @@ -33,6 +33,7 @@ import org.koitharu.kotatsu.core.db.migrations.Migration6To7 import org.koitharu.kotatsu.core.db.migrations.Migration7To8 import org.koitharu.kotatsu.core.db.migrations.Migration8To9 import org.koitharu.kotatsu.core.db.migrations.Migration9To10 +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.favourites.data.FavouriteCategoriesDao import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity import org.koitharu.kotatsu.favourites.data.FavouriteEntity @@ -46,7 +47,6 @@ import org.koitharu.kotatsu.suggestions.data.SuggestionEntity import org.koitharu.kotatsu.tracker.data.TrackEntity import org.koitharu.kotatsu.tracker.data.TrackLogEntity import org.koitharu.kotatsu.tracker.data.TracksDao -import org.koitharu.kotatsu.utils.ext.processLifecycleScope const val DATABASE_VERSION = 15 diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt index 7bba6f4df..80bcb6045 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt @@ -1,13 +1,13 @@ package org.koitharu.kotatsu.core.db.entity import org.koitharu.kotatsu.core.model.MangaSource +import org.koitharu.kotatsu.core.util.ext.longHashCode import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.toTitleCase -import org.koitharu.kotatsu.utils.ext.longHashCode // Entity to model diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt index c3bc2f893..68949cc36 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt @@ -6,9 +6,9 @@ import androidx.core.util.Consumer import androidx.fragment.app.Fragment import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.ErrorDetailsDialog +import org.koitharu.kotatsu.core.ui.dialog.ErrorDetailsDialog +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.parsers.exception.ParseException -import org.koitharu.kotatsu.utils.ext.getDisplayMessage class DialogErrorObserver( host: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt index e41b65955..3af75685e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt @@ -11,8 +11,8 @@ import androidx.lifecycle.Observer import androidx.lifecycle.coroutineScope import kotlinx.coroutines.isActive import kotlinx.coroutines.launch -import org.koitharu.kotatsu.utils.ext.findActivity -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope +import org.koitharu.kotatsu.core.util.ext.findActivity +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope abstract class ErrorObserver( protected val host: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt index 75d466bbb..b5e267dcb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt @@ -12,13 +12,13 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.BrowserActivity import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException -import org.koitharu.kotatsu.core.ui.ErrorDetailsDialog +import org.koitharu.kotatsu.core.ui.dialog.ErrorDetailsDialog +import org.koitharu.kotatsu.core.util.TaggedActivityResult +import org.koitharu.kotatsu.core.util.isSuccess import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity -import org.koitharu.kotatsu.utils.TaggedActivityResult -import org.koitharu.kotatsu.utils.isSuccess import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt index fb3cea7d9..9a1ef14d5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt @@ -5,10 +5,10 @@ import androidx.core.util.Consumer import androidx.fragment.app.Fragment import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.ErrorDetailsDialog +import org.koitharu.kotatsu.core.ui.dialog.ErrorDetailsDialog +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner import org.koitharu.kotatsu.parsers.exception.ParseException -import org.koitharu.kotatsu.utils.ext.getDisplayMessage class SnackbarErrorObserver( host: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt index 70598cb0a..53a53d273 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt @@ -14,13 +14,13 @@ import org.json.JSONArray import org.json.JSONObject import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.byte2HexFormatted import org.koitharu.kotatsu.parsers.util.json.mapJSONNotNull import org.koitharu.kotatsu.parsers.util.parseJsonArray -import org.koitharu.kotatsu.utils.ext.asArrayList -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.ByteArrayInputStream import java.io.InputStream import java.security.MessageDigest diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt b/app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt index 8c46d4c01..d63c2e3bb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt @@ -14,10 +14,10 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.processLifecycleScope -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.subdir +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.core.util.ext.subdir +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import java.io.FileOutputStream import java.text.SimpleDateFormat diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt index 47ac983f3..4ed4c7885 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt @@ -1,11 +1,11 @@ package org.koitharu.kotatsu.core.model import androidx.core.os.LocaleListCompat +import org.koitharu.kotatsu.core.util.ext.iterator import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.utils.ext.iterator fun Collection.ids() = mapToSet { it.id } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt index 7ed9f638f..e774ce82e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt @@ -2,12 +2,12 @@ package org.koitharu.kotatsu.core.model.parcelable import android.os.Parcel import androidx.core.os.ParcelCompat +import org.koitharu.kotatsu.core.util.ext.readParcelableCompat +import org.koitharu.kotatsu.core.util.ext.readSerializableCompat import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.ext.readParcelableCompat -import org.koitharu.kotatsu.utils.ext.readSerializableCompat fun Manga.writeToParcel(out: Parcel, flags: Int, withChapters: Boolean) { out.writeLong(id) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt index bd5490e0a..7f6cf2f42 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt @@ -2,15 +2,15 @@ package org.koitharu.kotatsu.core.model.parcelable import android.os.Parcel import android.os.Parcelable +import org.koitharu.kotatsu.core.util.ext.Set import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.ext.Set class ParcelableMangaTags( val tags: Set, ) : Parcelable { constructor(parcel: Parcel) : this( - Set(parcel.readInt()) { parcel.readMangaTag() } + Set(parcel.readInt()) { parcel.readMangaTag() }, ) override fun writeToParcel(parcel: Parcel, flags: Int) { @@ -33,4 +33,4 @@ class ParcelableMangaTags( return arrayOfNulls(size) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt index 8a19866cd..ce873fbc6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt @@ -12,7 +12,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mergeWith -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.net.IDN import java.util.Locale import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt index f32717aad..9547b4da5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt @@ -6,7 +6,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.dnsoverhttps.DnsOverHttps import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.net.InetAddress import java.net.UnknownHostException @@ -52,8 +52,9 @@ class DoHManager( tryGetByIp("8.8.8.8"), tryGetByIp("2001:4860:4860::8888"), tryGetByIp("2001:4860:4860::8844"), - ) + ), ).build() + DoHProvider.CLOUDFLARE -> DnsOverHttps.Builder().client(bootstrapClient) .url("https://cloudflare-dns.com/dns-query".toHttpUrl()) .resolvePrivateAddresses(true) @@ -68,8 +69,9 @@ class DoHManager( tryGetByIp("2606:4700:4700::1001"), tryGetByIp("2606:4700:4700::0064"), tryGetByIp("2606:4700:4700::6400"), - ) + ), ).build() + DoHProvider.ADGUARD -> DnsOverHttps.Builder().client(bootstrapClient) .url("https://dns-unfiltered.adguard.com/dns-query".toHttpUrl()) .resolvePrivateAddresses(true) @@ -79,7 +81,7 @@ class DoHManager( tryGetByIp("94.140.14.141"), tryGetByIp("2a10:50c0::1:ff"), tryGetByIp("2a10:50c0::2:ff"), - ) + ), ).build() } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt index ed1221613..a7dc8a04a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.core.network import android.annotation.SuppressLint import okhttp3.OkHttpClient -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.security.SecureRandom import java.security.cert.X509Certificate import javax.net.ssl.SSLContext diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt index cce51f827..4a709f38b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt @@ -8,7 +8,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.Cookie import okhttp3.HttpUrl -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug private const val PREFS_NAME = "cookies" diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt b/app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt index 0c3899bf6..63907bdde 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt @@ -6,8 +6,8 @@ import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import kotlinx.coroutines.flow.first -import org.koitharu.kotatsu.utils.MediatorStateFlow -import org.koitharu.kotatsu.utils.ext.isOnline +import org.koitharu.kotatsu.core.util.MediatorStateFlow +import org.koitharu.kotatsu.core.util.ext.isOnline class NetworkState( private val connectivityManager: ConnectivityManager, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt b/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt index 1de7b7c35..43c904696 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt @@ -22,16 +22,16 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.core.db.TABLE_HISTORY +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.reader.ui.ReaderActivity -import org.koitharu.kotatsu.utils.ext.getDrawableOrThrow -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.processLifecycleScope -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/VoiceInputContract.kt b/app/src/main/java/org/koitharu/kotatsu/core/os/VoiceInputContract.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/VoiceInputContract.kt rename to app/src/main/java/org/koitharu/kotatsu/core/os/VoiceInputContract.kt index ddb42ab45..15a6de48d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/VoiceInputContract.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/os/VoiceInputContract.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.os import android.app.Activity import android.content.Context diff --git a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaDataRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/domain/MangaDataRepository.kt rename to app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt index 263253786..32862bf59 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaDataRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.domain +package org.koitharu.kotatsu.core.parser import android.graphics.BitmapFactory import android.net.Uri @@ -19,7 +19,6 @@ import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.network.CommonHeaders -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage @@ -33,8 +32,6 @@ import java.util.zip.ZipFile import javax.inject.Inject import kotlin.math.roundToInt -private const val MIN_WEBTOON_RATIO = 2 - @Reusable class MangaDataRepository @Inject constructor( private val okHttpClient: OkHttpClient, @@ -148,6 +145,8 @@ class MangaDataRepository @Inject constructor( companion object { + private const val MIN_WEBTOON_RATIO = 2 + suspend fun getImageMimeType(file: File): String? = runInterruptible(Dispatchers.IO) { val options = BitmapFactory.Options().apply { inJustDecodeBounds = true diff --git a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaIntent.kt similarity index 83% rename from app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt rename to app/src/main/java/org/koitharu/kotatsu/core/parser/MangaIntent.kt index 55c34cb90..5c3d54a17 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaIntent.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaIntent.kt @@ -1,14 +1,14 @@ -package org.koitharu.kotatsu.base.domain +package org.koitharu.kotatsu.core.parser import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.lifecycle.SavedStateHandle -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.getParcelableCompat +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.getParcelableCompat -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat class MangaIntent private constructor( @JvmField val manga: Manga?, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt index 17f97c398..b8e864cba 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt @@ -11,10 +11,10 @@ import kotlinx.coroutines.withContext import okhttp3.OkHttpClient import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.prefs.SourceSettings +import org.koitharu.kotatsu.core.util.ext.toList import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.config.MangaSourceConfig import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.toList import java.lang.ref.WeakReference import java.util.* import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt index a99cd9acc..0f3d6d482 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt @@ -14,6 +14,7 @@ import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.cache.SafeDeferred import org.koitharu.kotatsu.core.prefs.SourceSettings +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.parsers.MangaParser import org.koitharu.kotatsu.parsers.MangaParserAuthProvider import org.koitharu.kotatsu.parsers.config.ConfigKey @@ -25,8 +26,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.domain -import org.koitharu.kotatsu.utils.ext.processLifecycleScope -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable class RemoteMangaRepository( private val parser: MangaParser, 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 6dab7e362..669b7ea41 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 @@ -14,16 +14,16 @@ import dagger.hilt.android.qualifiers.ApplicationContext import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.network.DoHProvider +import org.koitharu.kotatsu.core.util.ext.connectivityManager +import org.koitharu.kotatsu.core.util.ext.filterToSet +import org.koitharu.kotatsu.core.util.ext.getEnumValue +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.putEnumValue +import org.koitharu.kotatsu.core.util.ext.toUriOrNull import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.shelf.domain.ShelfSection -import org.koitharu.kotatsu.utils.ext.connectivityManager -import org.koitharu.kotatsu.utils.ext.filterToSet -import org.koitharu.kotatsu.utils.ext.getEnumValue -import org.koitharu.kotatsu.utils.ext.observe -import org.koitharu.kotatsu.utils.ext.putEnumValue -import org.koitharu.kotatsu.utils.ext.toUriOrNull import java.io.File import java.util.Collections import java.util.EnumSet diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt index 1b3af7980..0080c0b1d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt @@ -2,13 +2,13 @@ package org.koitharu.kotatsu.core.prefs import android.content.Context import androidx.core.content.edit +import org.koitharu.kotatsu.core.util.ext.getEnumValue +import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty +import org.koitharu.kotatsu.core.util.ext.putEnumValue import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.MangaSourceConfig import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.ext.getEnumValue -import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty -import org.koitharu.kotatsu.utils.ext.putEnumValue private const val KEY_SORT_ORDER = "sort_order" diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/AlertDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt similarity index 54% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/AlertDialogFragment.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt index a667fec32..40c091d4d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/AlertDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt @@ -1,8 +1,9 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.app.Dialog import android.os.Bundle import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup import androidx.annotation.CallSuper import androidx.appcompat.app.AlertDialog @@ -12,13 +13,15 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder abstract class AlertDialogFragment : DialogFragment() { - private var viewBinding: B? = null + var viewBinding: B? = null + private set + @Deprecated("", ReplaceWith("requireViewBinding()")) protected val binding: B - get() = checkNotNull(viewBinding) + get() = requireViewBinding() final override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val binding = onInflateView(layoutInflater, null) + val binding = onCreateViewBinding(layoutInflater, null) viewBinding = binding return MaterialAlertDialogBuilder(requireContext(), theme) .setView(binding.root) @@ -32,6 +35,11 @@ abstract class AlertDialogFragment : DialogFragment() { savedInstanceState: Bundle?, ) = viewBinding?.root + final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + onViewBindingCreated(requireViewBinding(), savedInstanceState) + } + @CallSuper override fun onDestroyView() { viewBinding = null @@ -42,7 +50,14 @@ abstract class AlertDialogFragment : DialogFragment() { open fun onDialogCreated(dialog: AlertDialog) = Unit - protected fun bindingOrNull(): B? = viewBinding + @Deprecated("", ReplaceWith("viewBinding")) + protected fun bindingOrNull() = viewBinding + + fun requireViewBinding(): B = checkNotNull(viewBinding) { + "Fragment $this did not return a ViewBinding from onCreateView() or this was called before onCreateView()." + } + + protected abstract fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): B - protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B + protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseActivity.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BaseActivity.kt index c9474a173..f547e527a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseActivity.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.content.Intent import android.content.res.Configuration @@ -25,11 +25,11 @@ import androidx.viewbinding.ViewBinding import dagger.hilt.android.EntryPointAccessors import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.util.ActionModeDelegate -import org.koitharu.kotatsu.base.ui.util.BaseActivityEntryPoint -import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver -import org.koitharu.kotatsu.utils.ext.getThemeColor +import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate +import org.koitharu.kotatsu.core.ui.util.BaseActivityEntryPoint +import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate +import org.koitharu.kotatsu.core.util.ext.getThemeColor @Suppress("LeakingThis") abstract class BaseActivity : @@ -38,7 +38,7 @@ abstract class BaseActivity : private var isAmoledTheme = false - protected lateinit var binding: B + lateinit var viewBinding: B private set @JvmField @@ -88,7 +88,7 @@ abstract class BaseActivity : } protected fun setContentView(binding: B) { - this.binding = binding + this.viewBinding = binding super.setContentView(binding.root) val toolbar = (binding.root.findViewById(R.id.toolbar) as? Toolbar) toolbar?.let(this::setSupportActionBar) @@ -131,7 +131,7 @@ abstract class BaseActivity : } else { ContextCompat.getColor(this, R.color.kotatsu_secondaryContainer) } - val insets = ViewCompat.getRootWindowInsets(binding.root) + val insets = ViewCompat.getRootWindowInsets(viewBinding.root) ?.getInsets(WindowInsetsCompat.Type.systemBars()) ?: return findViewById(androidx.appcompat.R.id.action_mode_bar).apply { setBackgroundColor(actionModeColor) diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt similarity index 73% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt index 6207ce83f..9c81104a1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.app.Dialog import android.os.Bundle @@ -13,17 +13,19 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.dialog.AppBottomSheetDialog -import org.koitharu.kotatsu.utils.ext.findActivity -import org.koitharu.kotatsu.utils.ext.getDisplaySize +import org.koitharu.kotatsu.core.ui.dialog.AppBottomSheetDialog +import org.koitharu.kotatsu.core.util.ext.findActivity +import org.koitharu.kotatsu.core.util.ext.getDisplaySize import com.google.android.material.R as materialR abstract class BaseBottomSheet : BottomSheetDialogFragment() { - private var viewBinding: B? = null + var viewBinding: B? = null + private set + @Deprecated("", ReplaceWith("requireViewBinding()")) protected val binding: B - get() = checkNotNull(viewBinding) + get() = requireViewBinding() protected val behavior: BottomSheetBehavior<*>? get() = (dialog as? BottomSheetDialog)?.behavior @@ -39,13 +41,14 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() { container: ViewGroup?, savedInstanceState: Bundle?, ): View { - val binding = onInflateView(inflater, container) + val binding = onCreateViewBinding(inflater, container) viewBinding = binding return binding.root } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val binding = requireViewBinding() // Enforce max width for tablets val width = resources.getDimensionPixelSize(R.dimen.bottom_sheet_width) if (width > 0) { @@ -55,6 +58,7 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() { binding.root.context.findActivity()?.getDisplaySize()?.let { behavior?.peekHeight = (it.height() * 0.4).toInt() } + onViewBindingCreated(binding, savedInstanceState) } override fun onDestroyView() { @@ -75,7 +79,9 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() { } } - protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B + protected abstract fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): B + + protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit protected fun setExpanded(isExpanded: Boolean, isLocked: Boolean) { val b = behavior ?: return @@ -89,4 +95,8 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() { } b.isDraggable = !isLocked } + + fun requireViewBinding(): B = checkNotNull(viewBinding) { + "Fragment $this did not return a ViewBinding from onCreateView() or this was called before onCreateView()." + } } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFragment.kt similarity index 53% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFragment.kt index 697016c9a..6dfdadf1d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFragment.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.os.Bundle import android.view.LayoutInflater @@ -6,19 +6,21 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.viewbinding.ViewBinding -import org.koitharu.kotatsu.base.ui.util.ActionModeDelegate -import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver +import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate +import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate @Suppress("LeakingThis") abstract class BaseFragment : Fragment(), WindowInsetsDelegate.WindowInsetsListener { - private var viewBinding: B? = null + var viewBinding: B? = null + private set + @Deprecated("", ReplaceWith("requireViewBinding()")) protected val binding: B - get() = checkNotNull(viewBinding) + get() = requireViewBinding() @JvmField protected val exceptionResolver = ExceptionResolver(this) @@ -29,19 +31,20 @@ abstract class BaseFragment : protected val actionModeDelegate: ActionModeDelegate get() = (requireActivity() as BaseActivity<*>).actionModeDelegate - override fun onCreateView( + final override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - val binding = onInflateView(inflater, container) + ): View { + val binding = onCreateViewBinding(inflater, container) viewBinding = binding return binding.root } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) insetsDelegate.onViewCreated(view) + onViewBindingCreated(requireViewBinding(), savedInstanceState) } override fun onDestroyView() { @@ -50,7 +53,14 @@ abstract class BaseFragment : super.onDestroyView() } + fun requireViewBinding(): B = checkNotNull(viewBinding) { + "Fragment $this did not return a ViewBinding from onCreateView() or this was called before onCreateView()." + } + + @Deprecated("", ReplaceWith("viewBinding")) protected fun bindingOrNull() = viewBinding - protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B + protected abstract fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): B + + protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFullscreenActivity.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFullscreenActivity.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt index e43ca8877..96a240e55 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFullscreenActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.graphics.Color import android.os.Build @@ -56,4 +56,4 @@ abstract class BaseFullscreenActivity : } protected open fun onSystemUiVisibilityChanged(isVisible: Boolean) = Unit -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BasePreferenceFragment.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt similarity index 88% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BasePreferenceFragment.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt index 809944e8c..bfffb7ab3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BasePreferenceFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.os.Bundle import android.view.View @@ -9,9 +9,9 @@ import androidx.core.view.updatePadding import androidx.preference.PreferenceFragmentCompat import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner -import org.koitharu.kotatsu.base.ui.util.WindowInsetsDelegate import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate import org.koitharu.kotatsu.settings.SettingsHeadersFragment import javax.inject.Inject @@ -56,6 +56,7 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : ) } + @Suppress("UsePropertyAccessSyntax") protected fun setTitle(title: CharSequence) { (parentFragment as? SettingsHeadersFragment)?.setTitle(title) ?: activity?.setTitle(title) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt new file mode 100644 index 000000000..7a8f1463c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt @@ -0,0 +1,5 @@ +package org.koitharu.kotatsu.core.ui + +import androidx.lifecycle.LifecycleService + +abstract class BaseService : LifecycleService() diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseViewModel.kt similarity index 87% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/BaseViewModel.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/BaseViewModel.kt index ac5f78b09..12cda4167 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseViewModel.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel @@ -9,9 +9,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import org.koitharu.kotatsu.base.ui.util.CountedBooleanLiveData -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.core.ui.util.CountedBooleanLiveData +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/CoroutineIntentService.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/CoroutineIntentService.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt index 1fd56bd94..dc1c59bd4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/CoroutineIntentService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.content.Intent import androidx.lifecycle.lifecycleScope @@ -9,7 +9,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug abstract class CoroutineIntentService : BaseService() { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/DefaultActivityLifecycleCallbacks.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/DefaultActivityLifecycleCallbacks.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt index dd83e4dc7..f97db54ae 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/DefaultActivityLifecycleCallbacks.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui +package org.koitharu.kotatsu.core.ui import android.app.Activity import android.app.Application.ActivityLifecycleCallbacks diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/AppBottomSheetDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/AppBottomSheetDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt index 8b6da8d3d..f76e27d11 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/AppBottomSheetDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.Context import android.graphics.Color @@ -26,4 +26,4 @@ class AppBottomSheetDialog(context: Context, theme: Int) : BottomSheetDialog(con } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/CheckBoxAlertDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/CheckBoxAlertDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt index c452bd1ce..f246aba42 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/CheckBoxAlertDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.Context import android.content.DialogInterface @@ -77,4 +77,4 @@ class CheckBoxAlertDialog private constructor(private val delegate: AlertDialog) fun create() = CheckBoxAlertDialog(delegate.create()) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/ErrorDetailsDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt similarity index 80% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/ErrorDetailsDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt index a9bb5eb8a..6f9d0f12c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/ui/ErrorDetailsDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.core.ui +package org.koitharu.kotatsu.core.ui.dialog import android.content.ClipData import android.content.ClipboardManager @@ -6,7 +6,6 @@ import android.content.Context import android.os.Bundle import android.text.method.LinkMovementMethod import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.text.HtmlCompat import androidx.core.text.htmlEncode @@ -14,12 +13,12 @@ import androidx.core.text.parseAsHtml import androidx.fragment.app.FragmentManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.isReportable +import org.koitharu.kotatsu.core.util.ext.report +import org.koitharu.kotatsu.core.util.ext.requireSerializable +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.DialogErrorDetailsBinding -import org.koitharu.kotatsu.utils.ext.isReportable -import org.koitharu.kotatsu.utils.ext.report -import org.koitharu.kotatsu.utils.ext.requireSerializable -import org.koitharu.kotatsu.utils.ext.withArgs class ErrorDetailsDialog : AlertDialogFragment() { @@ -31,12 +30,12 @@ class ErrorDetailsDialog : AlertDialogFragment() { exception = args.requireSerializable(ARG_ERROR) } - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogErrorDetailsBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): DialogErrorDetailsBinding { return DialogErrorDetailsBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogErrorDetailsBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) with(binding.textViewMessage) { movementMethod = LinkMovementMethod.getInstance() text = context.getString( diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RecyclerViewAlertDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RecyclerViewAlertDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt index a2e28fd17..3199138e4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RecyclerViewAlertDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.Context import android.content.DialogInterface diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RememberSelectionDialogListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt similarity index 85% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RememberSelectionDialogListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt index 7783a564b..e98e5d992 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/RememberSelectionDialogListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.DialogInterface @@ -10,4 +10,4 @@ class RememberSelectionDialogListener(initialValue: Int) : DialogInterface.OnCli override fun onClick(dialog: DialogInterface?, which: Int) { selection = which } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/StorageSelectDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/StorageSelectDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt index 58e353ca8..efc47ffde 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/StorageSelectDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.Context import android.content.DialogInterface @@ -98,4 +98,4 @@ class StorageSelectDialog private constructor(private val delegate: AlertDialog) fun onStorageSelected(file: File) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/TwoButtonsAlertDialog.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/TwoButtonsAlertDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt index 12bc0d955..4d15077e1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/dialog/TwoButtonsAlertDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.dialog +package org.koitharu.kotatsu.core.ui.dialog import android.content.Context import android.content.DialogInterface diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/image/CoilImageGetter.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/utils/image/CoilImageGetter.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt index 381d71d9f..7c5a5467f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/image/CoilImageGetter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.image +package org.koitharu.kotatsu.core.ui.image import android.content.Context import android.graphics.drawable.Drawable diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/image/CoverSizeResolver.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/utils/image/CoverSizeResolver.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt index 69f61133f..43d662759 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/image/CoverSizeResolver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.image +package org.koitharu.kotatsu.core.ui.image import android.view.View import android.view.View.OnLayoutChangeListener @@ -7,10 +7,10 @@ import android.widget.ImageView import coil.size.Dimension import coil.size.Size import coil.size.SizeResolver -import kotlin.coroutines.resume -import kotlin.math.roundToInt import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume +import kotlin.math.roundToInt private const val ASPECT_RATIO_HEIGHT = 18f private const val ASPECT_RATIO_WIDTH = 13f @@ -80,4 +80,4 @@ class CoverSizeResolver( continuation.resume(size) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/image/FaviconFallbackDrawable.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/utils/image/FaviconFallbackDrawable.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt index f6fdaa7df..ab065e004 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/image/FaviconFallbackDrawable.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt @@ -1,7 +1,12 @@ -package org.koitharu.kotatsu.utils.image +package org.koitharu.kotatsu.core.ui.image import android.content.Context -import android.graphics.* +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorFilter +import android.graphics.Paint +import android.graphics.PixelFormat +import android.graphics.Rect import android.graphics.drawable.Drawable import androidx.core.graphics.ColorUtils import com.google.android.material.color.MaterialColors diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/image/RegionBitmapDecoder.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/image/RegionBitmapDecoder.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt index 9736f6776..47d5461cb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/image/RegionBitmapDecoder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.image +package org.koitharu.kotatsu.core.ui.image import android.graphics.Bitmap import android.graphics.BitmapFactory @@ -13,7 +13,11 @@ import coil.decode.Decoder import coil.decode.ImageSource import coil.fetch.SourceResult import coil.request.Options -import coil.size.* +import coil.size.Dimension +import coil.size.Scale +import coil.size.Size +import coil.size.isOriginal +import coil.size.pxOrElse import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/image/TrimTransformation.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt similarity index 91% rename from app/src/main/java/org/koitharu/kotatsu/utils/image/TrimTransformation.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt index b44281f38..bc22724ed 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/image/TrimTransformation.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt @@ -1,8 +1,12 @@ -package org.koitharu.kotatsu.utils.image +package org.koitharu.kotatsu.core.ui.image import android.graphics.Bitmap import androidx.annotation.ColorInt -import androidx.core.graphics.* +import androidx.core.graphics.alpha +import androidx.core.graphics.blue +import androidx.core.graphics.get +import androidx.core.graphics.green +import androidx.core.graphics.red import coil.size.Size import coil.transform.Transformation import kotlin.math.abs @@ -104,4 +108,4 @@ class TrimTransformation( abs(a.blue - b.blue) <= tolerance && abs(a.alpha - b.alpha) <= tolerance } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/AdapterDelegateClickListenerAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/AdapterDelegateClickListenerAdapter.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt index 19d1d5661..a9e6e13ea 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/AdapterDelegateClickListenerAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.view.View import android.view.View.OnClickListener diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/BoundsScrollListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/BoundsScrollListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt index 11d65d7b3..f9d41fec8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/BoundsScrollListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightGridLayoutManager.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightGridLayoutManager.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt index fc6564beb..ddb94ce34 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightGridLayoutManager.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.content.Context import android.util.AttributeSet @@ -34,4 +34,4 @@ class FitHeightGridLayoutManager : GridLayoutManager { super.layoutDecoratedWithMargins(child, left, top, right, bottom) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightLinearLayoutManager.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightLinearLayoutManager.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt index 64e73198a..f4a36a227 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/FitHeightLinearLayoutManager.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.content.Context import android.util.AttributeSet @@ -34,4 +34,4 @@ class FitHeightLinearLayoutManager : LinearLayoutManager { super.layoutDecoratedWithMargins(child, left, top, right, bottom) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/ListSelectionController.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/ListSelectionController.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt index 5cadc9c6f..e552e1098 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/ListSelectionController.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.app.Activity import android.os.Bundle @@ -12,9 +12,9 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView import androidx.savedstate.SavedStateRegistry import androidx.savedstate.SavedStateRegistryOwner -import kotlin.coroutines.EmptyCoroutineContext import kotlinx.coroutines.Dispatchers -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import kotlin.coroutines.EmptyCoroutineContext private const val KEY_SELECTION = "selection" private const val PROVIDER_NAME = "selection_decoration" diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/NestedScrollStateHandle.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/NestedScrollStateHandle.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt index 80d5310d3..b4946ccb0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/NestedScrollStateHandle.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.os.Bundle import android.os.Parcelable diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnListItemClickListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt similarity index 79% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnListItemClickListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt index e61f85bb0..e394740b9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnListItemClickListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.view.View diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnTipCloseListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt similarity index 59% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnTipCloseListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt index 9c9721eef..81078afee 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/OnTipCloseListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list interface OnTipCloseListener { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/PaginationScrollListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/PaginationScrollListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt index 5681cae23..4f70dcd4d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/PaginationScrollListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import androidx.recyclerview.widget.RecyclerView @@ -15,4 +15,4 @@ class PaginationScrollListener(offset: Int, private val callback: Callback) : fun onScrolledToEnd() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/ScrollListenerInvalidationObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/ScrollListenerInvalidationObserver.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt index b3e30c910..5acc5862c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/ScrollListenerInvalidationObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/SectionedSelectionController.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/SectionedSelectionController.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt index d210c6991..066b4fa59 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/SectionedSelectionController.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list +package org.koitharu.kotatsu.core.ui.list import android.app.Activity import android.os.Bundle @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.savedstate.SavedStateRegistry import androidx.savedstate.SavedStateRegistryOwner import kotlinx.coroutines.Dispatchers -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration import kotlin.coroutines.EmptyCoroutineContext private const val PROVIDER_NAME = "selection_decoration_sectioned" diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractDividerItemDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractDividerItemDecoration.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt index 2d91e71c7..ca4bbec76 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractDividerItemDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.decor +package org.koitharu.kotatsu.core.ui.list.decor import android.annotation.SuppressLint import android.content.Context @@ -59,7 +59,7 @@ abstract class AbstractDividerItemDecoration(context: Context) : RecyclerView.It left, parent.paddingTop.toFloat(), right, - (parent.height - parent.paddingBottom).toFloat() + (parent.height - parent.paddingBottom).toFloat(), ) } else { left = 0f @@ -84,4 +84,4 @@ abstract class AbstractDividerItemDecoration(context: Context) : RecyclerView.It above: RecyclerView.ViewHolder, below: RecyclerView.ViewHolder, ): Boolean -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractSelectionItemDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractSelectionItemDecoration.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt index 1974f6a5d..20e3aef78 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/AbstractSelectionItemDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.decor +package org.koitharu.kotatsu.core.ui.list.decor import android.graphics.Canvas import android.graphics.Rect @@ -67,7 +67,7 @@ abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() { if (parent.clipToPadding) { canvas.clipRect( parent.paddingLeft, parent.paddingTop, parent.width - parent.paddingRight, - parent.height - parent.paddingBottom + parent.height - parent.paddingBottom, ) } @@ -108,4 +108,4 @@ abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() { bounds: RectF, state: RecyclerView.State, ) = Unit -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SpacingItemDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SpacingItemDecoration.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt index 5b9fbde29..88f3593ac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SpacingItemDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.decor +package org.koitharu.kotatsu.core.ui.list.decor import android.graphics.Rect import android.view.View diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/TypedSpacingItemDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/TypedSpacingItemDecoration.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt index 5662f026a..244936dbf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/TypedSpacingItemDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.decor +package org.koitharu.kotatsu.core.ui.list.decor import android.graphics.Rect import android.util.SparseIntArray @@ -13,7 +13,7 @@ class TypedSpacingItemDecoration( ) : RecyclerView.ItemDecoration() { private val mapping = SparseIntArray(spacingMapping.size) - + init { spacingMapping.forEach { (k, v) -> mapping[k] = v } } @@ -32,4 +32,4 @@ class TypedSpacingItemDecoration( } outRect.set(spacing, spacing, spacing, spacing) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/BubbleAnimator.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/BubbleAnimator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt index 36b5e0e5f..359edfc05 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/BubbleAnimator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.fastscroll +package org.koitharu.kotatsu.core.ui.list.fastscroll import android.animation.Animator import android.animation.AnimatorListenerAdapter @@ -8,9 +8,9 @@ import android.view.animation.AccelerateInterpolator import android.view.animation.DecelerateInterpolator import androidx.core.view.isInvisible import androidx.core.view.isVisible +import org.koitharu.kotatsu.core.util.ext.animatorDurationScale +import org.koitharu.kotatsu.core.util.ext.measureWidth import kotlin.math.hypot -import org.koitharu.kotatsu.utils.ext.animatorDurationScale -import org.koitharu.kotatsu.utils.ext.measureWidth class BubbleAnimator( private val bubble: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScrollRecyclerView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScrollRecyclerView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt index 5a7c1274e..2b62a6d49 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScrollRecyclerView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.fastscroll +package org.koitharu.kotatsu.core.ui.list.fastscroll import android.content.Context import android.util.AttributeSet @@ -42,4 +42,4 @@ class FastScrollRecyclerView @JvmOverloads constructor( fastScroller.detachRecyclerView() super.onDetachedFromWindow() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScroller.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScroller.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt index e5cb94dd4..d7eca512d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/FastScroller.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.fastscroll +package org.koitharu.kotatsu.core.ui.list.fastscroll import android.annotation.SuppressLint import android.content.Context @@ -22,9 +22,9 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.isLayoutReversed import org.koitharu.kotatsu.databinding.FastScrollerBinding -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.isLayoutReversed import kotlin.math.roundToInt import com.google.android.material.R as materialR @@ -98,6 +98,7 @@ class FastScroller @JvmOverloads constructor( showScrollbar() if (showBubbleAlways && sectionIndexer != null) showBubble() } + RecyclerView.SCROLL_STATE_IDLE -> if (hideScrollbar && !binding.thumb.isSelected) { handler.postDelayed(scrollbarHider, SCROLLBAR_HIDE_DELAY) } @@ -176,10 +177,12 @@ class FastScroller @JvmOverloads constructor( setYPositions() return true } + MotionEvent.ACTION_MOVE -> { setYPositions() return true } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { requestDisallowInterceptTouchEvent(false) setHandleSelected(false) @@ -248,17 +251,20 @@ class FastScroller @JvmOverloads constructor( setMargins(0, marginTop, 0, marginBottom) } } + is CoordinatorLayout -> layoutParams = (layoutParams as CoordinatorLayout.LayoutParams).apply { height = LayoutParams.MATCH_PARENT anchorGravity = GravityCompat.END anchorId = recyclerViewId setMargins(0, marginTop, 0, marginBottom) } + is FrameLayout -> layoutParams = (layoutParams as FrameLayout.LayoutParams).apply { height = LayoutParams.MATCH_PARENT gravity = GravityCompat.END setMargins(0, marginTop, 0, marginBottom) } + is RelativeLayout -> layoutParams = (layoutParams as RelativeLayout.LayoutParams).apply { height = 0 addRule(RelativeLayout.ALIGN_TOP, recyclerViewId) @@ -266,6 +272,7 @@ class FastScroller @JvmOverloads constructor( addRule(RelativeLayout.ALIGN_END, recyclerViewId) setMargins(0, marginTop, 0, marginBottom) } + else -> throw IllegalArgumentException("Parent ViewGroup must be a ConstraintLayout, CoordinatorLayout, FrameLayout, or RelativeLayout") } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/ScrollbarAnimator.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/ScrollbarAnimator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt index 75298a802..1d9287b2d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/fastscroll/ScrollbarAnimator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.list.fastscroll +package org.koitharu.kotatsu.core.ui.list.fastscroll import android.animation.Animator import android.animation.AnimatorListenerAdapter @@ -7,7 +7,7 @@ import android.view.ViewPropertyAnimator import androidx.core.view.isInvisible import androidx.core.view.isVisible import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.animatorDurationScale +import org.koitharu.kotatsu.core.util.ext.animatorDurationScale class ScrollbarAnimator( private val scrollbar: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/DateTimeAgo.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/DateTimeAgo.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt index a11f56e01..8e468b5ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/ui/DateTimeAgo.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt @@ -1,10 +1,10 @@ -package org.koitharu.kotatsu.core.ui +package org.koitharu.kotatsu.core.ui.model import android.content.res.Resources import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.daysDiff +import org.koitharu.kotatsu.core.util.ext.format import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.daysDiff -import org.koitharu.kotatsu.utils.ext.format import java.util.Date sealed class DateTimeAgo : ListModel { @@ -107,9 +107,7 @@ sealed class DateTimeAgo : ListModel { other as Absolute - if (day != other.day) return false - - return true + return day == other.day } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/SortOrder.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/model/SortOrder.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/SortOrder.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/model/SortOrder.kt index 92b9fd9ef..71e6034e6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/ui/SortOrder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/model/SortOrder.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.core.ui +package org.koitharu.kotatsu.core.ui.model import androidx.annotation.StringRes import org.koitharu.kotatsu.R @@ -12,4 +12,4 @@ val SortOrder.titleRes: Int SortOrder.RATING -> R.string.by_rating SortOrder.NEWEST -> R.string.newest SortOrder.ALPHABETICAL -> R.string.by_name - } \ No newline at end of file + } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeDelegate.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt index feed3fc6a..585f39e69 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import androidx.activity.OnBackPressedCallback import androidx.appcompat.view.ActionMode diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt similarity index 78% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt index 0c87ff612..fde599ede 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActionModeListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import androidx.appcompat.view.ActionMode @@ -7,4 +7,4 @@ interface ActionModeListener { fun onActionModeStarted(mode: ActionMode) fun onActionModeFinished(mode: ActionMode) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActivityRecreationHandle.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt similarity index 86% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActivityRecreationHandle.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt index 036515bbe..46c1d0f9e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ActivityRecreationHandle.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt @@ -1,9 +1,9 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.app.Activity import android.os.Bundle import androidx.core.app.ActivityCompat -import org.koitharu.kotatsu.base.ui.DefaultActivityLifecycleCallbacks +import org.koitharu.kotatsu.core.ui.DefaultActivityLifecycleCallbacks import java.util.WeakHashMap import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/BaseActivityEntryPoint.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt similarity index 86% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/BaseActivityEntryPoint.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt index 66b1a588c..309883319 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/BaseActivityEntryPoint.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import dagger.hilt.EntryPoint import dagger.hilt.InstallIn diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/CollapseActionViewCallback.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/CollapseActionViewCallback.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt index 5d9058de1..b417e40e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/CollapseActionViewCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.view.MenuItem import android.view.MenuItem.OnActionExpandListener diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/CountedBooleanLiveData.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/CountedBooleanLiveData.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt index d654e541d..a737c0af9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/CountedBooleanLiveData.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import androidx.annotation.AnyThread import androidx.lifecycle.LiveData @@ -28,4 +28,4 @@ class CountedBooleanLiveData : LiveData(false) { postValue(false) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt index a382f488c..999dd6641 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/DefaultTextWatcher.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.text.Editable import android.text.TextWatcher diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/RecyclerViewOwner.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt similarity index 72% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/RecyclerViewOwner.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt index 9b0976d51..f34963f15 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/RecyclerViewOwner.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt @@ -1,8 +1,8 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import androidx.recyclerview.widget.RecyclerView interface RecyclerViewOwner { val recyclerView: RecyclerView -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleAction.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt similarity index 56% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleAction.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt index 57bb80a78..f9fea6652 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleAction.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt @@ -1,9 +1,8 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import androidx.annotation.StringRes -import org.koitharu.kotatsu.base.domain.ReversibleHandle class ReversibleAction( @StringRes val stringResId: Int, val handle: ReversibleHandle?, -) \ No newline at end of file +) diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleActionObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt similarity index 86% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleActionObserver.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt index ba685c4f4..4f6319f66 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ReversibleActionObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt @@ -1,10 +1,9 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.view.View import androidx.lifecycle.Observer import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.reverseAsync class ReversibleActionObserver( private val snackbarHost: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/base/domain/ReversibleHandle.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt similarity index 70% rename from app/src/main/java/org/koitharu/kotatsu/base/domain/ReversibleHandle.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt index f34c99e69..d3d6bc475 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/domain/ReversibleHandle.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt @@ -1,12 +1,12 @@ -package org.koitharu.kotatsu.base.domain +package org.koitharu.kotatsu.core.ui.util import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.processLifecycleScope -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug fun interface ReversibleHandle { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ShrinkOnScrollBehavior.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/ShrinkOnScrollBehavior.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt index c22585755..8d648ec3a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/ShrinkOnScrollBehavior.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.content.Context import android.util.AttributeSet diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/SpanSizeResolver.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/SpanSizeResolver.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt index 71e5dc398..9c0e07f91 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/SpanSizeResolver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.view.View import androidx.annotation.Px diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/StatusBarDimHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/StatusBarDimHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt index 7a8bf28d4..b58f36ae1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/StatusBarDimHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt @@ -1,11 +1,11 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.animation.ValueAnimator import android.view.animation.AccelerateDecelerateInterpolator -import com.google.android.material.R as materialR import com.google.android.material.appbar.AppBarLayout import com.google.android.material.shape.MaterialShapeDrawable -import org.koitharu.kotatsu.utils.ext.getAnimationDuration +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration +import com.google.android.material.R as materialR class StatusBarDimHelper : AppBarLayout.OnOffsetChangedListener { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/WindowInsetsDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/util/WindowInsetsDelegate.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt index ff80acbbb..a85868857 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/util/WindowInsetsDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.util +package org.koitharu.kotatsu.core.ui.util import android.view.View import androidx.core.graphics.Insets diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt index 3f01e8769..354206ad4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/BottomSheetHeaderBar.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.animation.LayoutTransition import android.content.Context @@ -21,10 +21,10 @@ import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.bottomsheet.BottomSheetBehavior import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration +import org.koitharu.kotatsu.core.util.ext.getThemeDrawable +import org.koitharu.kotatsu.core.util.ext.parents import org.koitharu.kotatsu.databinding.LayoutSheetHeaderBinding -import org.koitharu.kotatsu.utils.ext.getAnimationDuration -import org.koitharu.kotatsu.utils.ext.getThemeDrawable -import org.koitharu.kotatsu.utils.ext.parents import java.util.* import com.google.android.material.R as materialR diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt index 2d18292cc..b872917c0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CheckableImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.content.Context import android.os.Parcel @@ -101,4 +101,4 @@ class CheckableImageView @JvmOverloads constructor( } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt index 88398cbd0..3ad0838ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.annotation.SuppressLint import android.content.Context @@ -13,7 +13,7 @@ import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipGroup import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.castOrNull +import org.koitharu.kotatsu.core.util.ext.castOrNull import com.google.android.material.R as materialR class ChipsView @JvmOverloads constructor( @@ -149,9 +149,7 @@ class ChipsView @JvmOverloads constructor( if (title != other.title) return false if (isCheckable != other.isCheckable) return false if (isChecked != other.isChecked) return false - if (data != other.data) return false - - return true + return data == other.data } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt index 3a52eb237..9bcd4ca60 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/CoverImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.content.Context import android.util.AttributeSet @@ -40,4 +40,4 @@ class CoverImageView @JvmOverloads constructor( } setMeasuredDimension(desiredWidth, desiredHeight) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/HideBottomNavigationOnScrollBehavior.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/HideBottomNavigationOnScrollBehavior.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt index b1742420a..629ffcd12 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/HideBottomNavigationOnScrollBehavior.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.animation.ValueAnimator import android.content.Context @@ -10,8 +10,8 @@ import androidx.core.view.ViewCompat import com.google.android.material.appbar.AppBarLayout import com.google.android.material.bottomnavigation.BottomNavigationView import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.getAnimationDuration -import org.koitharu.kotatsu.utils.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration +import org.koitharu.kotatsu.core.util.ext.measureHeight class HideBottomNavigationOnScrollBehavior @JvmOverloads constructor( context: Context? = null, diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ListItemTextView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ListItemTextView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt index e51509920..71d9314f7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ListItemTextView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.annotation.SuppressLint import android.content.Context @@ -19,7 +19,7 @@ import com.google.android.material.ripple.RippleUtils import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.ShapeAppearanceModel import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.resolveDp +import org.koitharu.kotatsu.core.util.ext.resolveDp @SuppressLint("RestrictedApi") class ListItemTextView @JvmOverloads constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SegmentedBarView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SegmentedBarView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt index 1125b7839..39591490a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SegmentedBarView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.animation.Animator import android.animation.ValueAnimator @@ -12,11 +12,11 @@ import android.view.ViewOutlineProvider import android.view.animation.DecelerateInterpolator import androidx.annotation.ColorInt import androidx.annotation.FloatRange +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.parsers.util.replaceWith -import org.koitharu.kotatsu.utils.ext.getAnimationDuration -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled -import org.koitharu.kotatsu.utils.ext.resolveDp import com.google.android.material.R as materialR class SegmentedBarView @JvmOverloads constructor( @@ -135,9 +135,7 @@ class SegmentedBarView @JvmOverloads constructor( other as Segment if (percent != other.percent) return false - if (color != other.color) return false - - return true + return color == other.color } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SelectableTextView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SelectableTextView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt index e931853f0..32cb29875 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SelectableTextView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.content.Context import android.text.Selection @@ -26,4 +26,4 @@ class SelectableTextView @JvmOverloads constructor( Selection.setSelection(spannableText, text.length) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ShapeView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ShapeView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt index 5ec934c1e..32b7f47dd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ShapeView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.annotation.SuppressLint import android.content.Context diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SlidingBottomNavigationView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SlidingBottomNavigationView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt index 3e9e7b55d..b34a958bf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/SlidingBottomNavigationView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.animation.Animator import android.animation.AnimatorListenerAdapter @@ -14,10 +14,10 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.customview.view.AbsSavedState import androidx.interpolator.view.animation.FastOutLinearInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator -import com.google.android.material.R as materialR import com.google.android.material.bottomnavigation.BottomNavigationView -import org.koitharu.kotatsu.utils.ext.applySystemAnimatorScale -import org.koitharu.kotatsu.utils.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.applySystemAnimatorScale +import org.koitharu.kotatsu.core.util.ext.measureHeight +import com.google.android.material.R as materialR private const val STATE_DOWN = 1 private const val STATE_UP = 2 diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/TwoLinesItemView.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/TwoLinesItemView.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt index f7f8d44e1..37058bac2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/TwoLinesItemView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.annotation.SuppressLint import android.content.Context @@ -23,8 +23,8 @@ import com.google.android.material.ripple.RippleUtils import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.ShapeAppearanceModel import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.databinding.ViewTwoLinesItemBinding -import org.koitharu.kotatsu.utils.ext.resolveDp @SuppressLint("RestrictedApi") class TwoLinesItemView @JvmOverloads constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/WindowInsetHolder.kt b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/WindowInsetHolder.kt rename to app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt index 3279dfc06..57870cf19 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/WindowInsetHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.base.ui.widgets +package org.koitharu.kotatsu.core.ui.widgets import android.content.Context import android.util.AttributeSet diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/AlphanumComparator.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/AlphanumComparator.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/AlphanumComparator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/AlphanumComparator.kt index cee0626c0..46867633e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/AlphanumComparator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/AlphanumComparator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util class AlphanumComparator : Comparator { @@ -60,4 +60,4 @@ class AlphanumComparator : Comparator { } return chunk.toString() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/BufferedObserver.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/BufferedObserver.kt similarity index 64% rename from app/src/main/java/org/koitharu/kotatsu/utils/BufferedObserver.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/BufferedObserver.kt index bc806ec7a..ccebce668 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/BufferedObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/BufferedObserver.kt @@ -1,6 +1,6 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util fun interface BufferedObserver { fun onChanged(t: T, previous: T?) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/CancellableSource.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/CancellableSource.kt similarity index 90% rename from app/src/main/java/org/koitharu/kotatsu/utils/CancellableSource.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/CancellableSource.kt index 9830d86b6..d06daa6ea 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/CancellableSource.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/CancellableSource.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import kotlinx.coroutines.Job import kotlinx.coroutines.ensureActive diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/CompositeMutex.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/CompositeMutex.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/CompositeMutex.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/CompositeMutex.kt index 99f69e11a..9c9c9f0d3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/CompositeMutex.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/CompositeMutex.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import androidx.collection.ArrayMap import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/EditTextValidator.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/EditTextValidator.kt index 37ca77618..3554fc194 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/EditTextValidator.kt @@ -1,11 +1,11 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.content.Context import android.text.Editable import android.text.TextWatcher import android.widget.EditText import androidx.annotation.CallSuper -import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import java.lang.ref.WeakReference abstract class EditTextValidator : TextWatcher { @@ -51,4 +51,4 @@ abstract class EditTextValidator : TextWatcher { class Failed(val message: CharSequence) : ValidationResult() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/FileSize.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/FileSize.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/utils/FileSize.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/FileSize.kt index cb558edfe..6325c3dec 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/FileSize.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/FileSize.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.content.Context import org.koitharu.kotatsu.R @@ -22,8 +22,8 @@ enum class FileSize(private val multiplier: Int) { return buildString { append( DecimalFormat("#,##0.#").format( - bytes / 1024.0.pow(digitGroups.toDouble()) - ) + bytes / 1024.0.pow(digitGroups.toDouble()), + ), ) val unit = units.getOrNull(digitGroups) if (unit != null) { @@ -32,4 +32,4 @@ enum class FileSize(private val multiplier: Int) { } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/FlowLiveData.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/FlowLiveData.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/utils/FlowLiveData.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/FlowLiveData.kt index 797893609..7b3693902 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/FlowLiveData.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/FlowLiveData.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import androidx.lifecycle.LiveData import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/GoneOnInvisibleListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/GoneOnInvisibleListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt index 46de769c6..25ab3717f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/GoneOnInvisibleListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.view.View import android.view.ViewTreeObserver diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/GridTouchHelper.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/GridTouchHelper.kt index 9605fb93b..6608c719e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/GridTouchHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/GridTouchHelper.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.content.Context import android.view.GestureDetector @@ -44,6 +44,7 @@ class GridTouchHelper( else -> return false } } + 2 -> AREA_RIGHT else -> return false }, diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/IdlingDetector.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/IdlingDetector.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/utils/IdlingDetector.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/IdlingDetector.kt index 0501a3da6..d9cbedfdc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/IdlingDetector.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/IdlingDetector.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.os.Handler import android.os.Looper diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/IncognitoModeIndicator.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/utils/IncognitoModeIndicator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt index 8ca72f3eb..7dc2ee1ac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/IncognitoModeIndicator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.app.Activity import android.os.Bundle @@ -11,10 +11,10 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.DefaultActivityLifecycleCallbacks import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.utils.ext.getThemeColor +import org.koitharu.kotatsu.core.ui.DefaultActivityLifecycleCallbacks +import org.koitharu.kotatsu.core.util.ext.getThemeColor import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/MediatorStateFlow.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/utils/MediatorStateFlow.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt index 0f4fda663..7bee7ffc2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/MediatorStateFlow.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt index 075126db2..f8815ae6e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import androidx.annotation.Px import androidx.recyclerview.widget.LinearLayoutManager @@ -23,4 +23,4 @@ class RecyclerViewScrollCallback( lm.scrollToPosition(position) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/RetainedLifecycleCoroutineScope.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/RetainedLifecycleCoroutineScope.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt index 66a232922..cf5645f1c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/RetainedLifecycleCoroutineScope.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import dagger.hilt.android.lifecycle.RetainedLifecycle import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ScreenOrientationHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ScreenOrientationHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt index 4cecbd2a8..8f062e247 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ScreenOrientationHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.app.Activity import android.content.pm.ActivityInfo @@ -18,7 +18,7 @@ class ScreenOrientationHelper(private val activity: Activity) { get() = Settings.System.getInt( activity.contentResolver, Settings.System.ACCELEROMETER_ROTATION, - 0 + 0, ) == 1 var isLandscape: Boolean @@ -42,7 +42,7 @@ class ScreenOrientationHelper(private val activity: Activity) { } } activity.contentResolver.registerContentObserver( - Settings.System.CONTENT_URI, true, observer + Settings.System.CONTENT_URI, true, observer, ) awaitClose { activity.contentResolver.unregisterContentObserver(observer) @@ -50,4 +50,4 @@ class ScreenOrientationHelper(private val activity: Activity) { }.onStart { emit(isAutoRotationEnabled) }.distinctUntilChanged() -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ShareHelper.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ShareHelper.kt index 3bdbc5ce3..57d5e7c80 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ShareHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ShareHelper.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.content.Context import android.net.Uri diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/SingleLiveEvent.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/SingleLiveEvent.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt index cbc89d96b..504690d6f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/SingleLiveEvent.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import androidx.annotation.AnyThread import androidx.annotation.MainThread diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/TaggedActivityResult.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt similarity index 63% rename from app/src/main/java/org/koitharu/kotatsu/utils/TaggedActivityResult.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt index ee84cffb2..8fba053eb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/TaggedActivityResult.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.app.Activity @@ -8,4 +8,4 @@ class TaggedActivityResult( ) val TaggedActivityResult.isSuccess: Boolean - get() = this.result == Activity.RESULT_OK \ No newline at end of file + get() = this.result == Activity.RESULT_OK diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/Throttler.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/Throttler.kt similarity index 88% rename from app/src/main/java/org/koitharu/kotatsu/utils/Throttler.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/Throttler.kt index b026cf15e..5748c79bb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/Throttler.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/Throttler.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.os.SystemClock diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ViewBadge.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ViewBadge.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/ViewBadge.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ViewBadge.kt index 90f7a94d7..e8aa4263d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ViewBadge.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ViewBadge.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.view.View import androidx.annotation.OptIn diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/WorkManagerHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/WorkManagerHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt index 0b768d3f5..95e7aaa4e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/WorkManagerHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.annotation.SuppressLint import androidx.work.WorkInfo diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/WorkServiceStopHelper.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt similarity index 91% rename from app/src/main/java/org/koitharu/kotatsu/utils/WorkServiceStopHelper.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt index b0c426cc2..533c407a2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/WorkServiceStopHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils +package org.koitharu.kotatsu.core.util import android.annotation.SuppressLint import android.content.Context @@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import org.koitharu.kotatsu.utils.ext.processLifecycleScope +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope /** * Workaround for issue diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Android.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Android.kt index 7a1872739..02c0f3ba0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/AndroidExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Android.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.app.Activity import android.app.ActivityManager @@ -41,6 +41,8 @@ import org.json.JSONException import org.jsoup.internal.StringUtil.StringJoiner import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException import kotlin.math.roundToLong @@ -134,8 +136,8 @@ fun Context.getAnimationDuration(@IntegerRes resId: Int): Long { return (resources.getInteger(resId) * animatorDurationScale).roundToLong() } -fun isLowRamDevice(context: Context): Boolean { - return context.activityManager?.isLowRamDevice ?: false +fun Context.isLowRamDevice(): Boolean { + return activityManager?.isLowRamDevice ?: false } fun scaleUpActivityOptionsOf(view: View): ActivityOptions = ActivityOptions.makeScaleUpAnimation( diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Bundle.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Bundle.kt index 1dcead8e2..d17233c25 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Bundle.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Bundle.kt @@ -1,6 +1,6 @@ @file:Suppress("DEPRECATION") -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.Intent import android.os.Build diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coil.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coil.kt index 8837856bc..d870f8d3b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coil.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.Context import android.widget.ImageView @@ -12,9 +12,9 @@ import coil.request.SuccessResult import coil.util.CoilUtils import com.google.android.material.progressindicator.BaseProgressIndicator import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.ui.image.RegionBitmapDecoder +import org.koitharu.kotatsu.core.util.progress.ImageRequestIndicatorListener import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.image.RegionBitmapDecoder -import org.koitharu.kotatsu.utils.progress.ImageRequestIndicatorListener fun ImageView.newImageRequest(lifecycleOwner: LifecycleOwner, data: Any?): ImageRequest.Builder? { val current = CoilUtils.result(this) @@ -23,6 +23,7 @@ fun ImageView.newImageRequest(lifecycleOwner: LifecycleOwner, data: Any?): Image return null } } + disposeImageRequest() return ImageRequest.Builder(context) .data(data) .lifecycle(lifecycleOwner) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Collections.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Collections.kt index 879704445..9cb967878 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CollectionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Collections.kt @@ -1,9 +1,10 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.collection.ArrayMap import androidx.collection.ArraySet import java.util.Collections +@Deprecated("TODO: remove") fun MutableList.move(sourceIndex: Int, targetIndex: Int) { if (sourceIndex <= targetIndex) { Collections.rotate(subList(sourceIndex, targetIndex + 1), -1) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoroutineExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coroutines.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/CoroutineExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coroutines.kt index 3120f2f68..632030e09 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoroutineExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coroutines.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleCoroutineScope diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CursorExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Cursor.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/CursorExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Cursor.kt index eeab153b0..3cec3da3b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CursorExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Cursor.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.ContentValues import android.database.Cursor @@ -36,4 +36,4 @@ fun JSONObject.toContentValues(): ContentValues { return cv } -private fun String.escapeName() = "`$this`" \ No newline at end of file +private fun String.escapeName() = "`$this`" diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Date.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Date.kt index 0a78f0341..e75842410 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DateExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Date.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.annotation.SuppressLint import android.text.format.DateUtils @@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit fun Date.format(pattern: String): String = SimpleDateFormat(pattern).format(this) fun Date.formatRelative(minResolution: Long): CharSequence = DateUtils.getRelativeTimeSpanString( - time, System.currentTimeMillis(), minResolution + time, System.currentTimeMillis(), minResolution, ) fun Date.daysDiff(other: Long): Int { @@ -27,4 +27,4 @@ fun Date.startOfDay(): Long { calendar[Calendar.SECOND] = 0 calendar[Calendar.MILLISECOND] = 0 return calendar.timeInMillis -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DisplayExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Display.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/DisplayExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Display.kt index 6f917ac1e..b8ca902d4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/DisplayExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Display.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.app.Activity import android.graphics.Rect diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/File.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/File.kt index f2800f68c..ac98e2b48 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FileExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/File.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.ContentResolver import android.content.Context diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FlowExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Flow.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/FlowExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Flow.kt index 0ed270991..3db3bb15e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FlowExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Flow.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.os.SystemClock import kotlinx.coroutines.delay diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Fragment.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Fragment.kt index 1b696422e..d755911aa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/FragmentExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Fragment.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.os.Bundle import androidx.annotation.MainThread diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/GraphicsExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Graphics.kt similarity index 85% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/GraphicsExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Graphics.kt index 94dc692a3..2e59b582f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/GraphicsExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Graphics.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.graphics.Rect import kotlin.math.roundToInt @@ -10,4 +10,4 @@ fun Rect.scale(factor: Double) { (width() - newWidth) / 2, (height() - newHeight) / 2, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Http.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Http.kt index a38596cb0..f5a23453e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Http.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.toRequestBody diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/IO.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/IO.kt similarity index 80% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/IO.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/IO.kt index 82a3780ce..d41e0ba38 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/IO.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/IO.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -8,8 +8,8 @@ import kotlinx.coroutines.withContext import okhttp3.ResponseBody import okio.BufferedSink import okio.Source -import org.koitharu.kotatsu.utils.CancellableSource -import org.koitharu.kotatsu.utils.progress.ProgressResponseBody +import org.koitharu.kotatsu.core.util.CancellableSource +import org.koitharu.kotatsu.core.util.progress.ProgressResponseBody fun ResponseBody.withProgress(progressState: MutableStateFlow): ResponseBody { return ProgressResponseBody(this, progressState) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Insets.kt similarity index 83% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Insets.kt index af2ddca22..eef3a3b45 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Insets.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.view.View import androidx.core.graphics.Insets diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LiveDataExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LiveData.kt similarity index 88% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/LiveDataExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/LiveData.kt index 7f23b9487..ed8d96b62 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LiveDataExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LiveData.kt @@ -1,11 +1,11 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.koitharu.kotatsu.utils.BufferedObserver +import org.koitharu.kotatsu.core.util.BufferedObserver import kotlin.coroutines.EmptyCoroutineContext fun LiveData.requireValue(): T = checkNotNull(value) { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LocaleListExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LocaleList.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/LocaleListExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/LocaleList.kt index b6ae2535c..1c093a2d8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LocaleListExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LocaleList.kt @@ -1,7 +1,7 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.core.os.LocaleListCompat -import java.util.* +import java.util.Locale operator fun LocaleListCompat.iterator(): ListIterator = LocaleListCompatIterator(this) @@ -32,4 +32,4 @@ private class LocaleListCompatIterator(private val list: LocaleListCompat) : Lis override fun previous() = list.get(--index) ?: throw NoSuchElementException() override fun previousIndex() = index - 1 -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Network.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Network.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/Network.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Network.kt index 07bdd0304..9f73ecfbf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/Network.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Network.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.Context import android.net.ConnectivityManager diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/OtherExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Other.kt similarity index 77% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/OtherExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Other.kt index 61066cd5d..baf078b7f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/OtherExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Other.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext @Suppress("UNCHECKED_CAST") fun Class.castOrNull(obj: Any?): T? { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/PreferencesExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Preferences.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/PreferencesExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Preferences.kt index d20c1eca6..72b7fc3bd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/PreferencesExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Preferences.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.SharedPreferences import androidx.preference.ListPreference @@ -22,4 +22,4 @@ fun > SharedPreferences.getEnumValue(key: String, defaultValue: E): fun > SharedPreferences.Editor.putEnumValue(key: String, value: E?) { putString(key, value?.name) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/PrimitiveExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Primitive.kt similarity index 81% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/PrimitiveExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Primitive.kt index dee4a06d7..85fe52e38 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/PrimitiveExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Primitive.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext inline fun Int.ifZero(defaultValue: () -> Int): Int = if (this == 0) defaultValue() else this diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt new file mode 100644 index 000000000..0dd4d0cf2 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt @@ -0,0 +1,81 @@ +package org.koitharu.kotatsu.core.util.ext + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder +import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewHolder + +fun RecyclerView.clearItemDecorations() { + suppressLayout(true) + while (itemDecorationCount > 0) { + removeItemDecorationAt(0) + } + suppressLayout(false) +} + +fun RecyclerView.removeItemDecoration(cls: Class) { + repeat(itemDecorationCount) { i -> + if (cls.isInstance(getItemDecorationAt(i))) { + removeItemDecorationAt(i) + return + } + } +} + +var RecyclerView.firstVisibleItemPosition: Int + get() = (layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() + ?: RecyclerView.NO_POSITION + set(value) { + if (value != RecyclerView.NO_POSITION) { + (layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(value, 0) + } + } + +val RecyclerView.visibleItemCount: Int + get() = (layoutManager as? LinearLayoutManager)?.run { + findLastVisibleItemPosition() - findFirstVisibleItemPosition() + } ?: 0 + +fun RecyclerView.findCenterViewPosition(): Int { + val centerX = width / 2f + val centerY = height / 2f + val view = findChildViewUnder(centerX, centerY) ?: return RecyclerView.NO_POSITION + return getChildAdapterPosition(view) +} + +fun RecyclerView.ViewHolder.getItem(clazz: Class): T? { + val rawItem = when (this) { + is AdapterDelegateViewBindingViewHolder<*, *> -> item + is AdapterDelegateViewHolder<*> -> item + else -> null + } ?: return null + return if (clazz.isAssignableFrom(rawItem.javaClass)) { + clazz.cast(rawItem) + } else { + null + } +} + +val RecyclerView.isScrolledToTop: Boolean + get() { + if (childCount == 0) { + return true + } + val holder = findViewHolderForAdapterPosition(0) + return holder != null && holder.itemView.top >= 0 + } + +val RecyclerView.LayoutManager?.firstVisibleItemPosition + get() = when (this) { + is LinearLayoutManager -> findFirstVisibleItemPosition() + is StaggeredGridLayoutManager -> findFirstVisibleItemPositions(null)[0] + else -> 0 + } + +val RecyclerView.LayoutManager?.isLayoutReversed + get() = when (this) { + is LinearLayoutManager -> reverseLayout + is StaggeredGridLayoutManager -> reverseLayout + else -> false + } diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ResourcesExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Resources.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/ResourcesExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Resources.kt index 187642b5b..6e75afee3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ResourcesExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Resources.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.annotation.SuppressLint import android.content.Context diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/String.kt similarity index 89% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/String.kt index 5e4056a5d..bc43c656e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/StringExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/String.kt @@ -1,7 +1,8 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.annotation.FloatRange import org.koitharu.kotatsu.parsers.util.levenshteinDistance +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.UUID inline fun String?.ifNullOrEmpty(defaultValue: () -> String): String { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/TextView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/TextView.kt index 305b1e5df..424e1e77c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/TextView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.graphics.Typeface import android.graphics.drawable.Drawable diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThemeExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Theme.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/ThemeExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Theme.kt index 7896da2e5..102b9bdb1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThemeExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Theme.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.Context import android.graphics.Color diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Throwable.kt similarity index 90% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/Throwable.kt index c205ca939..3623d56d1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ThrowableExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Throwable.kt @@ -1,10 +1,9 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.content.ActivityNotFoundException import android.content.res.Resources import android.util.AndroidRuntimeException import androidx.collection.arraySetOf -import kotlinx.coroutines.CancellationException import okio.FileNotFoundException import okio.IOException import org.acra.ktx.sendWithAcra @@ -84,18 +83,6 @@ private val reportableExceptions = arraySetOf>( UnsupportedOperationException::class.java, ) -inline fun runCatchingCancellable(block: () -> R): Result { - return try { - Result.success(block()) - } catch (e: InterruptedException) { - throw e - } catch (e: CancellationException) { - throw e - } catch (e: Throwable) { - Result.failure(e) - } -} - fun Throwable.isWebViewUnavailable(): Boolean { return (this is AndroidRuntimeException && message?.contains("WebView") == true) || cause?.isWebViewUnavailable() == true diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/View.kt similarity index 65% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/View.kt index 599aff2e7..70816e0b1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/View.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import android.app.Activity import android.graphics.Rect @@ -9,13 +9,9 @@ import android.view.ViewParent import android.view.inputmethod.InputMethodManager import android.widget.Checkable import androidx.core.view.children -import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerView.ItemDecoration import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.slider.Slider -import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder -import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewHolder import kotlin.math.roundToInt fun View.hideKeyboard() { @@ -28,37 +24,6 @@ fun View.showKeyboard() { imm.showSoftInput(this, 0) } -fun RecyclerView.clearItemDecorations() { - suppressLayout(true) - while (itemDecorationCount > 0) { - removeItemDecorationAt(0) - } - suppressLayout(false) -} - -fun RecyclerView.removeItemDecoration(cls: Class) { - repeat(itemDecorationCount) { i -> - if (cls.isInstance(getItemDecorationAt(i))) { - removeItemDecorationAt(i) - return - } - } -} - -var RecyclerView.firstVisibleItemPosition: Int - get() = (layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() - ?: RecyclerView.NO_POSITION - set(value) { - if (value != RecyclerView.NO_POSITION) { - (layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(value, 0) - } - } - -val RecyclerView.visibleItemCount: Int - get() = (layoutManager as? LinearLayoutManager)?.run { - findLastVisibleItemPosition() - findFirstVisibleItemPosition() - } ?: 0 - fun View.hasGlobalPoint(x: Int, y: Int): Boolean { if (visibility != View.VISIBLE) { return false @@ -111,26 +76,6 @@ fun View.resetTransformations() { rotationY = 0f } -fun RecyclerView.findCenterViewPosition(): Int { - val centerX = width / 2f - val centerY = height / 2f - val view = findChildViewUnder(centerX, centerY) ?: return RecyclerView.NO_POSITION - return getChildAdapterPosition(view) -} - -fun RecyclerView.ViewHolder.getItem(clazz: Class): T? { - val rawItem = when (this) { - is AdapterDelegateViewBindingViewHolder<*, *> -> item - is AdapterDelegateViewHolder<*> -> item - else -> null - } ?: return null - return if (clazz.isAssignableFrom(rawItem.javaClass)) { - clazz.cast(rawItem) - } else { - null - } -} - fun Slider.setValueRounded(newValue: Float) { val step = stepSize val roundedValue = if (step <= 0f) { @@ -141,15 +86,6 @@ fun Slider.setValueRounded(newValue: Float) { value = roundedValue.coerceIn(valueFrom, valueTo) } -val RecyclerView.isScrolledToTop: Boolean - get() { - if (childCount == 0) { - return true - } - val holder = findViewHolderForAdapterPosition(0) - return holder != null && holder.itemView.top >= 0 - } - fun ViewGroup.findViewsByType(clazz: Class): Sequence { if (childCount == 0) { return emptySequence() diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/ViewModel.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/ext/ViewModel.kt index 3b840ade1..27108dc26 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/ext/ViewModel.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.ext +package org.koitharu.kotatsu.core.util.ext import androidx.annotation.MainThread import androidx.fragment.app.Fragment diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ImageRequestIndicatorListener.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt similarity index 93% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/ImageRequestIndicatorListener.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt index 1f1dc1b40..5b2d5bee8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ImageRequestIndicatorListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import coil.request.ErrorResult import coil.request.ImageRequest diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/IntPercentLabelFormatter.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt similarity index 88% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/IntPercentLabelFormatter.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt index d9f4ff533..e9882986d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/IntPercentLabelFormatter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import android.content.Context import com.google.android.material.slider.LabelFormatter diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/PausingProgressJob.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt similarity index 92% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/PausingProgressJob.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt index eba6501d9..7641646f8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/PausingProgressJob.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import androidx.annotation.AnyThread import kotlinx.coroutines.Job diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressDeferred.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt similarity index 87% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressDeferred.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt index 7fd1a9357..c1bad74c6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressDeferred.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import kotlinx.coroutines.Deferred import kotlinx.coroutines.flow.Flow @@ -13,4 +13,4 @@ class ProgressDeferred( get() = progress.value fun progressAsFlow(): Flow

= progress -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressJob.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt similarity index 85% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressJob.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt index 919d952ab..826916ddf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressJob.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow @@ -13,4 +13,4 @@ open class ProgressJob

( get() = progress.value fun progressAsFlow(): Flow

= progress -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressResponseBody.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressResponseBody.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt index 20327a272..b66e5cd2a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/ProgressResponseBody.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import kotlinx.coroutines.flow.MutableStateFlow import okhttp3.MediaType diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/progress/TimeLeftEstimator.kt b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt similarity index 96% rename from app/src/main/java/org/koitharu/kotatsu/utils/progress/TimeLeftEstimator.kt rename to app/src/main/java/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt index 97b83f52d..e83507ef1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/progress/TimeLeftEstimator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.utils.progress +package org.koitharu.kotatsu.core.util.progress import android.os.SystemClock import java.util.concurrent.TimeUnit diff --git a/app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt b/app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt index 993894bfd..4a549c6e7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt @@ -4,18 +4,18 @@ import android.content.Context import android.content.Intent import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.EntryPointAccessors -import org.koitharu.kotatsu.base.ui.CoroutineIntentService import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaChapters import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.ui.CoroutineIntentService +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt index d40cb7195..c6921d6e8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt @@ -5,8 +5,8 @@ import android.view.View.OnLayoutChangeListener import androidx.activity.OnBackPressedCallback import androidx.appcompat.view.ActionMode import com.google.android.material.bottomsheet.BottomSheetBehavior -import org.koitharu.kotatsu.base.ui.util.ActionModeListener -import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar +import org.koitharu.kotatsu.core.ui.util.ActionModeListener +import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar class ChaptersBottomSheetMediator( bottomSheet: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index 4915d3221..93d79c01e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -12,9 +12,11 @@ import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.ListSelectionController -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.FragmentChaptersBinding import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter import org.koitharu.kotatsu.details.ui.adapter.ChaptersSelectionDecoration @@ -23,8 +25,6 @@ import org.koitharu.kotatsu.local.ui.LocalChaptersRemoveService import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState -import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import kotlin.math.roundToInt class ChaptersFragment : @@ -37,17 +37,17 @@ class ChaptersFragment : private var chaptersAdapter: ChaptersAdapter? = null private var selectionController: ListSelectionController? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentChaptersBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentChaptersBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) chaptersAdapter = ChaptersAdapter(this) selectionController = ListSelectionController( activity = requireActivity(), - decoration = ChaptersSelectionDecoration(view.context), + decoration = ChaptersSelectionDecoration(binding.root.context), registryOwner = this, callback = this, ) @@ -108,7 +108,7 @@ class ChaptersFragment : else -> { LocalChaptersRemoveService.start(requireContext(), manga, ids) Snackbar.make( - binding.recyclerViewChapters, + requireViewBinding().recyclerViewChapters, R.string.chapters_will_removed_background, Snackbar.LENGTH_LONG, ).show() @@ -185,7 +185,7 @@ class ChaptersFragment : } override fun onSelectionChanged(controller: ListSelectionController, count: Int) { - binding.recyclerViewChapters.invalidateItemDecorations() + requireViewBinding().recyclerViewChapters.invalidateItemDecorations() } override fun onWindowInsetsChanged(insets: Insets) = Unit @@ -196,7 +196,10 @@ class ChaptersFragment : val position = list.indexOfFirst { it.hasFlag(ChapterListItem.FLAG_CURRENT) } - 1 if (position > 0) { val offset = (resources.getDimensionPixelSize(R.dimen.chapter_list_item_height) * 0.6).roundToInt() - adapter.setItems(list, RecyclerViewScrollCallback(binding.recyclerViewChapters, position, offset)) + adapter.setItems( + list, + RecyclerViewScrollCallback(requireViewBinding().recyclerViewChapters, position, offset), + ) } else { adapter.items = list } @@ -206,6 +209,6 @@ class ChaptersFragment : } private fun onLoadingStateChanged(isLoading: Boolean) { - binding.progressBar.isVisible = isLoading + requireViewBinding().progressBar.isVisible = isLoading } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index b2c3e08ae..0a97180c6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -24,14 +24,17 @@ import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.dialog.RecyclerViewAlertDialog -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.os.ShortcutsUpdater +import org.koitharu.kotatsu.core.parser.MangaIntent +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar +import org.koitharu.kotatsu.core.util.ViewBadge +import org.koitharu.kotatsu.core.util.ext.setNavigationBarTransparentCompat +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ActivityDetailsBinding import org.koitharu.kotatsu.details.service.MangaPrefetchService import org.koitharu.kotatsu.details.ui.adapter.branchAD @@ -44,9 +47,6 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet -import org.koitharu.kotatsu.utils.ViewBadge -import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat -import org.koitharu.kotatsu.utils.ext.textAndVisible import javax.inject.Inject @AndroidEntryPoint @@ -59,7 +59,7 @@ class DetailsActivity : PopupMenu.OnMenuItemClickListener { override val bsHeader: BottomSheetHeaderBar? - get() = binding.headerChapters + get() = viewBinding.headerChapters @Inject lateinit var shortcutsUpdater: ShortcutsUpdater @@ -76,16 +76,16 @@ class DetailsActivity : setDisplayHomeAsUpEnabled(true) setDisplayShowTitleEnabled(false) } - binding.buttonRead.setOnClickListener(this) - binding.buttonRead.setOnLongClickListener(this) - binding.buttonDropdown.setOnClickListener(this) - viewBadge = ViewBadge(binding.buttonRead, this) + viewBinding.buttonRead.setOnClickListener(this) + viewBinding.buttonRead.setOnLongClickListener(this) + viewBinding.buttonDropdown.setOnClickListener(this) + viewBadge = ViewBadge(viewBinding.buttonRead, this) - chaptersMenuProvider = if (binding.layoutBottom != null) { - val bsMediator = ChaptersBottomSheetMediator(checkNotNull(binding.layoutBottom)) + chaptersMenuProvider = if (viewBinding.layoutBottom != null) { + val bsMediator = ChaptersBottomSheetMediator(checkNotNull(viewBinding.layoutBottom)) actionModeDelegate.addListener(bsMediator) - checkNotNull(binding.headerChapters).addOnExpansionChangeListener(bsMediator) - checkNotNull(binding.headerChapters).addOnLayoutChangeListener(bsMediator) + checkNotNull(viewBinding.headerChapters).addOnExpansionChangeListener(bsMediator) + checkNotNull(viewBinding.headerChapters).addOnLayoutChangeListener(bsMediator) onBackPressedDispatcher.addCallback(bsMediator) ChaptersMenuProvider(viewModel, bsMediator) } else { @@ -98,7 +98,7 @@ class DetailsActivity : viewModel.onError.observe( this, SnackbarErrorObserver( - host = binding.containerDetails, + host = viewBinding.containerDetails, fragment = null, resolver = exceptionResolver, onResolved = { isResolved -> @@ -113,30 +113,30 @@ class DetailsActivity : } viewModel.historyInfo.observe(this, ::onHistoryChanged) viewModel.selectedBranchName.observe(this) { - binding.headerChapters?.subtitle = it - binding.textViewSubtitle?.textAndVisible = it + viewBinding.headerChapters?.subtitle = it + viewBinding.textViewSubtitle?.textAndVisible = it } viewModel.isChaptersReversed.observe(this) { - binding.headerChapters?.invalidateMenu() ?: invalidateOptionsMenu() + viewBinding.headerChapters?.invalidateMenu() ?: invalidateOptionsMenu() } viewModel.favouriteCategories.observe(this) { invalidateOptionsMenu() } viewModel.branches.observe(this) { - binding.buttonDropdown.isVisible = it.size > 1 + viewBinding.buttonDropdown.isVisible = it.size > 1 } viewModel.chapters.observe(this, PrefetchObserver(this)) - viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(binding.containerDetails)) + viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(viewBinding.containerDetails)) addMenuProvider( DetailsMenuProvider( activity = this, viewModel = viewModel, - snackbarHost = binding.containerChapters, + snackbarHost = viewBinding.containerChapters, shortcutsUpdater = shortcutsUpdater, ), ) - binding.headerChapters?.addOnExpansionChangeListener(this) ?: addMenuProvider(chaptersMenuProvider) + viewBinding.headerChapters?.addOnExpansionChangeListener(this) ?: addMenuProvider(chaptersMenuProvider) } override fun onClick(v: View) { @@ -189,16 +189,16 @@ class DetailsActivity : } else { headerBar.removeMenuProvider(chaptersMenuProvider) } - binding.buttonRead.isGone = isExpanded + viewBinding.buttonRead.isGone = isExpanded } private fun onMangaUpdated(manga: Manga) { title = manga.title val hasChapters = !manga.chapters.isNullOrEmpty() - binding.buttonRead.isEnabled = hasChapters + viewBinding.buttonRead.isEnabled = hasChapters invalidateOptionsMenu() showBottomSheet(manga.chapters != null) - binding.groupHeader?.isVisible = hasChapters + viewBinding.groupHeader?.isVisible = hasChapters } private fun onMangaRemoved(manga: Manga) { @@ -211,17 +211,17 @@ class DetailsActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) if (insets.bottom > 0) { - window.setNavigationBarTransparentCompat(this, binding.layoutBottom?.elevation ?: 0f, 0.9f) + window.setNavigationBarTransparentCompat(this, viewBinding.layoutBottom?.elevation ?: 0f, 0.9f) } } private fun onHistoryChanged(info: HistoryInfo) { - with(binding.buttonRead) { + with(viewBinding.buttonRead) { if (info.history != null) { setText(R.string._continue) setIconResource(if (info.isIncognitoMode) R.drawable.ic_incognito else R.drawable.ic_play) @@ -236,8 +236,8 @@ class DetailsActivity : info.totalChapters == 0 -> getString(R.string.no_chapters) else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters) } - binding.headerChapters?.title = text - binding.textViewTitle?.text = text + viewBinding.headerChapters?.title = text + viewBinding.textViewTitle?.text = text } private fun onNewChaptersChanged(newChapters: Int) { @@ -307,22 +307,22 @@ class DetailsActivity : } } - private fun isTabletLayout() = binding.layoutBottom == null + private fun isTabletLayout() = viewBinding.layoutBottom == null private fun showBottomSheet(isVisible: Boolean) { - val view = binding.layoutBottom ?: return + val view = viewBinding.layoutBottom ?: return if (view.isVisible == isVisible) return val transition = Slide(Gravity.BOTTOM) transition.addTarget(view) transition.interpolator = AccelerateDecelerateInterpolator() - TransitionManager.beginDelayedTransition(binding.root as ViewGroup, transition) + TransitionManager.beginDelayedTransition(viewBinding.root as ViewGroup, transition) view.isVisible = isVisible } private fun makeSnackbar(text: CharSequence, @BaseTransientBottomBar.Duration duration: Int): Snackbar { - val sb = Snackbar.make(binding.containerDetails, text, duration) - if (binding.layoutBottom?.isVisible == true) { - sb.anchorView = binding.headerChapters + val sb = Snackbar.make(viewBinding.containerDetails, text, duration) + if (viewBinding.layoutBottom?.isVisible == true) { + sb.anchorView = viewBinding.headerChapters } return sb } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index f8ed4aa69..875e7fb7a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -19,14 +19,24 @@ import coil.util.CoilUtils import com.google.android.material.chip.Chip import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration -import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter import org.koitharu.kotatsu.core.model.countChaptersByBranch import org.koitharu.kotatsu.core.parser.MangaTagHighlighter +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.FileSize +import org.koitharu.kotatsu.core.util.ext.crossfade +import org.koitharu.kotatsu.core.util.ext.drawableTop +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty +import org.koitharu.kotatsu.core.util.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.resolveDp +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.FragmentDetailsBinding import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.HistoryInfo @@ -43,16 +53,6 @@ import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.search.ui.SearchActivity -import org.koitharu.kotatsu.utils.FileSize -import org.koitharu.kotatsu.utils.ext.crossfade -import org.koitharu.kotatsu.utils.ext.drawableTop -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty -import org.koitharu.kotatsu.utils.ext.measureHeight -import org.koitharu.kotatsu.utils.ext.resolveDp -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf -import org.koitharu.kotatsu.utils.ext.textAndVisible -import org.koitharu.kotatsu.utils.image.CoverSizeResolver import javax.inject.Inject @AndroidEntryPoint @@ -70,13 +70,13 @@ class DetailsFragment : private val viewModel by activityViewModels() - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentDetailsBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentDetailsBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.textViewAuthor.setOnClickListener(this) binding.imageViewCover.setOnClickListener(this) binding.infoLayout.textViewSource.setOnClickListener(this) @@ -114,7 +114,7 @@ class DetailsFragment : } private fun onMangaUpdated(manga: Manga) { - with(binding) { + with(requireViewBinding()) { // Main loadCover(manga) textViewTitle.text = manga.title @@ -159,7 +159,7 @@ class DetailsFragment : } private fun onChaptersChanged(chapters: List?) { - val infoLayout = binding.infoLayout + val infoLayout = requireViewBinding().infoLayout if (chapters.isNullOrEmpty()) { infoLayout.textViewChapters.isVisible = false } else { @@ -171,14 +171,14 @@ class DetailsFragment : private fun onDescriptionChanged(description: CharSequence?) { if (description.isNullOrBlank()) { - binding.textViewDescription.setText(R.string.no_description) + requireViewBinding().textViewDescription.setText(R.string.no_description) } else { - binding.textViewDescription.text = description + requireViewBinding().textViewDescription.text = description } } private fun onLocalSizeChanged(size: Long) { - val textView = binding.infoLayout.textViewSize + val textView = requireViewBinding().infoLayout.textViewSize if (size == 0L) { textView.isVisible = false } else { @@ -188,41 +188,41 @@ class DetailsFragment : } private fun onHistoryChanged(history: HistoryInfo) { - binding.progressView.setPercent(history.history?.percent ?: PROGRESS_NONE, animate = true) + requireViewBinding().progressView.setPercent(history.history?.percent ?: PROGRESS_NONE, animate = true) } private fun onLoadingStateChanged(isLoading: Boolean) { if (isLoading) { - binding.progressBar.show() + requireViewBinding().progressBar.show() } else { - binding.progressBar.hide() + requireViewBinding().progressBar.hide() } } private fun onBookmarksChanged(bookmarks: List) { - var adapter = binding.recyclerViewBookmarks.adapter as? BookmarksAdapter - binding.groupBookmarks.isGone = bookmarks.isEmpty() + var adapter = requireViewBinding().recyclerViewBookmarks.adapter as? BookmarksAdapter + requireViewBinding().groupBookmarks.isGone = bookmarks.isEmpty() if (adapter != null) { adapter.items = bookmarks } else { adapter = BookmarksAdapter(coil, viewLifecycleOwner, this) adapter.items = bookmarks - binding.recyclerViewBookmarks.adapter = adapter + requireViewBinding().recyclerViewBookmarks.adapter = adapter val spacing = resources.getDimensionPixelOffset(R.dimen.bookmark_list_spacing) - binding.recyclerViewBookmarks.addItemDecoration(SpacingItemDecoration(spacing)) + requireViewBinding().recyclerViewBookmarks.addItemDecoration(SpacingItemDecoration(spacing)) } } private fun onScrobblingInfoChanged(scrobblings: List) { - var adapter = binding.recyclerViewScrobbling.adapter as? ScrollingInfoAdapter - binding.recyclerViewScrobbling.isGone = scrobblings.isEmpty() + var adapter = requireViewBinding().recyclerViewScrobbling.adapter as? ScrollingInfoAdapter + requireViewBinding().recyclerViewScrobbling.isGone = scrobblings.isEmpty() if (adapter != null) { adapter.items = scrobblings } else { adapter = ScrollingInfoAdapter(viewLifecycleOwner, coil, childFragmentManager) adapter.items = scrobblings - binding.recyclerViewScrobbling.adapter = adapter - binding.recyclerViewScrobbling.addItemDecoration(ScrobblingItemDecoration()) + requireViewBinding().recyclerViewScrobbling.adapter = adapter + requireViewBinding().recyclerViewScrobbling.addItemDecoration(ScrobblingItemDecoration()) } } @@ -267,7 +267,7 @@ class DetailsFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + requireViewBinding().root.updatePadding( bottom = ( (activity as? NoModalBottomSheetOwner)?.bsHeader?.measureHeight() ?.plus(insets.bottom)?.plus(resources.resolveDp(16)) @@ -277,7 +277,7 @@ class DetailsFragment : } private fun bindTags(manga: Manga) { - binding.chipsTags.setChips( + requireViewBinding().chipsTags.setChips( manga.tags.map { tag -> ChipsView.ChipModel( title = tag.title, @@ -292,13 +292,13 @@ class DetailsFragment : private fun loadCover(manga: Manga) { val imageUrl = manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl } - val lastResult = CoilUtils.result(binding.imageViewCover) + val lastResult = CoilUtils.result(requireViewBinding().imageViewCover) if (lastResult?.request?.data == imageUrl) { return } val request = ImageRequest.Builder(context ?: return) - .target(binding.imageViewCover) - .size(CoverSizeResolver(binding.imageViewCover)) + .target(requireViewBinding().imageViewCover) + .size(CoverSizeResolver(requireViewBinding().imageViewCover)) .data(imageUrl) .tag(manga.source) .crossfade(requireContext()) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt index 73ff6a880..0f20ad3e0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.launch import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.BrowserActivity import org.koitharu.kotatsu.core.os.ShortcutsUpdater +import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.details.ui.model.MangaBranch import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet import org.koitharu.kotatsu.parsers.model.Manga @@ -23,7 +24,6 @@ import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mapNotNullToSet import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorBottomSheet import org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity -import org.koitharu.kotatsu.utils.ShareHelper class DetailsMenuProvider( private val activity: FragmentActivity, 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 ecb76143b..69f666b20 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 @@ -28,11 +28,15 @@ import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.computeSize +import org.koitharu.kotatsu.core.util.ext.toFileOrNull import org.koitharu.kotatsu.details.domain.BranchComparator import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.HistoryInfo @@ -45,16 +49,12 @@ import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.computeSize -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.toFileOrNull +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.IOException import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt index b0072f4a8..c866a2c52 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt @@ -4,10 +4,10 @@ import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import org.koitharu.kotatsu.base.domain.MangaDataRepository -import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.getPreferredBranch +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.toListItem @@ -17,8 +17,8 @@ import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @ViewModelScoped diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt index 5e11ad8d2..d471a5c0b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt @@ -7,11 +7,11 @@ import android.text.style.RelativeSizeSpan import androidx.core.text.buildSpannedString import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.databinding.ItemCheckableNewBinding import org.koitharu.kotatsu.details.ui.model.MangaBranch -import org.koitharu.kotatsu.utils.ext.getThemeColor fun branchAD( clickListener: OnListItemClickListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt index cc3f73f73..add2a583f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.details.ui.adapter import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.details.ui.model.MangaBranch class BranchesAdapter( diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt index ab051c176..ea7dcdd54 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt @@ -3,8 +3,10 @@ package org.koitharu.kotatsu.details.ui.adapter import androidx.core.view.isVisible import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemChapterBinding import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_CURRENT @@ -12,13 +14,11 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_DOWN import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_MISSING import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_NEW import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_UNREAD -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.textAndVisible fun chapterListItemAD( clickListener: OnListItemClickListener, ) = adapterDelegateViewBinding( - { inflater, parent -> ItemChapterBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemChapterBinding.inflate(inflater, parent, false) }, ) { val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener) @@ -36,10 +36,12 @@ fun chapterListItemAD( binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_default) binding.textViewNumber.setTextColor(context.getThemeColor(com.google.android.material.R.attr.colorOnTertiary)) } + FLAG_CURRENT -> { binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_accent) binding.textViewNumber.setTextColor(context.getThemeColor(android.R.attr.textColorPrimaryInverse)) } + else -> { binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_outline) binding.textViewNumber.setTextColor(context.getThemeColor(android.R.attr.textColorTertiary)) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt index 7b91abef5..d1de826d9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt @@ -3,8 +3,8 @@ package org.koitharu.kotatsu.details.ui.adapter import android.content.Context import androidx.recyclerview.widget.DiffUtil import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.details.ui.model.ChapterListItem import kotlin.jvm.internal.Intrinsics diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt index 469ae6514..505de1c4b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt @@ -8,9 +8,9 @@ import android.graphics.RectF import android.view.View import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.util.ext.getThemeColor import com.google.android.material.R as materialR -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration -import org.koitharu.kotatsu.utils.ext.getThemeColor class ChaptersSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt index 93f32add9..7b73a0277 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt @@ -5,11 +5,11 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.databinding.ItemScrobblingInfoBinding import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest fun scrobblingInfoAD( lifecycleOwner: LifecycleOwner, diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt index dfaae62fd..96950f5ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt @@ -17,18 +17,18 @@ import androidx.fragment.app.activityViewModels import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetScrobblingBinding import org.koitharu.kotatsu.details.ui.DetailsViewModel import org.koitharu.kotatsu.image.ui.ImageActivity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorBottomSheet -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf -import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @AndroidEntryPoint @@ -52,15 +52,16 @@ class ScrobblingInfoBottomSheet : scrobblerIndex = requireArguments().getInt(ARG_INDEX, scrobblerIndex) } - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetScrobblingBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetScrobblingBinding { return SheetScrobblingBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetScrobblingBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged) viewModel.onError.observe(viewLifecycleOwner) { - Toast.makeText(view.context, it.getDisplayMessage(view.resources), Toast.LENGTH_SHORT).show() + Toast.makeText(binding.root.context, it.getDisplayMessage(binding.root.resources), Toast.LENGTH_SHORT) + .show() } binding.spinnerStatus.onItemSelectedListener = this @@ -69,7 +70,7 @@ class ScrobblingInfoBottomSheet : binding.imageViewCover.setOnClickListener(this) binding.textViewDescription.movementMethod = LinkMovementMethod.getInstance() - menu = PopupMenu(view.context, binding.buttonMenu).apply { + menu = PopupMenu(binding.root.context, binding.buttonMenu).apply { inflate(R.menu.opt_scrobbling) setOnMenuItemClickListener(this@ScrobblingInfoBottomSheet) } @@ -83,7 +84,7 @@ class ScrobblingInfoBottomSheet : override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { viewModel.updateScrobbling( index = scrobblerIndex, - rating = binding.ratingBar.rating / binding.ratingBar.numStars, + rating = requireViewBinding().ratingBar.rating / requireViewBinding().ratingBar.numStars, status = enumValues().getOrNull(position), ) } @@ -95,7 +96,7 @@ class ScrobblingInfoBottomSheet : viewModel.updateScrobbling( index = scrobblerIndex, rating = rating / ratingBar.numStars, - status = enumValues().getOrNull(binding.spinnerStatus.selectedItemPosition), + status = enumValues().getOrNull(requireViewBinding().spinnerStatus.selectedItemPosition), ) } } @@ -117,13 +118,13 @@ class ScrobblingInfoBottomSheet : dismissAllowingStateLoss() return } - binding.textViewTitle.text = scrobbling.title - binding.ratingBar.rating = scrobbling.rating * binding.ratingBar.numStars - binding.textViewDescription.text = scrobbling.description - binding.spinnerStatus.setSelection(scrobbling.status?.ordinal ?: -1) - binding.imageViewLogo.contentDescription = getString(scrobbling.scrobbler.titleResId) - binding.imageViewLogo.setImageResource(scrobbling.scrobbler.iconResId) - binding.imageViewCover.newImageRequest(viewLifecycleOwner, scrobbling.coverUrl)?.apply { + requireViewBinding().textViewTitle.text = scrobbling.title + requireViewBinding().ratingBar.rating = scrobbling.rating * requireViewBinding().ratingBar.numStars + requireViewBinding().textViewDescription.text = scrobbling.description + requireViewBinding().spinnerStatus.setSelection(scrobbling.status?.ordinal ?: -1) + requireViewBinding().imageViewLogo.contentDescription = getString(scrobbling.scrobbler.titleResId) + requireViewBinding().imageViewLogo.setImageResource(scrobbling.scrobbler.iconResId) + requireViewBinding().imageViewCover.newImageRequest(viewLifecycleOwner, scrobbling.coverUrl)?.apply { placeholder(R.drawable.ic_placeholder) fallback(R.drawable.ic_placeholder) error(R.drawable.ic_error_placeholder) diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt index 7517cb0d1..e2150152a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt @@ -7,14 +7,14 @@ import androidx.work.WorkInfo import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemDownloadBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.util.format -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.ext.textAndVisible fun downloadItemAD( lifecycleOwner: LifecycleOwner, diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt index c4dd45699..d72a541c2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.download.ui.list -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener interface DownloadItemListener : OnListItemClickListener { diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt index ddc1e9154..6fb8ecb9d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt @@ -15,10 +15,10 @@ import androidx.lifecycle.Observer import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.list.ListSelectionController -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration -import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.PausingReceiver @@ -51,7 +51,7 @@ class DownloadsActivity : BaseActivity(), registryOwner = this, callback = this, ) - with(binding.recyclerView) { + with(viewBinding.recyclerView) { setHasFixedSize(true) addItemDecoration(decoration) adapter = downloadsAdapter @@ -61,7 +61,7 @@ class DownloadsActivity : BaseActivity(), viewModel.items.observe(this) { downloadsAdapter.items = it } - viewModel.onActionDone.observe(this, ReversibleActionObserver(binding.recyclerView)) + viewModel.onActionDone.observe(this, ReversibleActionObserver(viewBinding.recyclerView)) val menuObserver = Observer { _ -> invalidateOptionsMenu() } viewModel.hasActiveWorks.observe(this, menuObserver) viewModel.hasPausedWorks.observe(this, menuObserver) @@ -69,12 +69,12 @@ class DownloadsActivity : BaseActivity(), } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( left = insets.left + listSpacing, right = insets.right + listSpacing, bottom = insets.bottom, ) - binding.toolbar.updatePadding( + viewBinding.toolbar.updatePadding( left = insets.left, right = insets.right, ) @@ -104,7 +104,7 @@ class DownloadsActivity : BaseActivity(), } override fun onSelectionChanged(controller: ListSelectionController, count: Int) { - binding.recyclerView.invalidateItemDecorations() + viewBinding.recyclerView.invalidateItemDecorations() } override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt index 2778efdc4..16fa29387 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD import org.koitharu.kotatsu.list.ui.adapter.relatedDateItemAD diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt index 0ca62de1b..eb47bc515 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt @@ -12,9 +12,9 @@ import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.NO_ID import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration -import org.koitharu.kotatsu.utils.ext.getItem -import org.koitharu.kotatsu.utils.ext.getThemeColor +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.util.ext.getItem +import org.koitharu.kotatsu.core.util.ext.getThemeColor import com.google.android.material.R as materialR class DownloadsSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() { diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt index cdcf5c4db..fb6e455ff 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt @@ -16,10 +16,13 @@ import kotlinx.coroutines.plus import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.download.domain.DownloadState import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -27,9 +30,6 @@ import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.daysDiff import java.util.Date import java.util.UUID import java.util.concurrent.TimeUnit diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt index 21f57cf3d..d7985849c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt @@ -23,6 +23,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.domain.DownloadState import org.koitharu.kotatsu.download.ui.list.DownloadsActivity @@ -31,8 +32,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.search.ui.MangaListActivity -import org.koitharu.kotatsu.utils.ext.getDrawableOrThrow -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.UUID import com.google.android.material.R as materialR diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt index 69453b711..10dbb2292 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt @@ -4,9 +4,9 @@ import android.view.View import androidx.lifecycle.Observer import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.findActivity import org.koitharu.kotatsu.download.ui.list.DownloadsActivity import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner -import org.koitharu.kotatsu.utils.ext.findActivity class DownloadStartedObserver( private val snackbarHost: View, diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt index 49c285fa1..bb26b9614 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt @@ -35,10 +35,17 @@ import okio.IOException import okio.buffer import okio.sink import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.Throttler +import org.koitharu.kotatsu.core.util.WorkManagerHelper +import org.koitharu.kotatsu.core.util.ext.deleteAwait +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty +import org.koitharu.kotatsu.core.util.ext.writeAllCancellable +import org.koitharu.kotatsu.core.util.progress.TimeLeftEstimator import org.koitharu.kotatsu.download.domain.DownloadState import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges @@ -51,15 +58,8 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.utils.Throttler -import org.koitharu.kotatsu.utils.WorkManagerHelper -import org.koitharu.kotatsu.utils.ext.deleteAwait -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.writeAllCancellable -import org.koitharu.kotatsu.utils.progress.TimeLeftEstimator +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import java.util.UUID import java.util.concurrent.TimeUnit diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt index 353911801..71dc7aa4c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt @@ -7,7 +7,7 @@ import android.content.IntentFilter import android.net.Uri import android.os.PatternMatcher import androidx.core.app.PendingIntentCompat -import org.koitharu.kotatsu.utils.ext.toUUIDOrNull +import org.koitharu.kotatsu.core.util.ext.toUUIDOrNull import java.util.UUID class PausingReceiver( diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt b/app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt index 5fbce6f56..e3ea1c156 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt @@ -2,14 +2,14 @@ package org.koitharu.kotatsu.explore.domain import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.almostEquals +import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.suggestions.domain.TagsBlacklist -import org.koitharu.kotatsu.utils.ext.almostEquals -import org.koitharu.kotatsu.utils.ext.asArrayList -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject class ExploreRepository @Inject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt b/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt index 618dc4763..d0159e851 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt @@ -16,14 +16,15 @@ import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.dialog.TwoButtonsAlertDialog -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner -import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver -import org.koitharu.kotatsu.base.ui.util.SpanSizeResolver import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.dialog.TwoButtonsAlertDialog +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.ui.util.SpanSizeResolver +import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.databinding.FragmentExploreBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter @@ -36,7 +37,6 @@ import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity -import org.koitharu.kotatsu.utils.ext.addMenuProvider import javax.inject.Inject @AndroidEntryPoint @@ -54,14 +54,14 @@ class ExploreFragment : private var paddingHorizontal = 0 override val recyclerView: RecyclerView - get() = binding.recyclerView + get() = requireViewBinding().recyclerView - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): FragmentExploreBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentExploreBinding { return FragmentExploreBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentExploreBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) exploreAdapter = ExploreAdapter(coil, viewLifecycleOwner, this, this) with(binding.recyclerView) { adapter = exploreAdapter @@ -70,7 +70,7 @@ class ExploreFragment : val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing) paddingHorizontal = spacing } - addMenuProvider(ExploreMenuProvider(view.context, viewModel)) + addMenuProvider(ExploreMenuProvider(binding.root.context, viewModel)) viewModel.content.observe(viewLifecycleOwner) { exploreAdapter?.items = it } @@ -89,7 +89,7 @@ class ExploreFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, ) } @@ -138,7 +138,7 @@ class ExploreFragment : } private fun onGridModeChanged(isGrid: Boolean) { - binding.recyclerView.layoutManager = if (isGrid) { + requireViewBinding().recyclerView.layoutManager = if (isGrid) { GridLayoutManager(requireContext(), 4).also { lm -> lm.spanSizeLookup = ExploreGridSpanSizeLookup(checkNotNull(exploreAdapter), lm) } diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt index d81472ba3..6ee8eb2b8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt @@ -13,17 +13,17 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.ReversibleHandle -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsStateFlow +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.ui.util.ReversibleHandle +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.explore.domain.ExploreRepository import org.koitharu.kotatsu.explore.ui.model.ExploreItem import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject private const val TIP_SUGGESTIONS = "suggestions" diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt index 51f5ccc13..f8386cda1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt @@ -3,7 +3,7 @@ package org.koitharu.kotatsu.explore.ui.adapter import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.explore.ui.model.ExploreItem class ExploreAdapter( diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt index a502d6931..bccedb039 100644 --- a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt @@ -7,9 +7,15 @@ import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.parser.favicon.faviconUri +import org.koitharu.kotatsu.core.ui.image.FaviconFallbackDrawable +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemEmptyCardBinding import org.koitharu.kotatsu.databinding.ItemExploreButtonsBinding import org.koitharu.kotatsu.databinding.ItemExploreSourceGridBinding @@ -17,12 +23,6 @@ import org.koitharu.kotatsu.databinding.ItemExploreSourceListBinding import org.koitharu.kotatsu.databinding.ItemHeaderButtonBinding import org.koitharu.kotatsu.explore.ui.model.ExploreItem import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.setTextAndVisible -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.image.FaviconFallbackDrawable fun exploreButtonsAD( clickListener: View.OnClickListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt index 72fb8d48c..e99653964 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt @@ -7,12 +7,13 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map -import org.koitharu.kotatsu.base.domain.ReversibleHandle import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.SortOrder import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.util.ReversibleHandle +import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity import org.koitharu.kotatsu.favourites.data.FavouriteEntity import org.koitharu.kotatsu.favourites.data.toFavouriteCategory @@ -21,7 +22,6 @@ import org.koitharu.kotatsu.favourites.data.toMangaList import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels -import org.koitharu.kotatsu.utils.ext.mapItems import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt index 3118a4618..dd275369d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt @@ -8,12 +8,11 @@ import androidx.core.view.updatePadding import androidx.fragment.app.commit import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID -import kotlin.text.Typography.dagger @AndroidEntryPoint class FavouritesActivity : BaseActivity() { @@ -37,7 +36,7 @@ class FavouritesActivity : BaseActivity() { } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt index c6cbd4be7..c62b36b1c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt @@ -6,7 +6,7 @@ import androidx.appcompat.view.ActionMode import androidx.recyclerview.widget.RecyclerView import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity import com.google.android.material.R as materialR @@ -41,10 +41,12 @@ class CategoriesSelectionCallback( mode.finish() true } + R.id.action_remove -> { confirmDeleteCategories(controller.snapshot(), mode) true } + else -> false } } @@ -61,4 +63,4 @@ class CategoriesSelectionCallback( mode.finish() }.show() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt index ebeaf648a..3ee6833f0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt @@ -9,10 +9,10 @@ import android.view.View import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.util.ext.getItem +import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel -import org.koitharu.kotatsu.utils.ext.getItem -import org.koitharu.kotatsu.utils.ext.getThemeColor import com.google.android.material.R as materialR class CategoriesSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() { @@ -22,7 +22,7 @@ class CategoriesSelectionDecoration(context: Context) : AbstractSelectionItemDec private val strokeColor = context.getThemeColor(materialR.attr.colorPrimary, Color.RED) private val fillColor = ColorUtils.setAlphaComponent( ColorUtils.blendARGB(strokeColor, context.getThemeColor(materialR.attr.colorSurface), 0.8f), - 0x74 + 0x74, ) private val padding = context.resources.getDimension(R.dimen.grid_spacing_outer) @@ -54,4 +54,4 @@ class CategoriesSelectionDecoration(context: Context) : AbstractSelectionItemDec paint.style = Paint.Style.STROKE canvas.drawRoundRect(bounds, radius, radius, paint) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt index 3be5f542f..66901002d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt @@ -20,10 +20,11 @@ import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding import org.koitharu.kotatsu.favourites.ui.FavouritesActivity import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoriesAdapter @@ -31,7 +32,6 @@ import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEdit import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import javax.inject.Inject @AndroidEntryPoint @@ -61,17 +61,17 @@ class FavouriteCategoriesActivity : activity = this, decoration = CategoriesSelectionDecoration(this), registryOwner = this, - callback = CategoriesSelectionCallback(binding.recyclerView, viewModel), + callback = CategoriesSelectionCallback(viewBinding.recyclerView, viewModel), ) - binding.buttonDone.setOnClickListener(this) - selectionController.attachToRecyclerView(binding.recyclerView) - binding.recyclerView.setHasFixedSize(true) - binding.recyclerView.adapter = adapter - binding.fabAdd.setOnClickListener(this) + viewBinding.buttonDone.setOnClickListener(this) + selectionController.attachToRecyclerView(viewBinding.recyclerView) + viewBinding.recyclerView.setHasFixedSize(true) + viewBinding.recyclerView.adapter = adapter + viewBinding.fabAdd.setOnClickListener(this) onBackPressedDispatcher.addCallback(exitReorderModeCallback) viewModel.detalizedCategories.observe(this, ::onCategoriesChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null)) + viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.isInReorderMode.observe(this, ::onReorderModeChanged) } @@ -126,16 +126,16 @@ class FavouriteCategoriesActivity : override fun onEmptyActionClick() = Unit override fun onWindowInsetsChanged(insets: Insets) { - binding.fabAdd.updateLayoutParams { + viewBinding.fabAdd.updateLayoutParams { rightMargin = topMargin + insets.right leftMargin = topMargin + insets.left bottomMargin = topMargin + insets.bottom } - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( bottom = insets.bottom, ) } @@ -149,21 +149,21 @@ class FavouriteCategoriesActivity : val transition = Fade().apply { duration = resources.getInteger(android.R.integer.config_shortAnimTime).toLong() } - TransitionManager.beginDelayedTransition(binding.toolbar, transition) + TransitionManager.beginDelayedTransition(viewBinding.toolbar, transition) reorderHelper?.attachToRecyclerView(null) reorderHelper = if (isReorderMode) { selectionController.clear() - binding.fabAdd.hide() + viewBinding.fabAdd.hide() ItemTouchHelper(ReorderHelperCallback()).apply { - attachToRecyclerView(binding.recyclerView) + attachToRecyclerView(viewBinding.recyclerView) } } else { - binding.fabAdd.show() + viewBinding.fabAdd.show() null } - binding.recyclerView.isNestedScrollingEnabled = !isReorderMode + viewBinding.recyclerView.isNestedScrollingEnabled = !isReorderMode invalidateOptionsMenu() - binding.buttonDone.isVisible = isReorderMode + viewBinding.buttonDone.isVisible = isReorderMode exitReorderModeCallback.isEnabled = isReorderMode } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt index 7819d0112..f85ff122e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt @@ -1,10 +1,10 @@ package org.koitharu.kotatsu.favourites.ui.categories import androidx.recyclerview.widget.RecyclerView -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener interface FavouriteCategoriesListListener : OnListItemClickListener { fun onDragHandleTouch(holder: RecyclerView.ViewHolder): Boolean -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt index 6c8d48798..e2057a28c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt @@ -8,15 +8,15 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.mapItems +import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.LoadingState -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.mapItems -import org.koitharu.kotatsu.utils.ext.requireValue import java.util.Collections import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt index d69ea5ec1..57d73ad5e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt @@ -15,14 +15,14 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.animatorDurationScale +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.databinding.ItemCategoryBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesListListener import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.animatorDurationScale -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.newImageRequest fun categoryAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt index a9a99305b..d7980dfcb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt @@ -16,16 +16,16 @@ import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.model.FavouriteCategory -import org.koitharu.kotatsu.core.ui.titleRes +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.model.titleRes +import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.getSerializableCompat +import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.getSerializableCompat -import org.koitharu.kotatsu.utils.ext.setChecked import com.google.android.material.R as materialR @AndroidEntryPoint @@ -46,16 +46,16 @@ class FavouritesCategoryEditActivity : setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } initSortSpinner() - binding.buttonDone.setOnClickListener(this) - binding.editName.addTextChangedListener(this) - afterTextChanged(binding.editName.text) + viewBinding.buttonDone.setOnClickListener(this) + viewBinding.editName.addTextChangedListener(this) + afterTextChanged(viewBinding.editName.text) viewModel.onSaved.observe(this) { finishAfterTransition() } viewModel.category.observe(this, ::onCategoryChanged) viewModel.isLoading.observe(this, ::onLoadingStateChanged) viewModel.onError.observe(this, ::onError) viewModel.isTrackerEnabled.observe(this) { - binding.switchTracker.isVisible = it + viewBinding.switchTracker.isVisible = it } } @@ -75,27 +75,27 @@ class FavouritesCategoryEditActivity : override fun onClick(v: View) { when (v.id) { R.id.button_done -> viewModel.save( - title = binding.editName.text?.toString()?.trim().orEmpty(), + title = viewBinding.editName.text?.toString()?.trim().orEmpty(), sortOrder = getSelectedSortOrder(), - isTrackerEnabled = binding.switchTracker.isChecked, - isVisibleOnShelf = binding.switchShelf.isChecked, + isTrackerEnabled = viewBinding.switchTracker.isChecked, + isVisibleOnShelf = viewBinding.switchShelf.isChecked, ) } } override fun afterTextChanged(s: Editable?) { - binding.buttonDone.isEnabled = !s.isNullOrBlank() + viewBinding.buttonDone.isEnabled = !s.isNullOrBlank() } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) - binding.scrollView.updatePadding( + viewBinding.scrollView.updatePadding( bottom = insets.bottom, ) - binding.toolbar.updateLayoutParams { + viewBinding.toolbar.updateLayoutParams { topMargin = insets.top } } @@ -109,40 +109,40 @@ class FavouritesCategoryEditActivity : if (selectedSortOrder != null) { return } - binding.editName.setText(category?.title) + viewBinding.editName.setText(category?.title) selectedSortOrder = category?.order val sortText = getString((category?.order ?: SortOrder.NEWEST).titleRes) - binding.editSort.setText(sortText, false) - binding.switchTracker.setChecked(category?.isTrackingEnabled ?: true, false) - binding.switchShelf.setChecked(category?.isVisibleInLibrary ?: true, false) + viewBinding.editSort.setText(sortText, false) + viewBinding.switchTracker.setChecked(category?.isTrackingEnabled ?: true, false) + viewBinding.switchShelf.setChecked(category?.isVisibleInLibrary ?: true, false) } private fun onError(e: Throwable) { - binding.textViewError.text = e.getDisplayMessage(resources) - binding.textViewError.isVisible = true + viewBinding.textViewError.text = e.getDisplayMessage(resources) + viewBinding.textViewError.isVisible = true } private fun onLoadingStateChanged(isLoading: Boolean) { - binding.editSort.isEnabled = !isLoading - binding.editName.isEnabled = !isLoading - binding.switchTracker.isEnabled = !isLoading - binding.switchShelf.isEnabled = !isLoading + viewBinding.editSort.isEnabled = !isLoading + viewBinding.editName.isEnabled = !isLoading + viewBinding.switchTracker.isEnabled = !isLoading + viewBinding.switchShelf.isEnabled = !isLoading if (isLoading) { - binding.textViewError.isVisible = false + viewBinding.textViewError.isVisible = false } } private fun initSortSpinner() { val entries = FavouriteCategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) } val adapter = SortAdapter(this, entries) - binding.editSort.setAdapter(adapter) - binding.editSort.onItemClickListener = this + viewBinding.editSort.setAdapter(adapter) + viewBinding.editSort.onItemClickListener = this } private fun getSelectedSortOrder(): SortOrder { selectedSortOrder?.let { return it } val entries = FavouriteCategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) } - val index = entries.indexOf(binding.editSort.text.toString()) + val index = entries.indexOf(viewBinding.editSort.text.toString()) return FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(index) ?: SortOrder.NEWEST } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt index 8e84a52c1..2677f1cd0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt @@ -6,15 +6,15 @@ import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.EXTRA_ID import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.NO_ID import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.emitValue import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt index 93bf67e1d..2c9b5f4d5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt @@ -11,16 +11,16 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetFavoriteCategoriesBinding import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity import org.koitharu.kotatsu.favourites.ui.categories.select.adapter.MangaCategoriesAdapter import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class FavouriteCategoriesBottomSheet : @@ -33,13 +33,13 @@ class FavouriteCategoriesBottomSheet : private var adapter: MangaCategoriesAdapter? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = SheetFavoriteCategoriesBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetFavoriteCategoriesBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) adapter = MangaCategoriesAdapter(this) binding.recyclerViewCategories.adapter = adapter binding.buttonDone.setOnClickListener(this) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt index 791a79787..32a7f0f11 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt @@ -5,13 +5,13 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.ids import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet.Companion.KEY_MANGA_LIST import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt index df6e54ca0..351037748 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.favourites.ui.categories.select.adapter import androidx.recyclerview.widget.DiffUtil import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem class MangaCategoriesAdapter( @@ -34,4 +34,4 @@ class MangaCategoriesAdapter( return super.getChangePayload(oldItem, newItem) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt index c9ce1e8b2..3badc482b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt @@ -1,14 +1,14 @@ package org.koitharu.kotatsu.favourites.ui.categories.select.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ItemCheckableNewBinding import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem fun mangaCategoryAD( clickListener: OnListItemClickListener ) = adapterDelegateViewBinding( - { inflater, parent -> ItemCheckableNewBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemCheckableNewBinding.inflate(inflater, parent, false) }, ) { itemView.setOnClickListener { @@ -21,4 +21,4 @@ fun mangaCategoryAD( isChecked = item.isChecked } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index d37f33c56..77c128fe5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -9,13 +9,14 @@ import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController -import org.koitharu.kotatsu.core.ui.titleRes +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.model.titleRes +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.withArgs +import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener { @@ -24,10 +25,10 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis override val isSwipeRefreshEnabled = false - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) if (viewModel.categoryId != NO_ID) { - addMenuProvider(FavouritesListMenuProvider(view.context, viewModel)) + addMenuProvider(FavouritesListMenuProvider(binding.root.context, viewModel)) } viewModel.sortOrder.observe(viewLifecycleOwner) { activity?.invalidateOptionsMenu() } } diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt index 85e49c294..4300d3e05 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt @@ -7,7 +7,7 @@ import android.view.MenuItem import androidx.core.view.MenuProvider import androidx.core.view.forEach import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.titleRes +import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity import org.koitharu.kotatsu.parsers.model.SortOrder diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index b6007cd6e..b8e310dcb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -10,9 +10,10 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID @@ -27,7 +28,6 @@ import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt b/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt index 1e84585de..784f74280 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt @@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart -import org.koitharu.kotatsu.base.domain.ReversibleHandle import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity @@ -19,6 +18,8 @@ import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.ui.util.ReversibleHandle +import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.history.data.HistoryEntity import org.koitharu.kotatsu.history.data.toMangaHistory import org.koitharu.kotatsu.parsers.model.Manga @@ -26,7 +27,6 @@ import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.tryScrobble import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.ext.mapItems import javax.inject.Inject const val PROGRESS_NONE = -1f diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt index f7e6b58ec..e9b2dcda1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt @@ -9,10 +9,9 @@ import androidx.fragment.app.commit import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner -import kotlin.text.Typography.dagger @AndroidEntryPoint class HistoryActivity : @@ -20,7 +19,7 @@ class HistoryActivity : AppBarOwner { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,7 +36,7 @@ class HistoryActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt index 4f0805690..a17e0da8f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt @@ -3,8 +3,8 @@ package org.koitharu.kotatsu.history.ui import android.content.Context import androidx.lifecycle.LifecycleOwner import coil.ImageLoader -import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter import org.koitharu.kotatsu.list.ui.adapter.MangaListListener diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt index 0ad1f5e92..de17fc3ed 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt @@ -3,15 +3,15 @@ package org.koitharu.kotatsu.history.ui import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.View import androidx.appcompat.view.ActionMode import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.addMenuProvider @AndroidEntryPoint class HistoryListFragment : MangaListFragment() { @@ -19,9 +19,9 @@ class HistoryListFragment : MangaListFragment() { override val viewModel by viewModels() override val isSwipeRefreshEnabled = false - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - addMenuProvider(HistoryListMenuProvider(view.context, viewModel)) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) + addMenuProvider(HistoryListMenuProvider(binding.root.context, viewModel)) viewModel.isGroupingEnabled.observe(viewLifecycleOwner) { activity?.invalidateOptionsMenu() } @@ -48,6 +48,7 @@ class HistoryListFragment : MangaListFragment() { mode.finish() true } + else -> super.onActionItemClicked(controller, mode, item) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index a3d5663ff..da09bea62 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -9,12 +9,16 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.daysDiff +import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.MangaWithHistory @@ -28,10 +32,6 @@ import org.koitharu.kotatsu.list.ui.model.toGridModel import org.koitharu.kotatsu.list.ui.model.toListDetailedModel import org.koitharu.kotatsu.list.ui.model.toListModel import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.daysDiff -import org.koitharu.kotatsu.utils.ext.emitValue -import org.koitharu.kotatsu.utils.ext.onFirst import java.util.Date import java.util.concurrent.TimeUnit import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt index dc4d1e22b..dc2bd9d8e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt @@ -1,14 +1,19 @@ package org.koitharu.kotatsu.history.ui.util import android.content.Context -import android.graphics.* +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorFilter +import android.graphics.Paint +import android.graphics.PixelFormat +import android.graphics.Rect import android.graphics.drawable.Drawable import androidx.annotation.StyleRes import androidx.appcompat.content.res.AppCompatResources import androidx.core.graphics.ColorUtils import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.scale import org.koitharu.kotatsu.history.domain.PROGRESS_NONE -import org.koitharu.kotatsu.utils.ext.scale class ReadingProgressDrawable( context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt index 243e8cb5d..49c05a7c5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt @@ -11,8 +11,8 @@ import android.view.animation.AccelerateDecelerateInterpolator import androidx.annotation.AttrRes import androidx.annotation.StyleRes import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getAnimationDuration import org.koitharu.kotatsu.history.domain.PROGRESS_NONE -import org.koitharu.kotatsu.utils.ext.getAnimationDuration class ReadingProgressView @JvmOverloads constructor( context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt b/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt index 9794039e8..469ea71c7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt @@ -17,12 +17,12 @@ import coil.target.ViewTarget import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat +import org.koitharu.kotatsu.core.util.ext.indicator import org.koitharu.kotatsu.databinding.ActivityImageBinding import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.getSerializableExtraCompat -import org.koitharu.kotatsu.utils.ext.indicator import javax.inject.Inject @AndroidEntryPoint @@ -42,7 +42,7 @@ class ImageActivity : BaseActivity() { } override fun onWindowInsetsChanged(insets: Insets) { - with(binding.toolbar) { + with(viewBinding.toolbar) { updatePadding( left = insets.left, right = insets.right, @@ -59,8 +59,8 @@ class ImageActivity : BaseActivity() { .memoryCachePolicy(CachePolicy.DISABLED) .lifecycle(this) .tag(intent.getSerializableExtraCompat(EXTRA_SOURCE)) - .target(SsivTarget(binding.ssiv)) - .indicator(binding.progressBar) + .target(SsivTarget(viewBinding.ssiv)) + .indicator(viewBinding.progressBar) .enqueueWith(coil) } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt index 37339aac2..2b7141385 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt @@ -2,7 +2,6 @@ package org.koitharu.kotatsu.list.ui import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.fragment.app.FragmentManager @@ -10,12 +9,12 @@ import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.slider.Slider import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.util.ext.setValueRounded +import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter import org.koitharu.kotatsu.databinding.DialogListModeBinding -import org.koitharu.kotatsu.utils.ext.setValueRounded -import org.koitharu.kotatsu.utils.progress.IntPercentLabelFormatter import javax.inject.Inject @AndroidEntryPoint @@ -27,13 +26,13 @@ class ListModeBottomSheet : @Inject lateinit var settings: AppSettings - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = DialogListModeBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogListModeBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val mode = settings.listMode binding.buttonList.isChecked = mode == ListMode.LIST binding.buttonListDetailed.isChecked = mode == ListMode.DETAILED_LIST @@ -41,7 +40,7 @@ class ListModeBottomSheet : binding.textViewGridTitle.isVisible = mode == ListMode.GRID binding.sliderGrid.isVisible = mode == ListMode.GRID - binding.sliderGrid.setLabelFormatter(IntPercentLabelFormatter(view.context)) + binding.sliderGrid.setLabelFormatter(IntPercentLabelFormatter(binding.root.context)) binding.sliderGrid.setValueRounded(settings.gridSize.toFloat()) binding.sliderGrid.addOnChangeListener(this) @@ -58,8 +57,8 @@ class ListModeBottomSheet : R.id.button_grid -> ListMode.GRID else -> return } - binding.textViewGridTitle.isVisible = mode == ListMode.GRID - binding.sliderGrid.isVisible = mode == ListMode.GRID + requireViewBinding().textViewGridTitle.isVisible = mode == ListMode.GRID + requireViewBinding().sliderGrid.isVisible = mode == ListMode.GRID settings.listMode = mode } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index 2aad241b3..c503087e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -20,18 +20,26 @@ import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.FitHeightGridLayoutManager -import org.koitharu.kotatsu.base.ui.list.FitHeightLinearLayoutManager -import org.koitharu.kotatsu.base.ui.list.ListSelectionController -import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration -import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration -import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller -import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.list.FitHeightGridLayoutManager +import org.koitharu.kotatsu.core.ui.list.FitHeightLinearLayoutManager +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller +import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.clearItemDecorations +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.resolveDp +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver @@ -48,14 +56,6 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.search.ui.MangaListActivity -import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.clearItemDecorations -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.measureHeight -import org.koitharu.kotatsu.utils.ext.resolveDp -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import javax.inject.Inject @AndroidEntryPoint @@ -88,18 +88,18 @@ abstract class MangaListFragment : protected val selectedItems: Set get() = collectSelectedItems() - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentListBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) listAdapter = onCreateAdapter() - spanResolver = MangaListSpanResolver(view.resources) + spanResolver = MangaListSpanResolver(binding.root.resources) selectionController = ListSelectionController( activity = requireActivity(), - decoration = MangaSelectionDecoration(view.context), + decoration = MangaSelectionDecoration(binding.root.context), registryOwner = this, callback = this, ) @@ -163,7 +163,7 @@ abstract class MangaListFragment : @CallSuper override fun onRefresh() { - binding.swipeRefreshLayout.isRefreshing = true + requireViewBinding().swipeRefreshLayout.isRefreshing = true viewModel.onRefresh() } @@ -185,10 +185,10 @@ abstract class MangaListFragment : @CallSuper protected open fun onLoadingStateChanged(isLoading: Boolean) { - binding.swipeRefreshLayout.isEnabled = binding.swipeRefreshLayout.isRefreshing || + requireViewBinding().swipeRefreshLayout.isEnabled = requireViewBinding().swipeRefreshLayout.isRefreshing || isSwipeRefreshEnabled && !isLoading if (!isLoading) { - binding.swipeRefreshLayout.isRefreshing = false + requireViewBinding().swipeRefreshLayout.isRefreshing = false } } @@ -201,15 +201,15 @@ abstract class MangaListFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, ) - binding.recyclerView.fastScroller.updateLayoutParams { + requireViewBinding().recyclerView.fastScroller.updateLayoutParams { bottomMargin = insets.bottom } if (activity is MainActivity) { val headerHeight = (activity as? AppBarOwner)?.appBar?.measureHeight() ?: insets.top - binding.swipeRefreshLayout.setProgressViewOffset( + requireViewBinding().swipeRefreshLayout.setProgressViewOffset( true, headerHeight + resources.resolveDp(-72), headerHeight + resources.resolveDp(10), @@ -233,12 +233,12 @@ abstract class MangaListFragment : private fun onGridScaleChanged(scale: Float) { spanSizeLookup.invalidateCache() - spanResolver?.setGridSize(scale, binding.recyclerView) + spanResolver?.setGridSize(scale, requireViewBinding().recyclerView) } private fun onListModeChanged(mode: ListMode) { spanSizeLookup.invalidateCache() - with(binding.recyclerView) { + with(requireViewBinding().recyclerView) { clearItemDecorations() removeOnLayoutChangeListener(spanResolver) when (mode) { @@ -269,7 +269,7 @@ abstract class MangaListFragment : addOnLayoutChangeListener(spanResolver) } } - selectionController?.attachToRecyclerView(binding.recyclerView) + selectionController?.attachToRecyclerView(requireViewBinding().recyclerView) } } @@ -310,16 +310,16 @@ abstract class MangaListFragment : } override fun onSelectionChanged(controller: ListSelectionController, count: Int) { - binding.recyclerView.invalidateItemDecorations() + requireViewBinding().recyclerView.invalidateItemDecorations() } override fun onFastScrollStart(fastScroller: FastScroller) { (activity as? AppBarOwner)?.appBar?.setExpanded(false, true) - binding.swipeRefreshLayout.isEnabled = false + requireViewBinding().swipeRefreshLayout.isEnabled = false } override fun onFastScrollStop(fastScroller: FastScroller) { - binding.swipeRefreshLayout.isEnabled = isSwipeRefreshEnabled + requireViewBinding().swipeRefreshLayout.isEnabled = isSwipeRefreshEnabled } private fun collectSelectedItems(): Set { @@ -343,7 +343,7 @@ abstract class MangaListFragment : override fun getSpanSize(position: Int): Int { val total = - (binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1 + (requireViewBinding().recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1 return when (listAdapter?.getItemViewType(position)) { ITEM_TYPE_MANGA_GRID -> 1 else -> total diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt index 6ff381fe4..b123776dc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt @@ -6,17 +6,17 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData abstract class MangaListViewModel( private val settings: AppSettings, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt index b8d5e03c9..5518e15a3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt @@ -12,10 +12,10 @@ import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.NO_ID import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.util.ext.getItem +import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.list.ui.model.MangaItemModel -import org.koitharu.kotatsu.utils.ext.getItem -import org.koitharu.kotatsu.utils.ext.getThemeColor import com.google.android.material.R as materialR open class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDecoration() { diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt index d03a7cdff..72bef49ae 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt @@ -3,13 +3,13 @@ package org.koitharu.kotatsu.list.ui.adapter import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.databinding.ItemEmptyCardBinding import org.koitharu.kotatsu.list.ui.model.EmptyHint import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun emptyHintAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt index 29a4b1dbb..745eb583e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt @@ -3,13 +3,13 @@ package org.koitharu.kotatsu.list.ui.adapter import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.databinding.ItemEmptyStateBinding import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun emptyStateListAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt index 52b3db95a..4e25a5eb7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt @@ -1,15 +1,15 @@ package org.koitharu.kotatsu.list.ui.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.databinding.ItemErrorFooterBinding import org.koitharu.kotatsu.list.ui.model.ErrorFooter import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.getDisplayMessage fun errorFooterAD( listener: MangaListListener, ) = adapterDelegateViewBinding( - { inflater, parent -> ItemErrorFooterBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemErrorFooterBinding.inflate(inflater, parent, false) }, ) { binding.root.setOnClickListener { @@ -20,4 +20,4 @@ fun errorFooterAD( binding.textViewTitle.text = item.exception.getDisplayMessage(context.resources) binding.imageViewIcon.setImageResource(item.icon) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt index a31b55d3f..03de52eb8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt @@ -2,15 +2,15 @@ package org.koitharu.kotatsu.list.ui.adapter import androidx.core.view.isVisible import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.databinding.ItemErrorStateBinding import org.koitharu.kotatsu.list.ui.model.ErrorState import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.getDisplayMessage fun errorStateListAD( listener: ListStateHolderListener, ) = adapterDelegateViewBinding( - { inflater, parent -> ItemErrorStateBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemErrorStateBinding.inflate(inflater, parent, false) }, ) { binding.buttonRetry.setOnClickListener { @@ -27,4 +27,4 @@ fun errorStateListAD( setText(item.buttonText) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt index d8ab7ce94..4a0f8f2fe 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt @@ -1,13 +1,13 @@ package org.koitharu.kotatsu.list.ui.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import org.koitharu.kotatsu.core.ui.titleRes +import org.koitharu.kotatsu.core.ui.model.titleRes +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.databinding.ItemHeader2Binding import org.koitharu.kotatsu.list.ui.model.ListHeader2 import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled -import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun listHeader2AD( listener: MangaListListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt index feaa97b0d..51a58e2e0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt @@ -1,10 +1,10 @@ package org.koitharu.kotatsu.list.ui.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.databinding.ItemHeaderButtonBinding import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun listHeaderAD( listener: ListHeaderClickListener?, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt index 9bb885da4..d1cf4f20c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.list.ui.adapter import android.view.View -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt index 98859c239..900738327 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt @@ -5,18 +5,18 @@ import coil.ImageLoader import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemMangaGridBinding import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaGridModel import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.image.CoverSizeResolver fun mangaGridItemAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt index cabf3a0e1..f471cc99a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListHeader2 import org.koitharu.kotatsu.list.ui.model.ListModel diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt index 26ced553f..645ecefa4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt @@ -8,18 +8,18 @@ import com.google.android.material.badge.BadgeDrawable import com.google.android.material.chip.Chip import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.ext.textAndVisible -import org.koitharu.kotatsu.utils.image.CoverSizeResolver fun mangaListDetailedItemAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt index 48904c2c4..77f68418d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt @@ -5,16 +5,16 @@ import coil.ImageLoader import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaListModel import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.ext.textAndVisible fun mangaListItemAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt index 98a4bc8f6..3a615aab5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt @@ -3,7 +3,7 @@ package org.koitharu.kotatsu.list.ui.adapter import android.widget.TextView import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.model.ListModel fun relatedDateItemAD() = adapterDelegate(R.layout.item_header) { @@ -11,4 +11,4 @@ fun relatedDateItemAD() = adapterDelegate(R.layout.item_ bind { (itemView as TextView).text = item.format(context.resources) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt index e34b5ad94..5dcb3a21a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt @@ -5,14 +5,14 @@ import androidx.core.view.isVisible import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.titleRes +import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.databinding.ItemCheckableNewBinding import org.koitharu.kotatsu.databinding.ItemFilterHeaderBinding fun filterSortDelegate( listener: OnFilterChangedListener, ) = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemCheckableNewBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemCheckableNewBinding.inflate(layoutInflater, parent, false) }, ) { itemView.setOnClickListener { @@ -28,7 +28,7 @@ fun filterSortDelegate( fun filterTagDelegate( listener: OnFilterChangedListener, ) = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemCheckableNewBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemCheckableNewBinding.inflate(layoutInflater, parent, false) }, ) { itemView.setOnClickListener { @@ -42,7 +42,7 @@ fun filterTagDelegate( } fun filterHeaderDelegate() = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemFilterHeaderBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemFilterHeaderBinding.inflate(layoutInflater, parent, false) }, ) { bind { @@ -63,4 +63,4 @@ fun filterErrorDelegate() = adapterDelegate(R.layo bind { (itemView as TextView).setText(item.textResId) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt index 226d73ed6..f1dc651f7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt @@ -3,18 +3,17 @@ package org.koitharu.kotatsu.list.ui.filter import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem -import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.SearchView import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.LinearLayoutManager import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.util.CollapseActionViewCallback +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback +import org.koitharu.kotatsu.core.util.ext.parentFragmentViewModels import org.koitharu.kotatsu.databinding.SheetFilterBinding import org.koitharu.kotatsu.remotelist.ui.RemoteListViewModel -import org.koitharu.kotatsu.utils.ext.parentFragmentViewModels class FilterBottomSheet : BaseBottomSheet(), @@ -25,12 +24,12 @@ class FilterBottomSheet : private val viewModel by parentFragmentViewModels() private var collapsibleActionViewCallback: CollapseActionViewCallback? = null - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetFilterBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetFilterBinding { return SheetFilterBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetFilterBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val adapter = FilterAdapter(viewModel, this) binding.recyclerView.adapter = adapter viewModel.filterItems.observe(viewLifecycleOwner, adapter::setItems) @@ -65,13 +64,13 @@ class FilterBottomSheet : override fun onCurrentListChanged(previousList: MutableList, currentList: MutableList) { if (currentList.size > previousList.size && view != null) { - (binding.recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0) + (requireViewBinding().recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0) } } private fun initOptionsMenu() { - binding.headerBar.inflateMenu(R.menu.opt_filter) - val searchMenuItem = binding.headerBar.menu.findItem(R.id.action_search) + requireViewBinding().headerBar.inflateMenu(R.menu.opt_filter) + val searchMenuItem = requireViewBinding().headerBar.menu.findItem(R.id.action_search) searchMenuItem.setOnActionExpandListener(this) val searchView = searchMenuItem.actionView as SearchView searchView.setOnQueryTextListener(this) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt index 96fb630ae..b8c04d96d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt @@ -13,12 +13,12 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.update import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.text.Collator import java.util.Locale import java.util.TreeSet @@ -188,9 +188,7 @@ class FilterCoordinator( if (tags != other.tags) return false if (isLoading != other.isLoading) return false - if (isError != other.isError) return false - - return true + return isError == other.isError } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt index 5d9682d75..1be8b5b74 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.list.ui.model import android.content.Context import androidx.annotation.StringRes -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo class ListHeader private constructor( val text: CharSequence?, @@ -46,9 +46,7 @@ class ListHeader private constructor( if (textRes != other.textRes) return false if (dateTimeAgo != other.dateTimeAgo) return false if (buttonTextRes != other.buttonTextRes) return false - if (payload != other.payload) return false - - return true + return payload == other.payload } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt index 0f053bfd6..dab335ee2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.list.ui.model -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.parsers.model.SortOrder class ListHeader2( @@ -16,10 +16,9 @@ class ListHeader2( other as ListHeader2 if (chips != other.chips) return false - if (sortOrder != other.sortOrder) return false + return sortOrder == other.sortOrder // Not need to check hasSelectedTags - return true } override fun hashCode(): Int { @@ -27,4 +26,4 @@ class ListHeader2( result = 31 * result + (sortOrder?.hashCode() ?: 0) return result } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt index 20fba3c37..89cd7eee1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt @@ -1,16 +1,16 @@ package org.koitharu.kotatsu.list.ui.model import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.ext.ifZero import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.ifZero import java.net.SocketTimeoutException import java.net.UnknownHostException diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt index d1f40dc46..1d246ebb2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.list.ui.model -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.parsers.model.Manga data class MangaListDetailedModel( diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt index 7653dbf07..9684dd63c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt @@ -11,9 +11,9 @@ import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.withContext import okhttp3.Cache import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.computeSize +import org.koitharu.kotatsu.core.util.ext.getStorageName import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.utils.ext.computeSize -import org.koitharu.kotatsu.utils.ext.getStorageName import java.io.File import javax.inject.Inject 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 eb216a140..6d08885af 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 @@ -14,7 +14,6 @@ import org.koitharu.kotatsu.parsers.util.json.getLongOrDefault import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet import org.koitharu.kotatsu.parsers.util.toTitleCase -import org.koitharu.kotatsu.utils.AlphanumComparator import java.io.File class MangaIndex(source: String?) { @@ -126,7 +125,7 @@ class MangaIndex(source: String?) { item.put("id", id) list.add(item) } - val comparator = AlphanumComparator() + val comparator = org.koitharu.kotatsu.core.util.AlphanumComparator() list.sortWith(compareBy(comparator) { it.getString("name") }) val newJo = JSONObject() list.forEachIndexed { i, obj -> diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt index 255bfdda6..755ed222b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt @@ -9,15 +9,15 @@ import kotlinx.coroutines.withContext import okio.Source import okio.buffer import okio.sink +import org.koitharu.kotatsu.core.util.FileSize +import org.koitharu.kotatsu.core.util.ext.longHashCode +import org.koitharu.kotatsu.core.util.ext.subdir +import org.koitharu.kotatsu.core.util.ext.takeIfReadable +import org.koitharu.kotatsu.core.util.ext.takeIfWriteable +import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.parsers.util.SuspendLazy -import org.koitharu.kotatsu.utils.FileSize -import org.koitharu.kotatsu.utils.ext.longHashCode -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.subdir -import org.koitharu.kotatsu.utils.ext.takeIfReadable -import org.koitharu.kotatsu.utils.ext.takeIfWriteable -import org.koitharu.kotatsu.utils.ext.writeAllCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt index 70307defa..e5c9bf9e1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt @@ -13,13 +13,13 @@ import okio.buffer import okio.sink import okio.source import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException +import org.koitharu.kotatsu.core.util.ext.resolveName +import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.local.data.input.LocalMangaInput -import org.koitharu.kotatsu.utils.ext.resolveName -import org.koitharu.kotatsu.utils.ext.writeAllCancellable import java.io.File import java.io.IOException import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt index 9dc597eb0..e383da294 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt @@ -4,6 +4,9 @@ import androidx.core.net.toFile import androidx.core.net.toUri import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible +import org.koitharu.kotatsu.core.util.ext.listFilesRecursive +import org.koitharu.kotatsu.core.util.ext.longHashCode +import org.koitharu.kotatsu.core.util.ext.toListSorted import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.ImageFileFilter import org.koitharu.kotatsu.local.data.LocalManga @@ -14,10 +17,6 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.toCamelCase -import org.koitharu.kotatsu.utils.AlphanumComparator -import org.koitharu.kotatsu.utils.ext.listFilesRecursive -import org.koitharu.kotatsu.utils.ext.longHashCode -import org.koitharu.kotatsu.utils.ext.toListSorted import java.io.File import java.util.zip.ZipFile @@ -89,7 +88,7 @@ class LocalMangaDirInput(root: File) : LocalMangaInput(root) { val file = chapter.url.toUri().toFile() if (file.isDirectory) { file.listFilesRecursive(ImageFileFilter()) - .toListSorted(compareBy(AlphanumComparator()) { x -> x.name }) + .toListSorted(compareBy(org.koitharu.kotatsu.core.util.AlphanumComparator()) { x -> x.name }) .map { val pageUri = it.toUri().toString() MangaPage( @@ -105,7 +104,7 @@ class LocalMangaDirInput(root: File) : LocalMangaInput(root) { .asSequence() .filter { x -> !x.isDirectory } .map { it.name } - .toListSorted(AlphanumComparator()) + .toListSorted(org.koitharu.kotatsu.core.util.AlphanumComparator()) .map { val pageUri = zipUri(file, it) MangaPage( @@ -122,7 +121,7 @@ class LocalMangaDirInput(root: File) : LocalMangaInput(root) { private fun String.toHumanReadable() = replace("_", " ").toCamelCase() private fun getChaptersFiles(): List = root.listFilesRecursive(CbzFilter()) - .toListSorted(compareBy(AlphanumComparator()) { x -> x.name }) + .toListSorted(compareBy(org.koitharu.kotatsu.core.util.AlphanumComparator()) { x -> x.name }) private fun findFirstImageEntry(): String? { val filter = ImageFileFilter() diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt index 7c01e50b8..e768e5b9b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt @@ -7,6 +7,9 @@ import androidx.core.net.toFile import androidx.core.net.toUri import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible +import org.koitharu.kotatsu.core.util.ext.longHashCode +import org.koitharu.kotatsu.core.util.ext.readText +import org.koitharu.kotatsu.core.util.ext.toListSorted import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.local.data.output.LocalMangaOutput @@ -15,10 +18,6 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.toCamelCase -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.toListSorted import java.io.File import java.util.Enumeration import java.util.zip.ZipEntry @@ -71,18 +70,19 @@ class LocalMangaZipInput(root: File) : LocalMangaInput(root) { publicUrl = fileUri, source = MangaSource.LOCAL, coverUrl = zipUri(root, findFirstImageEntry(zip.entries())?.name.orEmpty()), - chapters = chapters.sortedWith(AlphanumComparator()).mapIndexed { i, s -> - MangaChapter( - id = "$i$s".longHashCode(), - name = s.ifEmpty { title }, - number = i + 1, - source = MangaSource.LOCAL, - uploadDate = 0L, - url = uriBuilder.fragment(s).build().toString(), - scanlator = null, - branch = null, - ) - }, + chapters = chapters.sortedWith(org.koitharu.kotatsu.core.util.AlphanumComparator()) + .mapIndexed { i, s -> + MangaChapter( + id = "$i$s".longHashCode(), + name = s.ifEmpty { title }, + number = i + 1, + source = MangaSource.LOCAL, + uploadDate = 0L, + url = uriBuilder.fragment(s).build().toString(), + scanlator = null, + branch = null, + ) + }, altTitle = null, rating = -1f, isNsfw = false, @@ -125,7 +125,7 @@ class LocalMangaZipInput(root: File) : LocalMangaInput(root) { } } entries - .toListSorted(compareBy(AlphanumComparator()) { x -> x.name }) + .toListSorted(compareBy(org.koitharu.kotatsu.core.util.AlphanumComparator()) { x -> x.name }) .map { x -> val entryUri = zipUri(file, x.name) MangaPage( @@ -141,7 +141,7 @@ class LocalMangaZipInput(root: File) : LocalMangaInput(root) { private fun findFirstImageEntry(entries: Enumeration): ZipEntry? { val list = entries.toList() .filterNot { it.isDirectory } - .sortedWith(compareBy(AlphanumComparator()) { x -> x.name }) + .sortedWith(compareBy(org.koitharu.kotatsu.core.util.AlphanumComparator()) { x -> x.name }) val map = MimeTypeMap.getSingleton() return list.firstOrNull { map.getMimeTypeFromExtension(it.name.substringAfterLast('.')) diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt index 4e97b188e..ef050f1cc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt @@ -2,13 +2,13 @@ package org.koitharu.kotatsu.local.data.output import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible +import org.koitharu.kotatsu.core.util.ext.deleteAwait +import org.koitharu.kotatsu.core.util.ext.takeIfReadable import org.koitharu.kotatsu.core.zip.ZipOutput import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.toFileNameSafe -import org.koitharu.kotatsu.utils.ext.deleteAwait -import org.koitharu.kotatsu.utils.ext.takeIfReadable import java.io.File class LocalMangaDirOutput( diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt index 6c1fda62e..23caca4fa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt @@ -3,12 +3,12 @@ package org.koitharu.kotatsu.local.data.output import androidx.annotation.WorkerThread import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible +import org.koitharu.kotatsu.core.util.ext.deleteAwait +import org.koitharu.kotatsu.core.util.ext.readText import org.koitharu.kotatsu.core.zip.ZipOutput import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter -import org.koitharu.kotatsu.utils.ext.deleteAwait -import org.koitharu.kotatsu.utils.ext.readText import java.io.File import java.util.zip.ZipFile 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 2ca31d0e5..9763882a7 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 @@ -12,6 +12,8 @@ import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch import kotlinx.coroutines.runInterruptible import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.util.CompositeMutex +import org.koitharu.kotatsu.core.util.ext.deleteAwait import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.LocalStorageManager @@ -25,11 +27,8 @@ import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.AlphanumComparator -import org.koitharu.kotatsu.utils.CompositeMutex -import org.koitharu.kotatsu.utils.ext.deleteAwait -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import javax.inject.Inject import javax.inject.Singleton @@ -65,7 +64,7 @@ class LocalMangaRepository @Inject constructor( list.retainAll { x -> x.containsTags(tags) } } when (sortOrder) { - SortOrder.ALPHABETICAL -> list.sortWith(compareBy(AlphanumComparator()) { x -> x.manga.title }) + SortOrder.ALPHABETICAL -> list.sortWith(compareBy(org.koitharu.kotatsu.core.util.AlphanumComparator()) { x -> x.manga.title }) SortOrder.RATING -> list.sortByDescending { it.manga.rating } SortOrder.NEWEST, SortOrder.UPDATED, diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt index b72f82200..6ff59f3a3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt @@ -10,7 +10,7 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.FragmentManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.databinding.DialogImportBinding import org.koitharu.kotatsu.settings.backup.BackupDialogFragment import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment @@ -27,7 +27,7 @@ class ImportDialogFragment : AlertDialogFragment(), View.On restoreBackup(it) } - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogImportBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): DialogImportBinding { return DialogImportBinding.inflate(inflater, container, false) } @@ -38,8 +38,8 @@ class ImportDialogFragment : AlertDialogFragment(), View.On .setCancelable(true) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogImportBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.buttonDir.setOnClickListener(this) binding.buttonFile.setOnClickListener(this) binding.buttonBackup.setOnClickListener(this) diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt index dc2af369a..fc719ae5b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt @@ -23,13 +23,13 @@ import coil.request.ImageRequest import dagger.assisted.Assisted import dagger.assisted.AssistedInject import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull +import org.koitharu.kotatsu.core.util.ext.toUriOrNull import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.local.data.importer.SingleMangaImporter import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.toBitmapOrNull -import org.koitharu.kotatsu.utils.ext.toUriOrNull @HiltWorker class ImportWorker @AssistedInject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt index e7606dfcf..d63ea1100 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt @@ -11,14 +11,14 @@ import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.MutableSharedFlow import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.CoroutineIntentService import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.ui.CoroutineIntentService +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt index 4d88b6663..d451b3936 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt @@ -12,18 +12,19 @@ import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.addMenuProvider class LocalListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener { override val viewModel by viewModels() - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) addMenuProvider(LocalListMenuProvider(this::onEmptyActionClick)) viewModel.onMangaRemoved.observe(viewLifecycleOwner) { onItemRemoved() } } @@ -34,7 +35,7 @@ class LocalListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener override fun onFilterClick(view: View?) { super.onFilterClick(view) - val menu = PopupMenu(requireContext(), view ?: binding.recyclerView) + val menu = PopupMenu(requireContext(), view ?: requireViewBinding().recyclerView) menu.inflate(R.menu.popup_order) menu.setOnMenuItemClickListener(this) menu.show() @@ -53,12 +54,14 @@ class LocalListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener showDeletionConfirm(selectedItemsIds, mode) true } + R.id.action_share -> { val files = selectedItems.map { it.url.toUri().toFile() } ShareHelper(requireContext()).shareCbz(files) mode.finish() true } + else -> super.onActionItemClicked(controller, mode, item) } } @@ -87,7 +90,7 @@ class LocalListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener } private fun onItemRemoved() { - Snackbar.make(binding.recyclerView, R.string.removal_completed, Snackbar.LENGTH_SHORT).show() + Snackbar.make(requireViewBinding().recyclerView, R.string.removal_completed, Snackbar.LENGTH_SHORT).show() } companion object { 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 d8c7b4967..0439423eb 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 @@ -14,9 +14,11 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.update import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE @@ -33,10 +35,8 @@ import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import java.io.IOException import java.util.LinkedList import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt index 8d66aee1b..0c912e54e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt @@ -6,8 +6,8 @@ import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.ViewCompat import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton -import org.koitharu.kotatsu.base.ui.util.ShrinkOnScrollBehavior -import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView +import org.koitharu.kotatsu.core.ui.util.ShrinkOnScrollBehavior +import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView class MainActionButtonBehavior : ShrinkOnScrollBehavior { diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt index e60500113..9f34e0c61 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -38,10 +38,17 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.os.VoiceInputContract import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView +import org.koitharu.kotatsu.core.util.ext.drawableEnd +import org.koitharu.kotatsu.core.util.ext.hideKeyboard +import org.koitharu.kotatsu.core.util.ext.resolve +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf +import org.koitharu.kotatsu.core.util.ext.setNavigationBarTransparentCompat +import org.koitharu.kotatsu.core.util.ext.tryLaunch import org.koitharu.kotatsu.databinding.ActivityMainBinding import org.koitharu.kotatsu.details.service.MangaPrefetchService import org.koitharu.kotatsu.details.ui.DetailsActivity @@ -62,13 +69,6 @@ import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment import org.koitharu.kotatsu.shelf.ui.ShelfFragment import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker import org.koitharu.kotatsu.tracker.work.TrackWorker -import org.koitharu.kotatsu.utils.VoiceInputContract -import org.koitharu.kotatsu.utils.ext.drawableEnd -import org.koitharu.kotatsu.utils.ext.hideKeyboard -import org.koitharu.kotatsu.utils.ext.resolve -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf -import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat -import org.koitharu.kotatsu.utils.ext.tryLaunch import javax.inject.Inject import com.google.android.material.R as materialR @@ -94,41 +94,42 @@ class MainActivity : private lateinit var navigationDelegate: MainNavigationDelegate override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override val bottomNav: SlidingBottomNavigationView? - get() = binding.bottomNav + get() = viewBinding.bottomNav override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(ActivityMainBinding.inflate(layoutInflater)) if (bottomNav != null) { - ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets -> + ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root) { _, insets -> if (insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom > 0) { val elevation = bottomNav?.elevation ?: 0f window.setNavigationBarTransparentCompat(this@MainActivity, elevation) } insets } - ViewCompat.requestApplyInsets(binding.root) + ViewCompat.requestApplyInsets(viewBinding.root) } - with(binding.searchView) { + with(viewBinding.searchView) { onFocusChangeListener = this@MainActivity searchSuggestionListener = this@MainActivity } window.statusBarColor = ContextCompat.getColor(this, R.color.dim_statusbar) - binding.fab?.setOnClickListener(this) - binding.navRail?.headerView?.setOnClickListener(this) - binding.searchView.isVoiceSearchEnabled = voiceInputLauncher.resolve(this, null) != null + viewBinding.fab?.setOnClickListener(this) + viewBinding.navRail?.headerView?.setOnClickListener(this) + viewBinding.searchView.isVoiceSearchEnabled = voiceInputLauncher.resolve(this, null) != null - navigationDelegate = MainNavigationDelegate(checkNotNull(bottomNav ?: binding.navRail), supportFragmentManager) + navigationDelegate = + MainNavigationDelegate(checkNotNull(bottomNav ?: viewBinding.navRail), supportFragmentManager) navigationDelegate.addOnFragmentChangedListener(this) navigationDelegate.onCreate(savedInstanceState) - onBackPressedDispatcher.addCallback(ExitCallback(this, binding.container)) + onBackPressedDispatcher.addCallback(ExitCallback(this, viewBinding.container)) onBackPressedDispatcher.addCallback(navigationDelegate) onBackPressedDispatcher.addCallback(closeSearchCallback) @@ -137,7 +138,7 @@ class MainActivity : } viewModel.onOpenReader.observe(this, this::onOpenReader) - viewModel.onError.observe(this, SnackbarErrorObserver(binding.container, null)) + viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.container, null)) viewModel.isLoading.observe(this, this::onLoadingStateChanged) viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged) viewModel.counters.observe(this, ::onCountersChanged) @@ -153,13 +154,13 @@ class MainActivity : override fun onFragmentChanged(fragment: Fragment, fromUser: Boolean) { adjustFabVisibility(topFragment = fragment) if (fromUser) { - binding.appbar.setExpanded(true) + viewBinding.appbar.setExpanded(true) } } override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home && !isSearchOpened()) { - binding.searchView.requestFocus() + viewBinding.searchView.requestFocus() return true } return super.onOptionsItemSelected(item) @@ -173,7 +174,7 @@ class MainActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) @@ -198,7 +199,7 @@ class MainActivity : } override fun onQueryClick(query: String, submit: Boolean) { - binding.searchView.query = query + viewBinding.searchView.query = query if (submit) { if (query.isNotEmpty()) { startActivity(MultiSearchActivity.newIntent(this, query)) @@ -216,16 +217,16 @@ class MainActivity : } override fun onVoiceSearchClick() { - val options = binding.searchView.drawableEnd?.bounds?.let { bounds -> + val options = viewBinding.searchView.drawableEnd?.bounds?.let { bounds -> ActivityOptionsCompat.makeScaleUpAnimation( - binding.searchView, + viewBinding.searchView, bounds.centerX(), bounds.centerY(), bounds.width(), bounds.height(), ) } - voiceInputLauncher.tryLaunch(binding.searchView.hint?.toString(), options) + voiceInputLauncher.tryLaunch(viewBinding.searchView.hint?.toString(), options) } override fun onSourceToggle(source: MangaSource, isEnabled: Boolean) { @@ -250,7 +251,7 @@ class MainActivity : } private fun onOpenReader(manga: Manga) { - val fab = binding.fab ?: binding.navRail?.headerView + val fab = viewBinding.fab ?: viewBinding.navRail?.headerView val options = fab?.let { scaleUpActivityOptionsOf(it).toBundle() } @@ -270,17 +271,17 @@ class MainActivity : } private fun onIncognitoModeChanged(isIncognito: Boolean) { - var options = binding.searchView.imeOptions + var options = viewBinding.searchView.imeOptions options = if (isIncognito) { options or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING } else { options and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() } - binding.searchView.imeOptions = options + viewBinding.searchView.imeOptions = options } private fun onLoadingStateChanged(isLoading: Boolean) { - binding.fab?.isEnabled = !isLoading + viewBinding.fab?.isEnabled = !isLoading } private fun onResumeEnabledChanged(isEnabled: Boolean) { @@ -293,7 +294,7 @@ class MainActivity : } private fun onSearchClosed() { - binding.searchView.hideKeyboard() + viewBinding.searchView.hideKeyboard() adjustSearchUI(isOpened = false, animate = true) closeSearchCallback.isEnabled = false } @@ -306,7 +307,7 @@ class MainActivity : hide() } } - binding.navRail?.isVisible = visible + viewBinding.navRail?.isVisible = visible } private fun isSearchOpened(): Boolean { @@ -341,7 +342,7 @@ class MainActivity : topFragment: Fragment? = navigationDelegate.primaryFragment, isSearchOpened: Boolean = isSearchOpened(), ) { - val fab = binding.fab ?: return + val fab = viewBinding.fab ?: return if ( isResumeEnabled && !actionModeDelegate.isActionModeStarted && @@ -360,22 +361,22 @@ class MainActivity : private fun adjustSearchUI(isOpened: Boolean, animate: Boolean) { if (animate) { - TransitionManager.beginDelayedTransition(binding.appbar) + TransitionManager.beginDelayedTransition(viewBinding.appbar) } val appBarScrollFlags = if (isOpened) { SCROLL_FLAG_NO_SCROLL } else { SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS or SCROLL_FLAG_SNAP } - binding.toolbarCard.updateLayoutParams { scrollFlags = appBarScrollFlags } - binding.insetsHolder.updateLayoutParams { scrollFlags = appBarScrollFlags } - binding.toolbarCard.background = if (isOpened) { + viewBinding.toolbarCard.updateLayoutParams { scrollFlags = appBarScrollFlags } + viewBinding.insetsHolder.updateLayoutParams { scrollFlags = appBarScrollFlags } + viewBinding.toolbarCard.background = if (isOpened) { null } else { ContextCompat.getDrawable(this, R.drawable.toolbar_background) } val padding = if (isOpened) 0 else resources.getDimensionPixelOffset(R.dimen.margin_normal) - binding.appbar.updatePadding(left = padding, right = padding) + viewBinding.appbar.updatePadding(left = padding, right = padding) adjustFabVisibility(isSearchOpened = isOpened) supportActionBar?.setHomeAsUpIndicator( if (isOpened) materialR.drawable.abc_ic_ab_back_material else materialR.drawable.abc_ic_search_api_material, @@ -396,7 +397,7 @@ class MainActivity : override fun onActivityResult(result: String?) { if (result != null) { - binding.searchView.query = result + viewBinding.searchView.query = result } } } @@ -405,7 +406,7 @@ class MainActivity : override fun handleOnBackPressed() { val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH) - binding.searchView.clearFocus() + viewBinding.searchView.clearFocus() if (fragment == null) { // this should not happen but who knows isEnabled = false diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt index 92d71241d..fe23e3cc2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt @@ -10,13 +10,13 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentTransaction import com.google.android.material.navigation.NavigationBarView import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled import org.koitharu.kotatsu.explore.ui.ExploreFragment import org.koitharu.kotatsu.settings.tools.ToolsFragment import org.koitharu.kotatsu.shelf.ui.ShelfFragment import org.koitharu.kotatsu.tracker.ui.feed.FeedFragment -import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled import java.util.LinkedList private const val TAG_PRIMARY = "primary" diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt index 054b4cf5a..f6482dce8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt @@ -7,17 +7,17 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt index 5174b97f4..ac6d1f0c6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.main.ui.owners -import org.koitharu.kotatsu.base.ui.widgets.SlidingBottomNavigationView +import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView interface BottomNavOwner { diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt index 78c4f29a2..e03f90ad2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.main.ui.owners -import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar +import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar interface NoModalBottomSheetOwner { diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt index 4d09d621a..8a9f8ed3c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt @@ -4,13 +4,14 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import org.acra.dialog.CrashReportDialog -import org.koitharu.kotatsu.base.ui.DefaultActivityLifecycleCallbacks import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.DefaultActivityLifecycleCallbacks import javax.inject.Inject import javax.inject.Singleton @Singleton -class AppProtectHelper @Inject constructor(private val settings: AppSettings) : DefaultActivityLifecycleCallbacks { +class AppProtectHelper @Inject constructor(private val settings: AppSettings) : + DefaultActivityLifecycleCallbacks { private var isUnlocked = settings.appPassword.isNullOrEmpty() diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt index d249c493a..a4a693cf5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt @@ -19,10 +19,10 @@ import androidx.biometric.BiometricPrompt.AuthenticationCallback import androidx.core.graphics.Insets import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.databinding.ActivityProtectBinding -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat @AndroidEntryPoint class ProtectActivity : @@ -37,10 +37,10 @@ class ProtectActivity : super.onCreate(savedInstanceState) window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) setContentView(ActivityProtectBinding.inflate(layoutInflater)) - binding.editPassword.setOnEditorActionListener(this) - binding.editPassword.addTextChangedListener(this) - binding.buttonNext.setOnClickListener(this) - binding.buttonCancel.setOnClickListener(this) + viewBinding.editPassword.setOnEditorActionListener(this) + viewBinding.editPassword.addTextChangedListener(this) + viewBinding.buttonNext.setOnClickListener(this) + viewBinding.buttonCancel.setOnClickListener(this) viewModel.onError.observe(this, this::onError) viewModel.isLoading.observe(this, this::onLoadingStateChanged) @@ -54,13 +54,13 @@ class ProtectActivity : override fun onStart() { super.onStart() if (!useFingerprint()) { - binding.editPassword.requestFocus() + viewBinding.editPassword.requestFocus() } } override fun onWindowInsetsChanged(insets: Insets) { val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding) - binding.root.setPadding( + viewBinding.root.setPadding( basePadding + insets.left, basePadding + insets.top, basePadding + insets.right, @@ -70,14 +70,14 @@ class ProtectActivity : override fun onClick(v: View) { when (v.id) { - R.id.button_next -> viewModel.tryUnlock(binding.editPassword.text?.toString().orEmpty()) + R.id.button_next -> viewModel.tryUnlock(viewBinding.editPassword.text?.toString().orEmpty()) R.id.button_cancel -> finish() } } override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean { - return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) { - binding.buttonNext.performClick() + return if (actionId == EditorInfo.IME_ACTION_DONE && viewBinding.buttonNext.isEnabled) { + viewBinding.buttonNext.performClick() true } else { false @@ -89,16 +89,16 @@ class ProtectActivity : override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit override fun afterTextChanged(s: Editable?) { - binding.layoutPassword.error = null - binding.buttonNext.isEnabled = !s.isNullOrEmpty() + viewBinding.layoutPassword.error = null + viewBinding.buttonNext.isEnabled = !s.isNullOrEmpty() } private fun onError(e: Throwable) { - binding.layoutPassword.error = e.getDisplayMessage(resources) + viewBinding.layoutPassword.error = e.getDisplayMessage(resources) } private fun onLoadingStateChanged(isLoading: Boolean) { - binding.layoutPassword.isEnabled = !isLoading + viewBinding.layoutPassword.isEnabled = !isLoading } private fun useFingerprint(): Boolean { diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt index a55d15c84..e530a2a7d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt @@ -1,14 +1,14 @@ package org.koitharu.kotatsu.main.ui.protect import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import kotlinx.coroutines.Job import kotlinx.coroutines.delay -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.exceptions.WrongPasswordException import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent import org.koitharu.kotatsu.parsers.util.md5 -import org.koitharu.kotatsu.utils.SingleLiveEvent +import javax.inject.Inject private const val PASSWORD_COMPARE_DELAY = 1_000L diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt index e4f5c1269..d59ee6788 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -25,16 +25,16 @@ import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope +import org.koitharu.kotatsu.core.util.ext.withProgress +import org.koitharu.kotatsu.core.util.progress.ProgressDeferred import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -import org.koitharu.kotatsu.utils.RetainedLifecycleCoroutineScope -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.withProgress -import org.koitharu.kotatsu.utils.progress.ProgressDeferred +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import java.util.LinkedList import java.util.concurrent.atomic.AtomicInteger diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt index 87b92acd5..29caaca0a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt @@ -7,18 +7,18 @@ import android.view.ViewGroup import androidx.fragment.app.FragmentManager import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaChapters import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback +import org.koitharu.kotatsu.core.util.ext.getParcelableCompat +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetChaptersBinding import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.toListItem import org.koitharu.kotatsu.parsers.model.MangaChapter -import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback -import org.koitharu.kotatsu.utils.ext.getParcelableCompat -import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject import kotlin.math.roundToInt @@ -28,12 +28,12 @@ class ChaptersBottomSheet : BaseBottomSheet(), OnListItemC @Inject lateinit var settings: AppSettings - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetChaptersBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetChaptersBinding { return SheetChaptersBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetChaptersBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val chapters = arguments?.getParcelableCompat(ARG_CHAPTERS)?.chapters if (chapters.isNullOrEmpty()) { dismissAllowingStateLoss() diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt index 9f89886e9..d8382a543 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt @@ -15,11 +15,11 @@ import okio.IOException import okio.buffer import okio.sink import okio.source -import org.koitharu.kotatsu.base.domain.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.toFileNameSafe import org.koitharu.kotatsu.reader.domain.PageLoader -import org.koitharu.kotatsu.utils.ext.writeAllCancellable import java.io.File import javax.inject.Inject import kotlin.coroutines.Continuation diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index b3deab1df..3fff9ab9a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -30,13 +30,21 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent -import org.koitharu.kotatsu.base.ui.BaseFullscreenActivity import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.core.exceptions.resolve.DialogErrorObserver import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity +import org.koitharu.kotatsu.core.util.GridTouchHelper +import org.koitharu.kotatsu.core.util.IdlingDetector +import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.hasGlobalPoint +import org.koitharu.kotatsu.core.util.ext.isRtl +import org.koitharu.kotatsu.core.util.ext.observeWithPrevious +import org.koitharu.kotatsu.core.util.ext.postDelayed +import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.databinding.ActivityReaderBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter @@ -46,14 +54,6 @@ import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState import org.koitharu.kotatsu.reader.ui.thumbnails.OnPageSelectListener import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet import org.koitharu.kotatsu.settings.SettingsActivity -import org.koitharu.kotatsu.utils.GridTouchHelper -import org.koitharu.kotatsu.utils.IdlingDetector -import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.hasGlobalPoint -import org.koitharu.kotatsu.utils.ext.isRtl -import org.koitharu.kotatsu.utils.ext.observeWithPrevious -import org.koitharu.kotatsu.utils.ext.postDelayed -import org.koitharu.kotatsu.utils.ext.setValueRounded import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -102,16 +102,16 @@ class ReaderActivity : touchHelper = GridTouchHelper(this, this) scrollTimer = scrollTimerFactory.create(this, this) controlDelegate = ReaderControlDelegate(settings, this, this) - binding.toolbarBottom.setOnMenuItemClickListener(::onOptionsItemSelected) - binding.slider.setLabelFormatter(PageLabelFormatter()) - ReaderSliderListener(this, viewModel).attachToSlider(binding.slider) + viewBinding.toolbarBottom.setOnMenuItemClickListener(::onOptionsItemSelected) + viewBinding.slider.setLabelFormatter(PageLabelFormatter()) + ReaderSliderListener(this, viewModel).attachToSlider(viewBinding.slider) insetsDelegate.interceptingWindowInsetsListener = this idlingDetector.bindToLifecycle(this) viewModel.onError.observe( this, DialogErrorObserver( - host = binding.container, + host = viewBinding.container, fragment = null, resolver = exceptionResolver, onResolved = { isResolved -> @@ -134,8 +134,8 @@ class ReaderActivity : viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged) viewModel.isBookmarkAdded.observe(this, this::onBookmarkStateChanged) viewModel.onShowToast.observe(this) { msgId -> - Snackbar.make(binding.container, msgId, Snackbar.LENGTH_SHORT) - .setAnchorView(binding.appbarBottom) + Snackbar.make(viewBinding.container, msgId, Snackbar.LENGTH_SHORT) + .setAnchorView(viewBinding.appbarBottom) .show() } } @@ -154,10 +154,10 @@ class ReaderActivity : if (readerManager.currentMode != mode) { readerManager.replace(mode) } - if (binding.appbarTop.isVisible) { + if (viewBinding.appbarTop.isVisible) { lifecycle.postDelayed(hideUiRunnable, TimeUnit.SECONDS.toMillis(1)) } - binding.slider.isRtl = mode == ReaderMode.REVERSED + viewBinding.slider.isRtl = mode == ReaderMode.REVERSED } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -210,29 +210,29 @@ class ReaderActivity : private fun onLoadingStateChanged(isLoading: Boolean) { val hasPages = !viewModel.content.value?.pages.isNullOrEmpty() - binding.layoutLoading.isVisible = isLoading && !hasPages + viewBinding.layoutLoading.isVisible = isLoading && !hasPages if (isLoading && hasPages) { - binding.toastView.show(R.string.loading_) + viewBinding.toastView.show(R.string.loading_) } else { - binding.toastView.hide() + viewBinding.toastView.hide() } - val menu = binding.toolbarBottom.menu + val menu = viewBinding.toolbarBottom.menu menu.findItem(R.id.action_bookmark).isVisible = hasPages menu.findItem(R.id.action_pages_thumbs).isVisible = hasPages } override fun onGridTouch(area: Int) { - controlDelegate.onGridTouch(area, binding.container) + controlDelegate.onGridTouch(area, viewBinding.container) } override fun onProcessTouch(rawX: Int, rawY: Int): Boolean { return if ( rawX <= gestureInsets.left || rawY <= gestureInsets.top || - rawX >= binding.root.width - gestureInsets.right || - rawY >= binding.root.height - gestureInsets.bottom || - binding.appbarTop.hasGlobalPoint(rawX, rawY) || - binding.appbarBottom?.hasGlobalPoint(rawX, rawY) == true + rawX >= viewBinding.root.width - gestureInsets.right || + rawY >= viewBinding.root.height - gestureInsets.bottom || + viewBinding.appbarTop.hasGlobalPoint(rawX, rawY) || + viewBinding.appbarBottom?.hasGlobalPoint(rawX, rawY) == true ) { false } else { @@ -279,14 +279,14 @@ class ReaderActivity : private fun onPageSaved(uri: Uri?) { if (uri != null) { - Snackbar.make(binding.container, R.string.page_saved, Snackbar.LENGTH_LONG) - .setAnchorView(binding.appbarBottom) + Snackbar.make(viewBinding.container, R.string.page_saved, Snackbar.LENGTH_LONG) + .setAnchorView(viewBinding.appbarBottom) .setAction(R.string.share) { ShareHelper(this).shareImage(uri) }.show() } else { - Snackbar.make(binding.container, R.string.error_occurred, Snackbar.LENGTH_SHORT) - .setAnchorView(binding.appbarBottom) + Snackbar.make(viewBinding.container, R.string.error_occurred, Snackbar.LENGTH_SHORT) + .setAnchorView(viewBinding.appbarBottom) .show() } } @@ -300,18 +300,18 @@ class ReaderActivity : } private fun setUiIsVisible(isUiVisible: Boolean) { - if (binding.appbarTop.isVisible != isUiVisible) { + if (viewBinding.appbarTop.isVisible != isUiVisible) { val transition = TransitionSet() .setOrdering(TransitionSet.ORDERING_TOGETHER) - .addTransition(Slide(Gravity.TOP).addTarget(binding.appbarTop)) - .addTransition(Fade().addTarget(binding.infoBar)) - binding.appbarBottom?.let { bottomBar -> + .addTransition(Slide(Gravity.TOP).addTarget(viewBinding.appbarTop)) + .addTransition(Fade().addTarget(viewBinding.infoBar)) + viewBinding.appbarBottom?.let { bottomBar -> transition.addTransition(Slide(Gravity.BOTTOM).addTarget(bottomBar)) } - TransitionManager.beginDelayedTransition(binding.root, transition) - binding.appbarTop.isVisible = isUiVisible - binding.appbarBottom?.isVisible = isUiVisible - binding.infoBar.isGone = isUiVisible || (viewModel.isInfoBarEnabled.value == false) + TransitionManager.beginDelayedTransition(viewBinding.root, transition) + viewBinding.appbarTop.isVisible = isUiVisible + viewBinding.appbarBottom?.isVisible = isUiVisible + viewBinding.infoBar.isGone = isUiVisible || (viewModel.isInfoBarEnabled.value == false) if (isUiVisible) { showSystemUI() } else { @@ -323,12 +323,12 @@ class ReaderActivity : override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat { gestureInsets = insets.getInsets(WindowInsetsCompat.Type.systemGestures()) val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - binding.appbarTop.updatePadding( + viewBinding.appbarTop.updatePadding( top = systemBars.top, right = systemBars.right, left = systemBars.left, ) - binding.appbarBottom?.updatePadding( + viewBinding.appbarBottom?.updatePadding( bottom = systemBars.bottom, right = systemBars.right, left = systemBars.left, @@ -349,7 +349,7 @@ class ReaderActivity : } override fun toggleUiVisibility() { - setUiIsVisible(!binding.appbarTop.isVisible) + setUiIsVisible(!viewBinding.appbarTop.isVisible) } override fun isReaderResumed(): Boolean { @@ -358,21 +358,21 @@ class ReaderActivity : } private fun onReaderBarChanged(isBarEnabled: Boolean) { - binding.infoBar.isVisible = isBarEnabled && binding.appbarTop.isGone + viewBinding.infoBar.isVisible = isBarEnabled && viewBinding.appbarTop.isGone } private fun onBookmarkStateChanged(isAdded: Boolean) { - val menuItem = binding.toolbarBottom.menu.findItem(R.id.action_bookmark) ?: return + val menuItem = viewBinding.toolbarBottom.menu.findItem(R.id.action_bookmark) ?: return menuItem.setTitle(if (isAdded) R.string.bookmark_remove else R.string.bookmark_add) menuItem.setIcon(if (isAdded) R.drawable.ic_bookmark_added else R.drawable.ic_bookmark) } private fun onUiStateChanged(uiState: ReaderUiState?, previous: ReaderUiState?) { title = uiState?.chapterName ?: uiState?.mangaName ?: getString(R.string.loading_) - binding.infoBar.update(uiState) + viewBinding.infoBar.update(uiState) if (uiState == null) { supportActionBar?.subtitle = null - binding.slider.isVisible = false + viewBinding.slider.isVisible = false return } supportActionBar?.subtitle = if (uiState.chapterNumber in 1..uiState.chaptersTotal) { @@ -382,15 +382,15 @@ class ReaderActivity : } if (previous?.chapterName != null && uiState.chapterName != previous.chapterName) { if (!uiState.chapterName.isNullOrEmpty()) { - binding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) + viewBinding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) } } if (uiState.isSliderAvailable()) { - binding.slider.valueTo = uiState.totalPages.toFloat() - 1 - binding.slider.setValueRounded(uiState.currentPage.toFloat()) - binding.slider.isVisible = true + viewBinding.slider.valueTo = uiState.totalPages.toFloat() - 1 + viewBinding.slider.setValueRounded(uiState.currentPage.toFloat()) + viewBinding.slider.isVisible = true } else { - binding.slider.isVisible = false + viewBinding.slider.isVisible = false } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt index 3791ac5c4..62c6cd431 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode -import org.koitharu.kotatsu.utils.GridTouchHelper +import org.koitharu.kotatsu.core.util.GridTouchHelper class ReaderControlDelegate( private val settings: AppSettings, diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt index f4fd28289..7c2eb733a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt @@ -17,12 +17,12 @@ import androidx.core.graphics.ColorUtils import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.measureDimension +import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState -import org.koitharu.kotatsu.utils.ext.getThemeColor -import org.koitharu.kotatsu.utils.ext.measureDimension -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.resolveDp +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.text.SimpleDateFormat import java.util.Date import com.google.android.material.R as materialR diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index c4d6bdc5b..f092a5c06 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -31,36 +31,36 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository -import org.koitharu.kotatsu.base.domain.MangaIntent -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository import org.koitharu.kotatsu.core.os.ShortcutsUpdater +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ScreenshotsPolicy import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.reader.data.filterChapters import org.koitharu.kotatsu.reader.domain.ChaptersLoader import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.emitValue -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.processLifecycleScope -import org.koitharu.kotatsu.utils.ext.requireValue -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.Date import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt index 471ade52d..02a6b00ea 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt @@ -18,18 +18,18 @@ import com.google.android.material.slider.LabelFormatter import com.google.android.material.slider.Slider import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.decodeRegion +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.indicator +import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.reader.domain.ReaderColorFilter -import org.koitharu.kotatsu.utils.ext.decodeRegion -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.indicator -import org.koitharu.kotatsu.utils.ext.setValueRounded import javax.inject.Inject import com.google.android.material.R as materialR @@ -51,13 +51,13 @@ class ColorFilterConfigActivity : setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } - binding.sliderBrightness.addOnChangeListener(this) - binding.sliderContrast.addOnChangeListener(this) + viewBinding.sliderBrightness.addOnChangeListener(this) + viewBinding.sliderContrast.addOnChangeListener(this) val formatter = PercentLabelFormatter(resources) - binding.sliderContrast.setLabelFormatter(formatter) - binding.sliderBrightness.setLabelFormatter(formatter) - binding.buttonDone.setOnClickListener(this) - binding.buttonReset.setOnClickListener(this) + viewBinding.sliderContrast.setLabelFormatter(formatter) + viewBinding.sliderBrightness.setLabelFormatter(formatter) + viewBinding.buttonDone.setOnClickListener(this) + viewBinding.buttonReset.setOnClickListener(this) onBackPressedDispatcher.addCallback(ColorFilterConfigBackPressedDispatcher(this, viewModel)) @@ -86,22 +86,22 @@ class ColorFilterConfigActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) - binding.scrollView.updatePadding( + viewBinding.scrollView.updatePadding( bottom = insets.bottom, ) - binding.toolbar.updateLayoutParams { + viewBinding.toolbar.updateLayoutParams { topMargin = insets.top } } private fun onColorFilterChanged(readerColorFilter: ReaderColorFilter?) { - binding.sliderBrightness.setValueRounded(readerColorFilter?.brightness ?: 0f) - binding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f) - binding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter() + viewBinding.sliderBrightness.setValueRounded(readerColorFilter?.brightness ?: 0f) + viewBinding.sliderContrast.setValueRounded(readerColorFilter?.contrast ?: 0f) + viewBinding.imageViewAfter.colorFilter = readerColorFilter?.toColorFilter() } private fun onPreviewChanged(preview: MangaPage?) { @@ -111,18 +111,18 @@ class ColorFilterConfigActivity : .scale(Scale.FILL) .decodeRegion() .tag(preview.source) - .indicator(listOf(binding.progressBefore, binding.progressAfter)) + .indicator(listOf(viewBinding.progressBefore, viewBinding.progressAfter)) .error(R.drawable.ic_error_placeholder) - .size(ViewSizeResolver(binding.imageViewBefore)) + .size(ViewSizeResolver(viewBinding.imageViewBefore)) .allowRgb565(false) - .target(ShadowViewTarget(binding.imageViewBefore, binding.imageViewAfter)) + .target(ShadowViewTarget(viewBinding.imageViewBefore, viewBinding.imageViewAfter)) .enqueueWith(coil) } private fun onLoadingChanged(isLoading: Boolean) { - binding.sliderContrast.isEnabled = !isLoading - binding.sliderBrightness.isEnabled = !isLoading - binding.buttonDone.isEnabled = !isLoading + viewBinding.sliderContrast.isEnabled = !isLoading + viewBinding.sliderBrightness.isEnabled = !isLoading + viewBinding.buttonDone.isEnabled = !isLoading } private class PercentLabelFormatter(resources: Resources) : LabelFormatter { diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt index d5b3e517f..22ef8497b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt @@ -4,16 +4,16 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers -import org.koitharu.kotatsu.base.domain.MangaDataRepository -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.domain.ReaderColorFilter import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity.Companion.EXTRA_MANGA -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.emitValue import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt index 51c55af04..d83552079 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt @@ -19,18 +19,18 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.util.ScreenOrientationHelper +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetReaderConfigBinding import org.koitharu.kotatsu.reader.ui.PageSaveContract import org.koitharu.kotatsu.reader.ui.ReaderViewModel import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity import org.koitharu.kotatsu.settings.SettingsActivity -import org.koitharu.kotatsu.utils.ScreenOrientationHelper -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope -import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @AndroidEntryPoint @@ -56,12 +56,12 @@ class ReaderConfigBottomSheet : ?: ReaderMode.STANDARD } - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetReaderConfigBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetReaderConfigBinding { return SheetReaderConfigBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetReaderConfigBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) observeScreenOrientation() binding.buttonStandard.isChecked = mode == ReaderMode.STANDARD binding.buttonReversed.isChecked = mode == ReaderMode.REVERSED @@ -118,8 +118,8 @@ class ReaderConfigBottomSheet : when (buttonView.id) { R.id.switch_scroll_timer -> { findCallback()?.isAutoScrollEnabled = isChecked - binding.labelTimer.isVisible = isChecked - binding.sliderTimer.isVisible = isChecked + requireViewBinding().labelTimer.isVisible = isChecked + requireViewBinding().sliderTimer.isVisible = isChecked } } } @@ -157,7 +157,7 @@ class ReaderConfigBottomSheet : orientationHelper = helper helper.observeAutoOrientation() .onEach { - binding.buttonScreenRotate.isGone = it + requireViewBinding().buttonScreenRotate.isGone = it }.launchIn(viewLifecycleScope) } 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 3ab378cec..7a289cbdf 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,9 +6,9 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.ext.resetTransformations import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings -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/BaseReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt index 954c866c8..7570a9f5c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt @@ -1,14 +1,13 @@ package org.koitharu.kotatsu.reader.ui.pager import android.os.Bundle -import android.view.View import androidx.core.graphics.Insets import androidx.fragment.app.activityViewModels import androidx.viewbinding.ViewBinding -import org.koitharu.kotatsu.base.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.util.ext.getParcelableCompat import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderViewModel -import org.koitharu.kotatsu.utils.ext.getParcelableCompat private const val KEY_STATE = "state" @@ -17,8 +16,8 @@ abstract class BaseReaderFragment : BaseFragment() { protected val viewModel by activityViewModels() private var stateToSave: ReaderState? = null - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) var restoredState = savedInstanceState?.getParcelableCompat(KEY_STATE) viewModel.content.observe(viewLifecycleOwner) { 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 a517f630a..21a0f4f41 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 @@ -21,7 +21,7 @@ import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import java.io.IOException diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt index 5bf30b8a5..016a7436f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt @@ -1,15 +1,18 @@ package org.koitharu.kotatsu.reader.ui.pager.reversed -import android.annotation.SuppressLint import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.view.children import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.async import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.ext.doOnPageChanged +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.recyclerView +import org.koitharu.kotatsu.core.util.ext.resetTransformations +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.ReaderState @@ -17,11 +20,6 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderFragment import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import org.koitharu.kotatsu.reader.ui.pager.standard.PagerReaderFragment -import org.koitharu.kotatsu.utils.ext.doOnPageChanged -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled -import org.koitharu.kotatsu.utils.ext.recyclerView -import org.koitharu.kotatsu.utils.ext.resetTransformations -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import javax.inject.Inject import kotlin.math.absoluteValue @@ -36,14 +34,13 @@ class ReversedReaderFragment : BaseReaderFragment private var pagerAdapter: ReversedPagesAdapter? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentReaderStandardBinding.inflate(inflater, container, false) - @SuppressLint("NotifyDataSetChanged") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentReaderStandardBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) pagerAdapter = ReversedPagesAdapter( lifecycleOwner = viewLifecycleOwner, loader = pageLoader, @@ -70,18 +67,18 @@ class ReversedReaderFragment : BaseReaderFragment override fun onDestroyView() { pagerAdapter = null - binding.pager.adapter = null + requireViewBinding().pager.adapter = null super.onDestroyView() } override fun switchPageBy(delta: Int) { - with(binding.pager) { + with(requireViewBinding().pager) { setCurrentItem(currentItem - delta, context.isAnimationsEnabled) } } override fun switchPageTo(position: Int, smooth: Boolean) { - with(binding.pager) { + with(requireViewBinding().pager) { setCurrentItem( reversed(position), smooth && context.isAnimationsEnabled && (currentItem - position).absoluteValue < PagerReaderFragment.SMOOTH_SCROLL_LIMIT, @@ -101,7 +98,7 @@ class ReversedReaderFragment : BaseReaderFragment } items.await() ?: return@launch if (position != -1) { - binding.pager.setCurrentItem(position, false) + requireViewBinding().pager.setCurrentItem(position, false) notifyPageChanged(position) } } else { @@ -110,7 +107,7 @@ class ReversedReaderFragment : BaseReaderFragment } } - override fun getCurrentState(): ReaderState? = bindingOrNull()?.run { + override fun getCurrentState(): ReaderState? = viewBinding?.run { val adapter = pager.adapter as? BaseReaderAdapter<*> val page = adapter?.getItemOrNull(pager.currentItem) ?: return@run null ReaderState( 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 6d8076baf..eb5927fb1 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,12 +12,15 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.ifZero +import org.koitharu.kotatsu.core.util.ext.isLowRamDevice import org.koitharu.kotatsu.databinding.ItemPageBinding import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings import org.koitharu.kotatsu.reader.ui.pager.BasePageHolder import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -import org.koitharu.kotatsu.utils.ext.* +import org.koitharu.kotatsu.util.ext.* open class PageHolder( owner: LifecycleOwner, @@ -31,7 +34,7 @@ open class PageHolder( init { binding.ssiv.bindToLifecycle(owner) - binding.ssiv.isEagerLoadingEnabled = !isLowRamDevice(context) + binding.ssiv.isEagerLoadingEnabled = !context.isLowRamDevice() binding.ssiv.addOnImageEventListener(delegate) @Suppress("LeakingThis") bindingInfo.buttonRetry.setOnClickListener(this) diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt index 75462cfb0..19815597b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt @@ -1,26 +1,24 @@ package org.koitharu.kotatsu.reader.ui.pager.standard -import android.annotation.SuppressLint import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.view.children import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.async import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.ext.doOnPageChanged +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.recyclerView +import org.koitharu.kotatsu.core.util.ext.resetTransformations +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderFragment import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -import org.koitharu.kotatsu.utils.ext.doOnPageChanged -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled -import org.koitharu.kotatsu.utils.ext.recyclerView -import org.koitharu.kotatsu.utils.ext.resetTransformations -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import javax.inject.Inject import kotlin.math.absoluteValue @@ -35,14 +33,13 @@ class PagerReaderFragment : BaseReaderFragment() private var pagesAdapter: PagesAdapter? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentReaderStandardBinding.inflate(inflater, container, false) - @SuppressLint("NotifyDataSetChanged") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentReaderStandardBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) pagesAdapter = PagesAdapter( lifecycleOwner = viewLifecycleOwner, loader = pageLoader, @@ -69,7 +66,7 @@ class PagerReaderFragment : BaseReaderFragment() override fun onDestroyView() { pagesAdapter = null - binding.pager.adapter = null + requireViewBinding().pager.adapter = null super.onDestroyView() } @@ -84,7 +81,7 @@ class PagerReaderFragment : BaseReaderFragment() } items.await() ?: return@launch if (position != -1) { - binding.pager.setCurrentItem(position, false) + requireViewBinding().pager.setCurrentItem(position, false) notifyPageChanged(position) } } else { @@ -94,13 +91,13 @@ class PagerReaderFragment : BaseReaderFragment() } override fun switchPageBy(delta: Int) { - with(binding.pager) { + with(requireViewBinding().pager) { setCurrentItem(currentItem + delta, context.isAnimationsEnabled) } } override fun switchPageTo(position: Int, smooth: Boolean) { - with(binding.pager) { + with(requireViewBinding().pager) { setCurrentItem( position, smooth && context.isAnimationsEnabled && (currentItem - position).absoluteValue < SMOOTH_SCROLL_LIMIT, @@ -108,7 +105,7 @@ class PagerReaderFragment : BaseReaderFragment() } } - override fun getCurrentState(): ReaderState? = bindingOrNull()?.run { + override fun getCurrentState(): ReaderState? = viewBinding?.run { val adapter = pager.adapter as? BaseReaderAdapter<*> val page = adapter?.getItemOrNull(pager.currentItem) ?: return@run null ReaderState( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt index 1301a96b0..f5a936ad6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt @@ -10,14 +10,14 @@ import com.davemorrissey.labs.subscaleview.decoder.SkiaPooledImageRegionDecoder import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.GoneOnInvisibleListener +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.ifZero import org.koitharu.kotatsu.databinding.ItemPageWebtoonBinding import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings import org.koitharu.kotatsu.reader.ui.pager.BasePageHolder import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -import org.koitharu.kotatsu.utils.GoneOnInvisibleListener -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.ifZero class WebtoonHolder( owner: LifecycleOwner, diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt index 55aa6540a..d27a05669 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt @@ -5,8 +5,8 @@ import android.graphics.PointF import android.util.AttributeSet import androidx.recyclerview.widget.RecyclerView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView +import org.koitharu.kotatsu.core.util.ext.parents import org.koitharu.kotatsu.parsers.util.toIntUp -import org.koitharu.kotatsu.utils.ext.parents private const val SCROLL_UNKNOWN = -1 diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt index e836c7fd0..b8f2eac37 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt @@ -2,23 +2,22 @@ package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.view.animation.AccelerateDecelerateInterpolator import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.async import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition +import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition +import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter import org.koitharu.kotatsu.reader.ui.pager.BaseReaderFragment import org.koitharu.kotatsu.reader.ui.pager.ReaderPage -import org.koitharu.kotatsu.utils.ext.findCenterViewPosition -import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition -import org.koitharu.kotatsu.utils.ext.isAnimationsEnabled -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import javax.inject.Inject @AndroidEntryPoint @@ -33,13 +32,13 @@ class WebtoonReaderFragment : BaseReaderFragment() private val scrollInterpolator = AccelerateDecelerateInterpolator() private var webtoonAdapter: WebtoonAdapter? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentReaderWebtoonBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentReaderWebtoonBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) webtoonAdapter = WebtoonAdapter( lifecycleOwner = viewLifecycleOwner, loader = pageLoader, @@ -60,7 +59,7 @@ class WebtoonReaderFragment : BaseReaderFragment() override fun onDestroyView() { webtoonAdapter = null - binding.recyclerView.adapter = null + requireViewBinding().recyclerView.adapter = null super.onDestroyView() } @@ -73,7 +72,7 @@ class WebtoonReaderFragment : BaseReaderFragment() } setItems.await() ?: return@launch if (position != -1) { - with(binding.recyclerView) { + with(requireViewBinding().recyclerView) { firstVisibleItemPosition = position post { (findViewHolderForAdapterPosition(position) as? WebtoonHolder) @@ -88,7 +87,7 @@ class WebtoonReaderFragment : BaseReaderFragment() } } - override fun getCurrentState(): ReaderState? = bindingOrNull()?.run { + override fun getCurrentState(): ReaderState? = viewBinding?.run { val currentItem = recyclerView.findCenterViewPosition() val adapter = recyclerView.adapter as? BaseReaderAdapter<*> val page = adapter?.getItemOrNull(currentItem) ?: return@run null @@ -105,7 +104,7 @@ class WebtoonReaderFragment : BaseReaderFragment() } override fun switchPageBy(delta: Int) { - with(binding.recyclerView) { + with(requireViewBinding().recyclerView) { if (context.isAnimationsEnabled) { smoothScrollBy(0, (height * 0.9).toInt() * delta, scrollInterpolator) } else { @@ -115,11 +114,11 @@ class WebtoonReaderFragment : BaseReaderFragment() } override fun switchPageTo(position: Int, smooth: Boolean) { - binding.recyclerView.firstVisibleItemPosition = position + requireViewBinding().recyclerView.firstVisibleItemPosition = position } override fun scrollBy(delta: Int): Boolean { - binding.recyclerView.nestedScrollBy(0, delta) + requireViewBinding().recyclerView.nestedScrollBy(0, delta) return true } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt index aa28971af..2a0acaee3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt @@ -4,8 +4,8 @@ import android.content.Context import android.util.AttributeSet import androidx.core.view.ViewCompat.TYPE_TOUCH import androidx.recyclerview.widget.RecyclerView -import org.koitharu.kotatsu.utils.ext.findCenterViewPosition -import java.util.* +import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition +import java.util.LinkedList class WebtoonRecyclerView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 @@ -60,6 +60,7 @@ class WebtoonRecyclerView @JvmOverloads constructor( } return consumedByChild } + dy < 0 -> { val child = getChildAt(childCount - 1) as WebtoonFrameLayout var consumedByChild = child.dispatchVerticalScroll(dy) @@ -113,4 +114,4 @@ class WebtoonRecyclerView @JvmOverloads constructor( open fun onPageChanged(recyclerView: WebtoonRecyclerView, index: Int) = Unit } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index 80aee22e9..b4fe13b2f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -11,15 +11,17 @@ import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.list.BoundsScrollListener -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.ScrollListenerInvalidationObserver -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration -import org.koitharu.kotatsu.base.ui.widgets.BottomSheetHeaderBar import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.list.BoundsScrollListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.ScrollListenerInvalidationObserver +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetPagesBinding import org.koitharu.kotatsu.list.ui.MangaListSpanResolver import org.koitharu.kotatsu.parsers.model.Manga @@ -27,9 +29,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.TargetScrollObserver -import org.koitharu.kotatsu.utils.LoggingAdapterDataObserver -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf -import org.koitharu.kotatsu.utils.ext.withArgs +import org.koitharu.kotatsu.util.LoggingAdapterDataObserver import javax.inject.Inject @AndroidEntryPoint @@ -55,13 +55,13 @@ class PagesThumbnailsSheet : spanSizeLookup.invalidateCache() } - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetPagesBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetPagesBinding { return SheetPagesBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - spanResolver = MangaListSpanResolver(view.resources) + override fun onViewBindingCreated(binding: SheetPagesBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) + spanResolver = MangaListSpanResolver(binding.root.resources) with(binding.headerBar) { title = viewModel.title subtitle = null @@ -143,8 +143,7 @@ class PagesThumbnailsSheet : } override fun getSpanSize(position: Int): Int { - val total = - (binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1 + val total = (viewBinding?.recyclerView?.layoutManager as? GridLayoutManager)?.spanCount ?: return 1 return when (thumbnailsAdapter?.getItemViewType(position)) { PageThumbnailAdapter.ITEM_TYPE_THUMBNAIL -> 1 else -> total diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt index 00401578b..bf9e86070 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -5,16 +5,16 @@ import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.parsers.util.SuspendLazy import org.koitharu.kotatsu.reader.data.filterChapters import org.koitharu.kotatsu.reader.domain.ChaptersLoader -import org.koitharu.kotatsu.utils.ext.emitValue import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt index 3ec91573f..62ab44cb9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt @@ -6,17 +6,17 @@ import coil.size.Scale import coil.size.Size import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.decodeRegion +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.setTextColorAttr +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemPageThumbBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail -import org.koitharu.kotatsu.utils.ext.decodeRegion -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.setTextColorAttr -import org.koitharu.kotatsu.utils.ext.source import com.google.android.material.R as materialR fun pageThumbnailAD( diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt index 4fffe12e3..e1169638a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.list.ui.adapter.listHeaderAD import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.model.ListHeader diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt index e597c90a5..c441f6974 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt @@ -11,23 +11,24 @@ import androidx.core.view.MenuProvider import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.withArgs +import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.list.ui.filter.FilterBottomSheet import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.settings.SettingsActivity -import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class RemoteListFragment : MangaListFragment() { public override val viewModel by viewModels() - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) addMenuProvider(RemoteListMenuProvider()) } diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index 6601551db..a7a1fb73d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -15,12 +15,14 @@ import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaDataRepository -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.filter.FilterCoordinator @@ -38,9 +40,7 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.search.domain.MangaSearchRepository -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.require +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.LinkedList import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt index 2683d01b4..1d4e04c41 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.scrobbling.anilist.data -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug enum class ScoreFormat { diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt index 5eb3ebec7..3cd124561 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt @@ -10,7 +10,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.util.ext.findKeyByValue import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo @@ -18,9 +20,7 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus -import org.koitharu.kotatsu.utils.ext.findKeyByValue -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.EnumMap abstract class Scrobbler( @@ -53,7 +53,7 @@ abstract class Scrobbler( return repository.loadUser() } - suspend fun logout() { + fun logout() { repository.logout() } diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt index ccfcc2186..4cc7c0963 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt @@ -12,10 +12,13 @@ import coil.ImageLoader import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService @@ -23,9 +26,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.ui.config.adapter.ScrobblingMangaAdapter import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest import javax.inject.Inject @AndroidEntryPoint @@ -47,7 +47,7 @@ class ScrobblerConfigActivity : BaseActivity(), supportActionBar?.setDisplayHomeAsUpEnabled(true) val listAdapter = ScrobblingMangaAdapter(this, coil, this) - with(binding.recyclerView) { + with(viewBinding.recyclerView) { adapter = listAdapter setHasFixedSize(true) val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing) @@ -59,12 +59,12 @@ class ScrobblerConfigActivity : BaseActivity(), ) addItemDecoration(decoration) } - binding.imageViewAvatar.setOnClickListener(this) + viewBinding.imageViewAvatar.setOnClickListener(this) viewModel.content.observe(this, listAdapter::setItems) viewModel.user.observe(this, this::onUserChanged) viewModel.isLoading.observe(this, this::onLoadingStateChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null)) + viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.onLoggedOut.observe(this) { finishAfterTransition() } @@ -81,7 +81,7 @@ class ScrobblerConfigActivity : BaseActivity(), } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( left = insets.left + paddingHorizontal, right = insets.right + paddingHorizontal, bottom = insets.bottom + paddingVertical, @@ -112,17 +112,17 @@ class ScrobblerConfigActivity : BaseActivity(), private fun onUserChanged(user: ScrobblerUser?) { if (user == null) { - binding.imageViewAvatar.disposeImageRequest() - binding.imageViewAvatar.isVisible = false + viewBinding.imageViewAvatar.disposeImageRequest() + viewBinding.imageViewAvatar.isVisible = false return } - binding.imageViewAvatar.isVisible = true - binding.imageViewAvatar.newImageRequest(this, user.avatar) + viewBinding.imageViewAvatar.isVisible = true + viewBinding.imageViewAvatar.newImageRequest(this, user.avatar) ?.enqueueWith(coil) } private fun onLoadingStateChanged(isLoading: Boolean) { - binding.progressBar.run { + viewBinding.progressBar.run { if (isLoading) { show() } else { diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt index 84826d62e..1096123eb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt @@ -13,8 +13,13 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.onFirst +import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler @@ -22,11 +27,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.emitValue -import org.koitharu.kotatsu.utils.ext.onFirst -import org.koitharu.kotatsu.utils.ext.require import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt index 04c978f66..483f90b5e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt @@ -4,14 +4,14 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.databinding.ItemScrobblingMangaBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest fun scrobblingMangaAD( clickListener: OnListItemClickListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt index b33887675..4e0c4e913 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt index 76b5d8de0..37502d42a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt @@ -14,12 +14,15 @@ import coil.ImageLoader import com.google.android.material.tabs.TabLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener -import org.koitharu.kotatsu.base.ui.util.CollapseActionViewCallback import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.parser.MangaIntent +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener +import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback +import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetScrobblingSelectorBinding import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.parsers.model.Manga @@ -27,9 +30,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerMangaSelectionDecoration import org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter.ScrobblerSelectorAdapter -import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.withArgs import javax.inject.Inject @AndroidEntryPoint @@ -50,14 +50,14 @@ class ScrobblingSelectorBottomSheet : private val viewModel by viewModels() - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetScrobblingSelectorBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetScrobblingSelectorBinding { return SheetScrobblingSelectorBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetScrobblingSelectorBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val listAdapter = ScrobblerSelectorAdapter(viewLifecycleOwner, coil, this, this) - val decoration = ScrobblerMangaSelectionDecoration(view.context) + val decoration = ScrobblerMangaSelectionDecoration(binding.root.context) with(binding.recyclerView) { adapter = listAdapter addItemDecoration(decoration) @@ -133,7 +133,7 @@ class ScrobblingSelectorBottomSheet : return false } viewModel.search(query) - binding.headerBar.menu.findItem(R.id.action_search)?.collapseActionView() + requireViewBinding().headerBar.menu.findItem(R.id.action_search)?.collapseActionView() return true } @@ -149,11 +149,11 @@ class ScrobblingSelectorBottomSheet : if (!isExpanded) { setExpanded(isExpanded = true, isLocked = behavior?.isDraggable == false) } - binding.recyclerView.firstVisibleItemPosition = 0 + requireViewBinding().recyclerView.firstVisibleItemPosition = 0 } private fun openSearch() { - val menuItem = binding.headerBar.menu.findItem(R.id.action_search) ?: return + val menuItem = requireViewBinding().headerBar.menu.findItem(R.id.action_search) ?: return menuItem.expandActionView() } @@ -165,8 +165,8 @@ class ScrobblingSelectorBottomSheet : } private fun initOptionsMenu() { - binding.headerBar.inflateMenu(R.menu.opt_shiki_selector) - val searchMenuItem = binding.headerBar.menu.findItem(R.id.action_search) + requireViewBinding().headerBar.inflateMenu(R.menu.opt_shiki_selector) + val searchMenuItem = requireViewBinding().headerBar.menu.findItem(R.id.action_search) searchMenuItem.setOnActionExpandListener(this) val searchView = searchMenuItem.actionView as SearchView searchView.setOnQueryTextListener(this) @@ -179,7 +179,7 @@ class ScrobblingSelectorBottomSheet : private fun initTabs() { val entries = viewModel.availableScrobblers - val tabs = binding.tabs + val tabs = requireViewBinding().tabs if (entries.size <= 1) { tabs.isVisible = false return diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt index 495a68883..c27419e5d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt @@ -11,9 +11,14 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga +import org.koitharu.kotatsu.core.parser.MangaIntent +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.require +import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.list.ui.model.LoadingState @@ -21,12 +26,7 @@ import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.ui.selector.model.ScrobblerHint -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.emitValue -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.require -import org.koitharu.kotatsu.utils.ext.requireValue +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt index 90926f9fa..ea14d0a6c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt @@ -1,13 +1,13 @@ package org.koitharu.kotatsu.scrobbling.common.ui.selector.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemEmptyHintBinding import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.scrobbling.common.ui.selector.model.ScrobblerHint -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.setTextAndVisible -import org.koitharu.kotatsu.utils.ext.textAndVisible fun scrobblerHintAD( listener: ListStateHolderListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt index 5b74f913a..4fa7f1a6c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt @@ -7,9 +7,9 @@ import android.graphics.RectF import android.view.View import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.NO_ID +import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga -import org.koitharu.kotatsu.utils.ext.getItem class ScrobblerMangaSelectionDecoration(context: Context) : MangaSelectionDecoration(context) { diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt index 9ed58c8e4..c39a79846 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt index 79487a484..28b73ce01 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt @@ -4,14 +4,14 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.textAndVisible fun scrobblingMangaAD( lifecycleOwner: LifecycleOwner, diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt index 9e4c90289..9ddf0aacb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt @@ -9,6 +9,7 @@ import okhttp3.Request import org.json.JSONObject import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.db.MangaDatabase +import org.koitharu.kotatsu.core.util.ext.toRequestBody import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.json.getStringOrNull @@ -23,7 +24,6 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser -import org.koitharu.kotatsu.utils.ext.toRequestBody private const val REDIRECT_URI = "kotatsu://shikimori-auth" private const val BASE_URL = "https://shikimori.me/" diff --git a/app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt b/app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt index 80d3dce0f..79c106a80 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt @@ -20,8 +20,8 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.util.levenshteinDistance +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt index c1063de8c..1dd93c2a2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt @@ -9,16 +9,16 @@ import androidx.fragment.app.commit import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaTags +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.local.ui.LocalListFragment import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat -import org.koitharu.kotatsu.utils.ext.getSerializableExtraCompat @AndroidEntryPoint class MangaListActivity : @@ -26,7 +26,7 @@ class MangaListActivity : AppBarOwner { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -57,7 +57,7 @@ class MangaListActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt index f86f82b3e..f36639dec 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt @@ -11,12 +11,12 @@ import androidx.core.view.updatePadding import androidx.fragment.app.commit import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat +import org.koitharu.kotatsu.core.util.ext.showKeyboard import org.koitharu.kotatsu.databinding.ActivitySearchBinding import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel -import org.koitharu.kotatsu.utils.ext.getSerializableExtraCompat -import org.koitharu.kotatsu.utils.ext.showKeyboard @AndroidEntryPoint class SearchActivity : BaseActivity(), SearchView.OnQueryTextListener { @@ -34,7 +34,7 @@ class SearchActivity : BaseActivity(), SearchView.OnQuery val query = intent.getStringExtra(EXTRA_QUERY) supportActionBar?.setDisplayHomeAsUpEnabled(true) searchSuggestionViewModel.isIncognitoModeEnabled.observe(this, this::onIncognitoModeChanged) - with(binding.searchView) { + with(viewBinding.searchView) { queryHint = getString(R.string.search_on_s, source.title) setOnQueryTextListener(this@SearchActivity) @@ -48,11 +48,11 @@ class SearchActivity : BaseActivity(), SearchView.OnQuery } override fun onWindowInsetsChanged(insets: Insets) { - binding.toolbar.updatePadding( + viewBinding.toolbar.updatePadding( left = insets.left, right = insets.right, ) - binding.container.updatePadding( + viewBinding.container.updatePadding( bottom = insets.bottom, ) } @@ -67,7 +67,7 @@ class SearchActivity : BaseActivity(), SearchView.OnQuery setReorderingAllowed(true) replace(R.id.container, SearchFragment.newInstance(source, q)) } - binding.searchView.clearFocus() + viewBinding.searchView.clearFocus() searchSuggestionViewModel.saveQuery(q) return true } @@ -75,13 +75,13 @@ class SearchActivity : BaseActivity(), SearchView.OnQuery override fun onQueryTextChange(newText: String?): Boolean = false private fun onIncognitoModeChanged(isIncognito: Boolean) { - var options = binding.searchView.imeOptions + var options = viewBinding.searchView.imeOptions options = if (isIncognito) { options or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING } else { options and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() } - binding.searchView.imeOptions = options + viewBinding.searchView.imeOptions = options } companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt index b5fa580fe..6e8b9683a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt @@ -5,10 +5,10 @@ import androidx.appcompat.view.ActionMode import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class SearchFragment : MangaListFragment() { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index f6e1571f7..7c442d0b1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -12,6 +12,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -22,8 +24,6 @@ import org.koitharu.kotatsu.list.ui.model.toErrorFooter import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.require import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt index 96ab9c1b2..0e0c59362 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt @@ -14,11 +14,14 @@ import androidx.core.view.updatePadding import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.list.ListSelectionController -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations +import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.ActivitySearchMultiBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver @@ -33,9 +36,6 @@ import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter -import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations -import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf import javax.inject.Inject @AndroidEntryPoint @@ -80,8 +80,8 @@ class MultiSearchActivity : sizeResolver = sizeResolver, selectionDecoration = selectionDecoration, ) - binding.recyclerView.adapter = adapter - binding.recyclerView.setHasFixedSize(true) + viewBinding.recyclerView.adapter = adapter + viewBinding.recyclerView.setHasFixedSize(true) supportActionBar?.run { setDisplayHomeAsUpEnabled(true) @@ -90,16 +90,16 @@ class MultiSearchActivity : viewModel.query.observe(this) { title = it } viewModel.list.observe(this) { adapter.items = it } - viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null)) - viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(binding.recyclerView)) + viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) + viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(viewBinding.recyclerView)) } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( bottom = insets.bottom, ) } @@ -142,7 +142,7 @@ class MultiSearchActivity : override fun onListHeaderClick(item: ListHeader, view: View) = Unit override fun onSelectionChanged(controller: ListSelectionController, count: Int) { - binding.recyclerView.invalidateNestedItemDecorations() + viewBinding.recyclerView.invalidateNestedItemDecorations() } override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index 83c99f126..1a420e11f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -15,11 +15,14 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.update import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.exceptions.CompositeException import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -28,11 +31,8 @@ import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.emitValue -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject private const val MAX_PARALLELISM = 4 diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt index 05ff6f427..5abb41e8c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt @@ -5,7 +5,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView.RecycledViewPool import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration import org.koitharu.kotatsu.list.ui.adapter.MangaListListener diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt index 71b90aa10..2fdcf1b90 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt @@ -7,9 +7,9 @@ import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.databinding.ItemListGroupBinding import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration @@ -27,12 +27,12 @@ fun searchResultsAD( listener: OnListItemClickListener, itemClickListener: OnListItemClickListener, ) = adapterDelegateViewBinding( - { layoutInflater, parent -> ItemListGroupBinding.inflate(layoutInflater, parent, false) } + { layoutInflater, parent -> ItemListGroupBinding.inflate(layoutInflater, parent, false) }, ) { binding.recyclerView.setRecycledViewPool(sharedPool) val adapter = ListDelegationAdapter( - mangaGridItemAD(coil, lifecycleOwner, listener, sizeResolver) + mangaGridItemAD(coil, lifecycleOwner, listener, sizeResolver), ) binding.recyclerView.addItemDecoration(selectionDecoration) binding.recyclerView.adapter = adapter @@ -47,4 +47,4 @@ fun searchResultsAD( adapter.notifyDataSetChanged() adapter.items = item.list } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt index c7162aad8..bc77594e9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt @@ -2,7 +2,6 @@ package org.koitharu.kotatsu.search.ui.suggestion import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.graphics.Insets import androidx.core.view.updatePadding @@ -10,12 +9,12 @@ import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.ItemTouchHelper import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter -import org.koitharu.kotatsu.utils.ext.addMenuProvider +import javax.inject.Inject @AndroidEntryPoint class SearchSuggestionFragment : @@ -27,19 +26,19 @@ class SearchSuggestionFragment : private val viewModel by activityViewModels() - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentSearchSuggestionBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val adapter = SearchSuggestionAdapter( coil = coil, lifecycleOwner = viewLifecycleOwner, listener = requireActivity() as SearchSuggestionListener, ) - addMenuProvider(SearchSuggestionMenuProvider(view.context, viewModel)) + addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, viewModel)) binding.root.adapter = adapter binding.root.setHasFixedSize(true) viewModel.suggestion.observe(viewLifecycleOwner) { @@ -51,7 +50,7 @@ class SearchSuggestionFragment : override fun onWindowInsetsChanged(insets: Insets) { val extraPadding = resources.getDimensionPixelOffset(R.dimen.list_spacing) - binding.root.updatePadding( + requireViewBinding().root.updatePadding( top = extraPadding, right = insets.right, left = insets.left, diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt index 7c65c7c42..84120ad16 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt @@ -2,9 +2,9 @@ package org.koitharu.kotatsu.search.ui.suggestion import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView +import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.search.ui.suggestion.adapter.SEARCH_SUGGESTION_ITEM_TYPE_QUERY import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem -import org.koitharu.kotatsu.utils.ext.getItem class SearchSuggestionItemCallback( private val listener: SuggestionItemListener, @@ -12,7 +12,7 @@ class SearchSuggestionItemCallback( private val movementFlags = makeMovementFlags( 0, - ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT + ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, ) override fun getMovementFlags( @@ -39,4 +39,4 @@ class SearchSuggestionItemCallback( fun onRemoveQuery(query: String) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt index 6853f2d18..9862e195f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt @@ -15,16 +15,16 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.plus -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.widgets.ChipsView import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.search.domain.MangaSearchRepository import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem -import org.koitharu.kotatsu.utils.ext.emitValue import javax.inject.Inject private const val DEBOUNCE_TIMEOUT = 500L diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt index 5d713a300..6552643a1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt @@ -4,14 +4,14 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.core.parser.favicon.faviconUri +import org.koitharu.kotatsu.core.ui.image.FaviconFallbackDrawable +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemSearchSuggestionSourceBinding import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.image.FaviconFallbackDrawable fun searchSuggestionSourceAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt index 25e3eaf7d..7360de65c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.search.ui.suggestion.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem @@ -20,4 +20,4 @@ fun searchSuggestionTagsAD( bind { chipGroup.setChips(item.tags) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt index 992ebfd9b..f678ca53c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt @@ -9,16 +9,16 @@ import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemSearchSuggestionMangaGridBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem -import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source fun searchSuggestionMangaListAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt index 572d9c75b..8d720e2d1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.search.ui.suggestion.model -import android.net.Uri -import org.koitharu.kotatsu.base.ui.widgets.ChipsView +import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.areItemsEquals @@ -42,9 +41,7 @@ sealed interface SearchSuggestionItem { other as RecentQuery - if (query != other.query) return false - - return true + return query == other.query } override fun hashCode(): Int { @@ -64,9 +61,7 @@ sealed interface SearchSuggestionItem { other as Source if (source != other.source) return false - if (isEnabled != other.isEnabled) return false - - return true + return isEnabled == other.isEnabled } override fun hashCode(): Int { @@ -86,9 +81,7 @@ sealed interface SearchSuggestionItem { other as Tags - if (tags != other.tags) return false - - return true + return tags == other.tags } override fun hashCode(): Int { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt index 2c00a1310..417e48d94 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt @@ -16,9 +16,9 @@ import androidx.annotation.AttrRes import androidx.appcompat.widget.AppCompatEditText import androidx.core.content.ContextCompat import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.drawableEnd +import org.koitharu.kotatsu.core.util.ext.drawableStart import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener -import org.koitharu.kotatsu.utils.ext.drawableEnd -import org.koitharu.kotatsu.utils.ext.drawableStart import com.google.android.material.R as materialR private const val DRAWABLE_END = 2 diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt index d46df2738..468ffb0fa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt @@ -16,19 +16,19 @@ import androidx.preference.Preference import androidx.preference.TwoStatePreference import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment -import org.koitharu.kotatsu.base.ui.util.ActivityRecreationHandle import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle +import org.koitharu.kotatsu.core.util.ext.getLocalesConfig +import org.koitharu.kotatsu.core.util.ext.map +import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat +import org.koitharu.kotatsu.core.util.ext.toList import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.settings.protect.ProtectSetupActivity import org.koitharu.kotatsu.settings.utils.ActivityListPreference import org.koitharu.kotatsu.settings.utils.SliderPreference -import org.koitharu.kotatsu.utils.ext.getLocalesConfig -import org.koitharu.kotatsu.utils.ext.map -import org.koitharu.kotatsu.utils.ext.setDefaultValueCompat -import org.koitharu.kotatsu.utils.ext.toList import java.util.Locale import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt index 34523393b..bad3d8632 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt @@ -11,18 +11,18 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment -import org.koitharu.kotatsu.base.ui.dialog.StorageSelectDialog import org.koitharu.kotatsu.core.cache.ContentCache import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.ui.dialog.StorageSelectDialog +import org.koitharu.kotatsu.core.util.ext.getStorageName +import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.parsers.util.names -import org.koitharu.kotatsu.utils.ext.getStorageName -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.setDefaultValueCompat -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt b/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt index 8e55b27c4..0ac467edc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.settings import okhttp3.HttpUrl import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.EditTextValidator +import org.koitharu.kotatsu.core.util.EditTextValidator class DomainValidator : EditTextValidator() { 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 c0b53620a..4ced54381 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt @@ -10,18 +10,18 @@ import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CancellationException import kotlinx.coroutines.launch import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.os.ShortcutsUpdater import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.FileSize +import org.koitharu.kotatsu.core.util.ext.awaitStateAtLeast +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.search.domain.MangaSearchRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.FileSize -import org.koitharu.kotatsu.utils.ext.awaitStateAtLeast -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt index dedac9988..a75535bcc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt @@ -6,8 +6,8 @@ import android.os.Bundle import android.view.View import androidx.preference.Preference import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.settings.utils.RingtonePickContract class NotificationSettingsLegacyFragment : @@ -56,6 +56,7 @@ class NotificationSettingsLegacyFragment : ringtonePickContract.launch(settings.notificationSound) true } + else -> super.onPreferenceTreeClick(preference) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt index 0f1ab7c74..672073926 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt @@ -8,13 +8,13 @@ import androidx.preference.MultiSelectListPreference import androidx.preference.Preference import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider -import org.koitharu.kotatsu.utils.ext.setDefaultValueCompat @AndroidEntryPoint class ReaderSettingsFragment : diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt index ad02acf64..7d737ee50 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt @@ -2,11 +2,11 @@ package org.koitharu.kotatsu.settings import android.os.Bundle import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment class RootSettingsFragment : BasePreferenceFragment(R.string.settings) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_root) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt index 2cea0ee75..04bbd96ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt @@ -12,8 +12,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.scrobbling.anilist.data.AniListRepository import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.ui.config.ScrobblerConfigActivity @@ -21,9 +23,7 @@ import org.koitharu.kotatsu.scrobbling.mal.data.MALRepository import org.koitharu.kotatsu.scrobbling.shikimori.data.ShikimoriRepository import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.sync.ui.SyncSettingsIntent -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt index 5cecec9ab..9b608aa96 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt @@ -18,16 +18,16 @@ import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat +import org.koitharu.kotatsu.core.util.ext.isScrolledToTop import org.koitharu.kotatsu.databinding.ActivitySettingsBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.settings.about.AboutSettingsFragment import org.koitharu.kotatsu.settings.sources.SourcesListFragment import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment -import org.koitharu.kotatsu.utils.ext.getSerializableExtraCompat -import org.koitharu.kotatsu.utils.ext.isScrolledToTop @AndroidEntryPoint class SettingsActivity : @@ -37,7 +37,7 @@ class SettingsActivity : FragmentManager.OnBackStackChangedListener { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -51,7 +51,7 @@ class SettingsActivity : override fun onTitleChanged(title: CharSequence?, color: Int) { super.onTitleChanged(title, color) - binding.collapsingToolbarLayout?.title = title + viewBinding.collapsingToolbarLayout?.title = title } override fun onStart() { @@ -86,7 +86,7 @@ class SettingsActivity : val fragment = supportFragmentManager.findFragmentById(R.id.container) as? RecyclerViewOwner ?: return val recyclerView = fragment.recyclerView recyclerView.post { - binding.appbar.setExpanded(recyclerView.isScrolledToTop, false) + viewBinding.appbar.setExpanded(recyclerView.isScrolledToTop, false) } } @@ -104,11 +104,11 @@ class SettingsActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.appbar.updatePadding( + viewBinding.appbar.updatePadding( left = insets.left, right = insets.right, ) - binding.container.updatePadding( + viewBinding.container.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt index 43327d44a..565b8395d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt @@ -12,20 +12,20 @@ import kotlinx.coroutines.ensureActive import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.awaitViewLifecycle +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.requireSerializable +import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.settings.sources.auth.SourceAuthActivity -import org.koitharu.kotatsu.utils.ext.awaitViewLifecycle -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.requireSerializable -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.viewLifecycleScope -import org.koitharu.kotatsu.utils.ext.withArgs +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt index 0ba19a211..f7be5bdcd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt @@ -4,15 +4,15 @@ import android.content.SharedPreferences import android.os.Bundle import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import kotlinx.coroutines.launch import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.settings.utils.MultiAutoCompleteTextViewPreference import org.koitharu.kotatsu.settings.utils.TagsAutoCompleteProvider import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker +import javax.inject.Inject @AndroidEntryPoint class SuggestionsSettingsFragment : diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt index 530b8d0ea..60a609307 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt @@ -6,7 +6,7 @@ import androidx.fragment.app.FragmentResultListener import androidx.preference.Preference import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.sync.data.SyncSettings import org.koitharu.kotatsu.sync.ui.SyncHostDialogFragment import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt index cfede729c..94051d98b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt @@ -11,13 +11,13 @@ import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.github.AppVersion import org.koitharu.kotatsu.core.github.VersionId import org.koitharu.kotatsu.core.github.isStable import org.koitharu.kotatsu.core.logs.FileLogger import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.utils.ShareHelper +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ShareHelper import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt index 5289f751c..3ee1ea9e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt @@ -1,11 +1,11 @@ package org.koitharu.kotatsu.settings.about import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.github.AppVersion -import org.koitharu.kotatsu.utils.SingleLiveEvent +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import javax.inject.Inject @HiltViewModel class AboutSettingsViewModel @Inject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt b/app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt index 0043a5ab2..e57058e09 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt @@ -8,7 +8,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import io.noties.markwon.Markwon import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.github.AppVersion -import org.koitharu.kotatsu.utils.FileSize +import org.koitharu.kotatsu.core.util.FileSize import com.google.android.material.R as materialR class AppUpdateDialog(private val context: Context) { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt index 8acbc7a10..19362ebb2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.settings.backup import android.net.Uri import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts @@ -12,9 +11,9 @@ import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.databinding.DialogProgressBinding -import org.koitharu.kotatsu.utils.ext.getDisplayMessage import java.io.File import java.io.FileOutputStream import kotlin.math.roundToInt @@ -36,13 +35,13 @@ class BackupDialogFragment : AlertDialogFragment() { } } - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = DialogProgressBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogProgressBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.textViewTitle.setText(R.string.create_backup) binding.textViewSubtitle.setText(R.string.processing_) @@ -67,7 +66,7 @@ class BackupDialogFragment : AlertDialogFragment() { } private fun onProgressChanged(value: Float) { - with(binding.progressBar) { + with(requireViewBinding().progressBar) { isVisible = true val wasIndeterminate = isIndeterminate isIndeterminate = value < 0 diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt index 53ad51cbc..fbeb28594 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt @@ -8,9 +8,9 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.preference.Preference import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.util.ext.printStackTraceDebug class BackupSettingsFragment : BasePreferenceFragment(R.string.backup_restore), @@ -18,7 +18,7 @@ class BackupSettingsFragment : private val backupSelectCall = registerForActivityResult( ActivityResultContracts.OpenDocument(), - this + this, ) override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -31,17 +31,19 @@ class BackupSettingsFragment : BackupDialogFragment().show(childFragmentManager, BackupDialogFragment.TAG) true } + AppSettings.KEY_RESTORE -> { try { backupSelectCall.launch(arrayOf("*/*")) } catch (e: ActivityNotFoundException) { e.printStackTraceDebug() Snackbar.make( - listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT + listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT, ).show() } true } + else -> super.onPreferenceTreeClick(preference) } } @@ -50,4 +52,4 @@ class BackupSettingsFragment : RestoreDialogFragment.newInstance(result ?: return) .show(childFragmentManager, BackupDialogFragment.TAG) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt index ae1cae8a4..80d9705e3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt @@ -4,10 +4,10 @@ import android.content.Context import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipOutput -import org.koitharu.kotatsu.utils.SingleLiveEvent +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent import java.io.File import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt index e1e3dee63..c1c7c7817 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt @@ -3,18 +3,17 @@ package org.koitharu.kotatsu.settings.backup import android.net.Uri import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment import org.koitharu.kotatsu.core.backup.CompositeResult +import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.DialogProgressBinding -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.withArgs import kotlin.math.roundToInt @AndroidEntryPoint @@ -22,13 +21,13 @@ class RestoreDialogFragment : AlertDialogFragment() { private val viewModel: RestoreViewModel by viewModels() - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = DialogProgressBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogProgressBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.textViewTitle.setText(R.string.restore_backup) binding.textViewSubtitle.setText(R.string.preparing_) @@ -52,7 +51,7 @@ class RestoreDialogFragment : AlertDialogFragment() { } private fun onProgressChanged(value: Float) { - with(binding.progressBar) { + with(requireViewBinding().progressBar) { isVisible = true val wasIndeterminate = isIndeterminate isIndeterminate = value < 0 diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt index 9efc859cf..cea8a7dfa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt @@ -7,13 +7,13 @@ import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.backup.BackupEntry import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipInput import org.koitharu.kotatsu.core.backup.CompositeResult -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.toUriOrNull +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.toUriOrNull import java.io.File import java.io.FileNotFoundException import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt index 7c76e4d84..ac16391c6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.settings.newsources import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels @@ -11,7 +10,7 @@ import coil.ImageLoader import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.databinding.DialogOnboardBinding import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem @@ -28,12 +27,12 @@ class NewSourcesDialogFragment : private val viewModel by viewModels() - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): DialogOnboardBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): DialogOnboardBinding { return DialogOnboardBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogOnboardBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val adapter = SourcesSelectAdapter(this, coil, viewLifecycleOwner) binding.recyclerView.adapter = adapter binding.textViewTitle.setText(R.string.new_sources_text) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt index 52151b6a3..3f631be7b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt @@ -3,12 +3,12 @@ package org.koitharu.kotatsu.settings.newsources import androidx.core.os.LocaleListCompat import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.getLocaleTitle import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.ext.mapToSet import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem -import org.koitharu.kotatsu.utils.ext.mapToSet +import javax.inject.Inject @HiltViewModel class NewSourcesViewModel @Inject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt index 51b21e2ce..295a08a90 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt @@ -3,20 +3,19 @@ package org.koitharu.kotatsu.settings.onboard import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.showAllowStateLoss +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.DialogOnboardBinding import org.koitharu.kotatsu.settings.onboard.adapter.SourceLocaleListener import org.koitharu.kotatsu.settings.onboard.adapter.SourceLocalesAdapter import org.koitharu.kotatsu.settings.onboard.model.SourceLocale -import org.koitharu.kotatsu.utils.ext.showAllowStateLoss -import org.koitharu.kotatsu.utils.ext.withArgs @AndroidEntryPoint class OnboardDialogFragment : @@ -33,7 +32,7 @@ class OnboardDialogFragment : } } - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = DialogOnboardBinding.inflate(inflater, container, false) @@ -52,8 +51,8 @@ class OnboardDialogFragment : return builder } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: DialogOnboardBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val adapter = SourceLocalesAdapter(this) binding.recyclerView.adapter = adapter binding.textViewTitle.setText(R.string.onboard_text) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt index 82a7400b0..4380d0163 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt @@ -3,15 +3,15 @@ package org.koitharu.kotatsu.settings.onboard import androidx.core.os.LocaleListCompat import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.ext.map +import org.koitharu.kotatsu.core.util.ext.mapToSet import org.koitharu.kotatsu.parsers.util.mapNotNullToSet import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.settings.onboard.model.SourceLocale -import org.koitharu.kotatsu.utils.ext.map -import org.koitharu.kotatsu.utils.ext.mapToSet import java.util.Locale import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt index f5d5f1aed..3d5dfae35 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt @@ -2,10 +2,10 @@ package org.koitharu.kotatsu.settings.onboard.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.setChecked +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemSourceLocaleBinding import org.koitharu.kotatsu.settings.onboard.model.SourceLocale -import org.koitharu.kotatsu.utils.ext.setChecked -import org.koitharu.kotatsu.utils.ext.textAndVisible fun sourceLocaleAD( listener: SourceLocaleListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt index 479cbdb5e..955158643 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt @@ -17,7 +17,7 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding private const val MIN_PASSWORD_LENGTH = 4 @@ -36,29 +36,29 @@ class ProtectSetupActivity : super.onCreate(savedInstanceState) window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) setContentView(ActivitySetupProtectBinding.inflate(layoutInflater)) - binding.editPassword.addTextChangedListener(this) - binding.editPassword.setOnEditorActionListener(this) - binding.buttonNext.setOnClickListener(this) - binding.buttonCancel.setOnClickListener(this) + viewBinding.editPassword.addTextChangedListener(this) + viewBinding.editPassword.setOnEditorActionListener(this) + viewBinding.buttonNext.setOnClickListener(this) + viewBinding.buttonCancel.setOnClickListener(this) - binding.switchBiometric.isChecked = viewModel.isBiometricEnabled - binding.switchBiometric.setOnCheckedChangeListener(this) + viewBinding.switchBiometric.isChecked = viewModel.isBiometricEnabled + viewBinding.switchBiometric.setOnCheckedChangeListener(this) viewModel.isSecondStep.observe(this, this::onStepChanged) viewModel.onPasswordSet.observe(this) { finishAfterTransition() } viewModel.onPasswordMismatch.observe(this) { - binding.editPassword.error = getString(R.string.passwords_mismatch) + viewBinding.editPassword.error = getString(R.string.passwords_mismatch) } viewModel.onClearText.observe(this) { - binding.editPassword.text?.clear() + viewBinding.editPassword.text?.clear() } } override fun onWindowInsetsChanged(insets: Insets) { val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding) - binding.root.setPadding( + viewBinding.root.setPadding( basePadding + insets.left, basePadding + insets.top, basePadding + insets.right, @@ -70,7 +70,7 @@ class ProtectSetupActivity : when (v.id) { R.id.button_cancel -> finish() R.id.button_next -> viewModel.onNextClick( - password = binding.editPassword.text?.toString() ?: return, + password = viewBinding.editPassword.text?.toString() ?: return, ) } } @@ -80,8 +80,8 @@ class ProtectSetupActivity : } override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean { - return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) { - binding.buttonNext.performClick() + return if (actionId == EditorInfo.IME_ACTION_DONE && viewBinding.buttonNext.isEnabled) { + viewBinding.buttonNext.performClick() true } else { false @@ -93,22 +93,22 @@ class ProtectSetupActivity : override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit override fun afterTextChanged(s: Editable?) { - binding.editPassword.error = null + viewBinding.editPassword.error = null val isEnoughLength = (s?.length ?: 0) >= MIN_PASSWORD_LENGTH - binding.buttonNext.isEnabled = isEnoughLength - binding.layoutPassword.isHelperTextEnabled = + viewBinding.buttonNext.isEnabled = isEnoughLength + viewBinding.layoutPassword.isHelperTextEnabled = !isEnoughLength || viewModel.isSecondStep.value == true } private fun onStepChanged(isSecondStep: Boolean) { - binding.buttonCancel.isGone = isSecondStep - binding.switchBiometric.isVisible = isSecondStep && isBiometricAvailable() + viewBinding.buttonCancel.isGone = isSecondStep + viewBinding.switchBiometric.isVisible = isSecondStep && isBiometricAvailable() if (isSecondStep) { - binding.layoutPassword.helperText = getString(R.string.repeat_password) - binding.buttonNext.setText(R.string.confirm) + viewBinding.layoutPassword.helperText = getString(R.string.repeat_password) + viewBinding.buttonNext.setText(R.string.confirm) } else { - binding.layoutPassword.helperText = getString(R.string.password_length_hint) - binding.buttonNext.setText(R.string.next) + viewBinding.layoutPassword.helperText = getString(R.string.password_length_hint) + viewBinding.buttonNext.setText(R.string.next) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt index 351ccc360..387c34848 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt @@ -4,11 +4,11 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.parsers.util.md5 -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt index 2fdd8b92f..d34733efa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater import android.view.MenuItem -import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.SearchView import androidx.core.graphics.Insets @@ -17,9 +16,11 @@ import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner -import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.settings.SettingsActivity @@ -28,8 +29,6 @@ import org.koitharu.kotatsu.settings.SourceSettingsFragment import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem -import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.getItem import javax.inject.Inject @AndroidEntryPoint @@ -45,20 +44,15 @@ class SourcesListFragment : private val viewModel by viewModels() override val recyclerView: RecyclerView - get() = binding.recyclerView + get() = requireViewBinding().recyclerView - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentSettingsSourcesBinding.inflate(inflater, container, false) - override fun onResume() { - super.onResume() - activity?.setTitle(R.string.remote_sources) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentSettingsSourcesBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) val sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner) with(binding.recyclerView) { setHasFixedSize(true) @@ -74,13 +68,18 @@ class SourcesListFragment : addMenuProvider(SourcesMenuProvider()) } + override fun onResume() { + super.onResume() + activity?.setTitle(R.string.remote_sources) + } + override fun onDestroyView() { reorderHelper = null super.onDestroyView() } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, left = insets.left, right = insets.right, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt index 553988dce..9eaf346c2 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt @@ -9,18 +9,18 @@ import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.ReversibleHandle -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.model.getLocaleTitle import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.ui.util.ReversibleHandle +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.map +import org.koitharu.kotatsu.core.util.ext.move import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.map -import org.koitharu.kotatsu.utils.ext.move import java.util.Locale import java.util.TreeMap import javax.inject.Inject @@ -65,8 +65,7 @@ class SourcesListViewModel @Inject constructor( fun canReorder(oldPos: Int, newPos: Int): Boolean { val snapshot = items.value?.toMutableList() ?: return false if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isEnabled != true) return false - if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isEnabled != true) return false - return true + return (snapshot[newPos] as? SourceConfigItem.SourceItem)?.isEnabled == true } fun setEnabled(source: MangaSource, isEnabled: Boolean) { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt index 1f3aa5253..bef802851 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt @@ -8,21 +8,21 @@ import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnTipCloseListener import org.koitharu.kotatsu.core.parser.favicon.faviconUri +import org.koitharu.kotatsu.core.ui.image.FaviconFallbackDrawable +import org.koitharu.kotatsu.core.ui.list.OnTipCloseListener +import org.koitharu.kotatsu.core.util.ext.crossfade +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemExpandableBinding import org.koitharu.kotatsu.databinding.ItemFilterHeaderBinding import org.koitharu.kotatsu.databinding.ItemSourceConfigBinding import org.koitharu.kotatsu.databinding.ItemSourceConfigCheckableBinding import org.koitharu.kotatsu.databinding.ItemTipBinding import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem -import org.koitharu.kotatsu.utils.ext.crossfade -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source -import org.koitharu.kotatsu.utils.ext.textAndVisible -import org.koitharu.kotatsu.utils.image.FaviconFallbackDrawable fun sourceConfigHeaderDelegate() = adapterDelegateViewBinding( diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt index d8f0be9fa..d90969f17 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.settings.sources.adapter -import org.koitharu.kotatsu.base.ui.list.OnTipCloseListener +import org.koitharu.kotatsu.core.ui.list.OnTipCloseListener import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem interface SourceConfigListener : OnTipCloseListener { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt index b0f0ca321..68913fe55 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt @@ -13,7 +13,6 @@ import androidx.core.view.isVisible import androidx.core.view.updatePadding import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.browser.BrowserCallback import org.koitharu.kotatsu.browser.BrowserClient import org.koitharu.kotatsu.browser.ProgressChromeClient @@ -21,12 +20,13 @@ import org.koitharu.kotatsu.browser.WebViewBackPressedCallback import org.koitharu.kotatsu.core.network.CommonHeadersInterceptor import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.TaggedActivityResult +import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability +import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.parsers.MangaParserAuthProvider import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.utils.TaggedActivityResult -import org.koitharu.kotatsu.utils.ext.catchingWebViewUnavailability -import org.koitharu.kotatsu.utils.ext.getSerializableExtraCompat import javax.inject.Inject import com.google.android.material.R as materialR @@ -64,13 +64,13 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } - with(binding.webView.settings) { + with(viewBinding.webView.settings) { javaScriptEnabled = true userAgentString = CommonHeadersInterceptor.userAgentChrome } - binding.webView.webViewClient = BrowserClient(this) - binding.webView.webChromeClient = ProgressChromeClient(binding.progressBar) - onBackPressedCallback = WebViewBackPressedCallback(binding.webView) + viewBinding.webView.webViewClient = BrowserClient(this) + viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar) + onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView) onBackPressedDispatcher.addCallback(onBackPressedCallback) if (savedInstanceState != null) { return @@ -80,27 +80,27 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba source.title, getString(R.string.loading_), ) - binding.webView.loadUrl(url) + viewBinding.webView.loadUrl(url) } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - binding.webView.saveState(outState) + viewBinding.webView.saveState(outState) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) - binding.webView.restoreState(savedInstanceState) + viewBinding.webView.restoreState(savedInstanceState) } override fun onDestroy() { super.onDestroy() - binding.webView.destroy() + viewBinding.webView.destroy() } override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { android.R.id.home -> { - binding.webView.stopLoading() + viewBinding.webView.stopLoading() setResult(Activity.RESULT_CANCELED) finishAfterTransition() true @@ -110,17 +110,17 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba } override fun onPause() { - binding.webView.onPause() + viewBinding.webView.onPause() super.onPause() } override fun onResume() { super.onResume() - binding.webView.onResume() + viewBinding.webView.onResume() } override fun onLoadingStateChanged(isLoading: Boolean) { - binding.progressBar.isVisible = isLoading + viewBinding.progressBar.isVisible = isLoading if (!isLoading && authProvider.isAuthorized) { Toast.makeText(this, R.string.auth_complete, Toast.LENGTH_SHORT).show() setResult(Activity.RESULT_OK) @@ -138,8 +138,8 @@ class SourceAuthActivity : BaseActivity(), BrowserCallba } override fun onWindowInsetsChanged(insets: Insets) { - binding.appbar.updatePadding(top = insets.top) - binding.webView.updatePadding(bottom = insets.bottom) + viewBinding.appbar.updatePadding(top = insets.top) + viewBinding.webView.updatePadding(bottom = insets.bottom) } class Contract : ActivityResultContract() { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt index c7a7d4458..51ea765ef 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt @@ -13,13 +13,13 @@ import androidx.core.view.updatePadding import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment import org.koitharu.kotatsu.core.github.AppVersion +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.FragmentToolsBinding import org.koitharu.kotatsu.download.ui.list.DownloadsActivity import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.about.AppUpdateDialog -import org.koitharu.kotatsu.utils.ext.setChecked @AndroidEntryPoint class ToolsFragment : @@ -29,12 +29,12 @@ class ToolsFragment : private val viewModel by viewModels() - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): FragmentToolsBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentToolsBinding { return FragmentToolsBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentToolsBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.buttonSettings.setOnClickListener(this) binding.buttonDownloads.setOnClickListener(this) binding.cardUpdate.buttonChangelog.setOnClickListener(this) @@ -75,18 +75,18 @@ class ToolsFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + requireViewBinding().root.updatePadding( bottom = insets.bottom, ) } private fun onAppUpdateAvailable(version: AppVersion?) { if (version == null) { - binding.cardUpdate.root.isVisible = false + requireViewBinding().cardUpdate.root.isVisible = false return } - binding.cardUpdate.textSecondary.text = getString(R.string.new_version_s, version.name) - binding.cardUpdate.root.isVisible = true + requireViewBinding().cardUpdate.textSecondary.text = getString(R.string.new_version_s, version.name) + requireViewBinding().cardUpdate.root.isVisible = true } companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt index cbb17dd06..b977b7996 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt @@ -6,10 +6,10 @@ import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.settings.tools.model.StorageUsage diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt index a6eb2bc56..0328e5534 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt @@ -11,11 +11,11 @@ import androidx.core.graphics.ColorUtils import androidx.core.widget.TextViewCompat import com.google.android.material.color.MaterialColors import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.widgets.SegmentedBarView +import org.koitharu.kotatsu.core.ui.widgets.SegmentedBarView +import org.koitharu.kotatsu.core.util.FileSize +import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.databinding.LayoutMemoryUsageBinding import org.koitharu.kotatsu.settings.tools.model.StorageUsage -import org.koitharu.kotatsu.utils.FileSize -import org.koitharu.kotatsu.utils.ext.getThemeColor class MemoryUsageView @JvmOverloads constructor( context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt index e3ee6a41d..d60d185ad 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt @@ -20,13 +20,13 @@ import androidx.preference.MultiSelectListPreference import androidx.preference.Preference import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels +import javax.inject.Inject private const val KEY_IGNORE_DOZE = "ignore_dose" @@ -95,24 +95,29 @@ class TrackerSettingsFragment : startActivity(intent) true } + channels.areNotificationsDisabled -> { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", requireContext().packageName, null)) startActivity(intent) true } + else -> { super.onPreferenceTreeClick(preference) } } + AppSettings.KEY_TRACK_CATEGORIES -> { TrackerCategoriesConfigSheet.show(childFragmentManager) true } + KEY_IGNORE_DOZE -> { startIgnoreDoseActivity(preference.context) true } + else -> super.onPreferenceTreeClick(preference) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt index 21c75b086..b6d0f8106 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt @@ -5,12 +5,12 @@ import androidx.room.InvalidationTracker import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import okio.Closeable -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.TABLE_FAVOURITE_CATEGORIES import org.koitharu.kotatsu.core.db.removeObserverAsync +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.ext.emitValue import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt index d70833062..af0ebbf85 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt @@ -2,8 +2,8 @@ package org.koitharu.kotatsu.settings.tracker.categories import androidx.recyclerview.widget.DiffUtil import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener class TrackerCategoriesConfigAdapter( listener: OnListItemClickListener, diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt index a463660aa..028a22020 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt @@ -9,9 +9,9 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.SheetBaseBinding @AndroidEntryPoint @@ -22,12 +22,12 @@ class TrackerCategoriesConfigSheet : private val viewModel by viewModels() - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetBaseBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetBaseBinding { return SheetBaseBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: SheetBaseBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) binding.headerBar.setTitle(R.string.favourites_categories) binding.buttonDone.isVisible = true binding.buttonDone.setOnClickListener(this) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt index 1b9c10f7f..8ec72c44c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt @@ -2,13 +2,13 @@ package org.koitharu.kotatsu.settings.tracker.categories import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.utils.asFlowLiveData +import javax.inject.Inject @HiltViewModel class TrackerCategoriesConfigViewModel @Inject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt index 5e3876285..7db2f78b1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt @@ -1,9 +1,9 @@ package org.koitharu.kotatsu.settings.tracker.categories import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding fun trackerCategoryAD( diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt index 0de795a3b..950c69c2c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.Intent import android.util.AttributeSet import androidx.preference.ListPreference -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug +import org.koitharu.kotatsu.util.ext.printStackTraceDebug class ActivityListPreference : ListPreference { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt index 50e93f24b..7f2ccdd29 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.settings.utils import android.widget.EditText import androidx.preference.EditTextPreference -import org.koitharu.kotatsu.utils.EditTextValidator +import org.koitharu.kotatsu.core.util.EditTextValidator class EditTextBindListener( private val inputType: Int, @@ -15,4 +15,4 @@ class EditTextBindListener( editText.hint = hint validator?.attachToEditText(editText) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt index e1f88b59c..9e2151f6b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt @@ -7,7 +7,7 @@ import android.net.Uri import android.provider.Settings import androidx.activity.result.contract.ActivityResultContract import androidx.annotation.StringRes -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat class RingtonePickContract(@StringRes private val titleResId: Int) : ActivityResultContract() { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt index b2a818caa..fbf2fcc0c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt @@ -11,7 +11,7 @@ import androidx.preference.Preference import androidx.preference.PreferenceViewHolder import com.google.android.material.slider.Slider import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.setValueRounded +import org.koitharu.kotatsu.core.util.ext.setValueRounded class SliderPreference @JvmOverloads constructor( context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt index d6e9a7fac..a534c90cb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt @@ -24,9 +24,9 @@ import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt index 0cf72a0a9..cb499a611 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt @@ -13,13 +13,14 @@ import androidx.fragment.app.viewModels import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.NestedScrollStateHandle -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner -import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.list.NestedScrollStateHandle +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner +import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.databinding.FragmentShelfBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver @@ -35,7 +36,6 @@ import org.koitharu.kotatsu.shelf.ui.adapter.ShelfListEventListener import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity import org.koitharu.kotatsu.tracker.ui.updates.UpdatesActivity -import org.koitharu.kotatsu.utils.ext.addMenuProvider import javax.inject.Inject @AndroidEntryPoint @@ -56,14 +56,14 @@ class ShelfFragment : private var selectionController: SectionedSelectionController? = null override val recyclerView: RecyclerView - get() = binding.recyclerView + get() = requireViewBinding().recyclerView - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): FragmentShelfBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentShelfBinding { return FragmentShelfBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentShelfBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) nestedScrollStateHandle = NestedScrollStateHandle(savedInstanceState, KEY_NESTED_SCROLL) val sizeResolver = ItemSizeResolver(resources, settings) selectionController = SectionedSelectionController( @@ -81,7 +81,7 @@ class ShelfFragment : ) binding.recyclerView.adapter = adapter binding.recyclerView.setHasFixedSize(true) - addMenuProvider(ShelfMenuProvider(view.context, childFragmentManager, viewModel)) + addMenuProvider(ShelfMenuProvider(binding.root.context, childFragmentManager, viewModel)) viewModel.content.observe(viewLifecycleOwner, ::onListChanged) viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) @@ -136,7 +136,7 @@ class ShelfFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, ) } diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt index d00601406..842699dfc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt @@ -8,11 +8,11 @@ import androidx.core.view.MenuProvider import androidx.fragment.app.FragmentManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.dialog.RememberSelectionDialogListener +import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener +import org.koitharu.kotatsu.core.util.ext.startOfDay import org.koitharu.kotatsu.local.ui.ImportDialogFragment import org.koitharu.kotatsu.shelf.ui.config.ShelfSettingsActivity import org.koitharu.kotatsu.shelf.ui.config.size.ShelfSizeBottomSheet -import org.koitharu.kotatsu.utils.ext.startOfDay import java.util.Date import java.util.concurrent.TimeUnit import com.google.android.material.R as materialR diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt index 4dfa746ee..a5c5a942e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt @@ -8,15 +8,15 @@ import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.flattenTo import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel -import org.koitharu.kotatsu.utils.ShareHelper -import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations class ShelfSelectionCallback( private val recyclerView: RecyclerView, diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt index 2103b208f..e48113db3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt @@ -8,13 +8,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.base.ui.util.ReversibleAction import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.util.ReversibleAction +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.history.domain.HistoryRepository @@ -36,8 +38,6 @@ import org.koitharu.kotatsu.shelf.domain.ShelfSection import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt index 0043cd052..85baded5e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt @@ -6,9 +6,9 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.NestedScrollStateHandle -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.list.fastscroll.FastScroller +import org.koitharu.kotatsu.core.ui.list.NestedScrollStateHandle +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.adapter.emptyHintAD import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt index bf2c3e0fe..c0e561475 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt @@ -7,19 +7,19 @@ import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.NestedScrollStateHandle -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.base.ui.list.SectionedSelectionController -import org.koitharu.kotatsu.base.ui.list.decor.AbstractSelectionItemDecoration -import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.ui.list.NestedScrollStateHandle +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController +import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration +import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.util.ext.removeItemDecoration +import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.databinding.ItemListGroupBinding import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.adapter.mangaGridItemAD import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel -import org.koitharu.kotatsu.utils.ext.removeItemDecoration -import org.koitharu.kotatsu.utils.ext.setTextAndVisible fun shelfGroupAD( sharedPool: RecyclerView.RecycledViewPool, diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt index c4dce1804..6697d0367 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt @@ -12,7 +12,7 @@ import androidx.core.view.updatePadding import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityShelfSettingsBinding import com.google.android.material.R as materialR @@ -31,9 +31,9 @@ class ShelfSettingsActivity : setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } - binding.buttonDone.setOnClickListener(this) + viewBinding.buttonDone.setOnClickListener(this) val settingsAdapter = ShelfSettingsAdapter(this) - with(binding.recyclerView) { + with(viewBinding.recyclerView) { setHasFixedSize(true) adapter = settingsAdapter reorderHelper = ItemTouchHelper(SectionsReorderCallback()).also { @@ -58,14 +58,14 @@ class ShelfSettingsActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( bottom = insets.bottom, ) - binding.toolbar.updateLayoutParams { + viewBinding.toolbar.updateLayoutParams { topMargin = insets.top } } diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt index 4b73dc9ef..2897e3eb6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt @@ -7,10 +7,10 @@ import android.widget.CompoundButton import androidx.core.view.updatePaddingRelative import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding import org.koitharu.kotatsu.databinding.ItemShelfSectionDraggableBinding import org.koitharu.kotatsu.shelf.domain.ShelfSection -import org.koitharu.kotatsu.utils.ext.setChecked @SuppressLint("ClickableViewAccessibility") fun shelfSectionAD( diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt index fb09af8b1..6d9ac2bde 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt @@ -5,14 +5,14 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.combine -import org.koitharu.kotatsu.base.ui.BaseViewModel import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.parsers.util.move import org.koitharu.kotatsu.shelf.domain.ShelfSection -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.move import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt index 9677f8d4e..26f74d59b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt @@ -9,11 +9,11 @@ import com.google.android.material.slider.LabelFormatter import com.google.android.material.slider.Slider import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseBottomSheet import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BaseBottomSheet +import org.koitharu.kotatsu.core.util.ext.setValueRounded +import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter import org.koitharu.kotatsu.databinding.SheetShelfSizeBinding -import org.koitharu.kotatsu.utils.ext.setValueRounded -import org.koitharu.kotatsu.utils.progress.IntPercentLabelFormatter import javax.inject.Inject @AndroidEntryPoint @@ -26,13 +26,13 @@ class ShelfSizeBottomSheet : lateinit var settings: AppSettings private var labelFormatter: LabelFormatter? = null - override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetShelfSizeBinding { + override fun onCreateViewBinding(inflater: LayoutInflater, container: ViewGroup?): SheetShelfSizeBinding { return SheetShelfSizeBinding.inflate(inflater, container, false) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - labelFormatter = IntPercentLabelFormatter(view.context) + override fun onViewBindingCreated(binding: SheetShelfSizeBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) + labelFormatter = IntPercentLabelFormatter(binding.root.context) binding.sliderGrid.addOnChangeListener(this) binding.buttonSmall.setOnClickListener(this) binding.buttonLarge.setOnClickListener(this) @@ -47,11 +47,11 @@ class ShelfSizeBottomSheet : override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) { settings.gridSize = value.toInt() - binding.textViewLabel.text = labelFormatter?.getFormattedValue(value) + requireViewBinding().textViewLabel.text = labelFormatter?.getFormattedValue(value) } override fun onClick(v: View) { - val slider = binding.sliderGrid + val slider = requireViewBinding().sliderGrid when (v.id) { R.id.button_small -> slider.setValueRounded(slider.value - slider.stepSize) R.id.button_large -> slider.setValueRounded(slider.value + slider.stepSize) diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt index 14c4561d8..873d7750e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt @@ -7,9 +7,9 @@ import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toMangaTags +import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.suggestions.data.SuggestionEntity -import org.koitharu.kotatsu.utils.ext.mapItems import javax.inject.Inject class SuggestionRepository @Inject constructor( diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt index 691928fa8..a408dd722 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.suggestions.domain +import org.koitharu.kotatsu.core.util.ext.almostEquals import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.utils.ext.almostEquals class TagsBlacklist( private val tags: Set, diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt index 4e225378d..9c38cf50c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt @@ -9,10 +9,9 @@ import androidx.fragment.app.commit import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner -import kotlin.text.Typography.dagger @AndroidEntryPoint class SuggestionsActivity : @@ -20,7 +19,7 @@ class SuggestionsActivity : AppBarOwner { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,7 +36,7 @@ class SuggestionsActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt index a1c8ad796..17fdb6830 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt @@ -4,24 +4,24 @@ import android.os.Bundle import android.view.Menu import android.view.MenuInflater import android.view.MenuItem -import android.view.View import androidx.appcompat.view.ActionMode import androidx.core.view.MenuProvider import androidx.fragment.app.viewModels import com.google.android.material.snackbar.Snackbar import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.settings.SettingsActivity -import org.koitharu.kotatsu.utils.ext.addMenuProvider class SuggestionsFragment : MangaListFragment() { override val viewModel by viewModels() override val isSwipeRefreshEnabled = false - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) addMenuProvider(SuggestionMenuProvider()) } @@ -42,16 +42,18 @@ class SuggestionsFragment : MangaListFragment() { R.id.action_update -> { SuggestionsWorker.startNow(requireContext()) Snackbar.make( - binding.recyclerView, + requireViewBinding().recyclerView, R.string.feed_will_update_soon, Snackbar.LENGTH_LONG, ).show() true } + R.id.action_settings -> { startActivity(SettingsActivity.newSuggestionsSettingsIntent(requireContext())) true } + else -> false } } diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt index bbb548e77..acf3fe5d1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt @@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.onStart import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -16,8 +18,6 @@ import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.onFirst import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index 23f1f2766..e96b56930 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -38,6 +38,12 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.distinctById import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.almostEquals +import org.koitharu.kotatsu.core.util.ext.asArrayList +import org.koitharu.kotatsu.core.util.ext.flatten +import org.koitharu.kotatsu.core.util.ext.takeMostFrequent +import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull +import org.koitharu.kotatsu.core.util.ext.trySetForeground import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.history.domain.HistoryRepository @@ -45,18 +51,12 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.suggestions.domain.MangaSuggestion import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository import org.koitharu.kotatsu.suggestions.domain.TagsBlacklist -import org.koitharu.kotatsu.utils.ext.almostEquals -import org.koitharu.kotatsu.utils.ext.asArrayList -import org.koitharu.kotatsu.utils.ext.flatten -import org.koitharu.kotatsu.utils.ext.printStackTraceDebug -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.takeMostFrequent -import org.koitharu.kotatsu.utils.ext.toBitmapOrNull -import org.koitharu.kotatsu.utils.ext.trySetForeground +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.concurrent.TimeUnit import kotlin.math.pow import kotlin.random.Random @@ -74,6 +74,10 @@ class SuggestionsWorker @AssistedInject constructor( ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { + if (!appSettings.isSuggestionsEnabled) { + suggestionRepository.clear() + return Result.success() + } trySetForeground() val count = doWorkImpl() val outputData = workDataOf(DATA_COUNT to count) @@ -112,10 +116,6 @@ class SuggestionsWorker @AssistedInject constructor( } private suspend fun doWorkImpl(): Int { - if (!appSettings.isSuggestionsEnabled) { - suggestionRepository.clear() - return 0 - } val seed = ( historyRepository.getList(0, 20) + favouritesRepository.getLastManga(20) diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt index a3792664f..822c5736f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt @@ -5,10 +5,10 @@ import okhttp3.OkHttpClient import okhttp3.Request import org.json.JSONObject import org.koitharu.kotatsu.core.exceptions.SyncApiException +import org.koitharu.kotatsu.core.util.ext.toRequestBody import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.parseJson import org.koitharu.kotatsu.parsers.util.removeSurrounding -import org.koitharu.kotatsu.utils.ext.toRequestBody import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt index cee53bdb0..7e211e3d4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt @@ -7,7 +7,7 @@ import androidx.annotation.WorkerThread import dagger.Reusable import dagger.hilt.android.qualifiers.ApplicationContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty +import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty import javax.inject.Inject @Reusable diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt b/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt index 32cd68134..ba00c6285 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt @@ -23,7 +23,7 @@ import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.TABLE_FAVOURITES import org.koitharu.kotatsu.core.db.TABLE_FAVOURITE_CATEGORIES import org.koitharu.kotatsu.core.db.TABLE_HISTORY -import org.koitharu.kotatsu.utils.ext.processLifecycleScope +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Provider diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt b/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt index 089cb6a9c..e8c740c1b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt @@ -26,15 +26,15 @@ import org.koitharu.kotatsu.core.db.TABLE_TAGS import org.koitharu.kotatsu.core.logs.LoggersModule import org.koitharu.kotatsu.core.network.GZipInterceptor import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.parseJsonOrNull +import org.koitharu.kotatsu.core.util.ext.toContentValues +import org.koitharu.kotatsu.core.util.ext.toJson +import org.koitharu.kotatsu.core.util.ext.toRequestBody import org.koitharu.kotatsu.parsers.util.json.mapJSONTo import org.koitharu.kotatsu.sync.data.SyncAuthApi import org.koitharu.kotatsu.sync.data.SyncAuthenticator import org.koitharu.kotatsu.sync.data.SyncInterceptor import org.koitharu.kotatsu.sync.data.SyncSettings -import org.koitharu.kotatsu.utils.ext.parseJsonOrNull -import org.koitharu.kotatsu.utils.ext.toContentValues -import org.koitharu.kotatsu.utils.ext.toJson -import org.koitharu.kotatsu.utils.ext.toRequestBody import java.util.concurrent.TimeUnit private const val FIELD_TIMESTAMP = "timestamp" diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt index cf24fb7b9..cf234eb23 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt @@ -19,12 +19,12 @@ import androidx.transition.TransitionManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.databinding.ActivitySyncAuthBinding import org.koitharu.kotatsu.sync.data.SyncSettings import org.koitharu.kotatsu.sync.domain.SyncAuthResult -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.getParcelableExtraCompat @AndroidEntryPoint class SyncAuthActivity : BaseActivity(), View.OnClickListener, FragmentResultListener { @@ -41,14 +41,14 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi accountAuthenticatorResponse = intent.getParcelableExtraCompat(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE) accountAuthenticatorResponse?.onRequestContinued() - binding.buttonCancel.setOnClickListener(this) - binding.buttonNext.setOnClickListener(this) - binding.buttonBack.setOnClickListener(this) - binding.buttonDone.setOnClickListener(this) - binding.layoutProgress.setOnClickListener(this) - binding.buttonSettings.setOnClickListener(this) - binding.editEmail.addTextChangedListener(EmailTextWatcher(binding.buttonNext)) - binding.editPassword.addTextChangedListener(PasswordTextWatcher(binding.buttonDone)) + viewBinding.buttonCancel.setOnClickListener(this) + viewBinding.buttonNext.setOnClickListener(this) + viewBinding.buttonBack.setOnClickListener(this) + viewBinding.buttonDone.setOnClickListener(this) + viewBinding.layoutProgress.setOnClickListener(this) + viewBinding.buttonSettings.setOnClickListener(this) + viewBinding.editEmail.addTextChangedListener(EmailTextWatcher(viewBinding.buttonNext)) + viewBinding.editPassword.addTextChangedListener(PasswordTextWatcher(viewBinding.buttonDone)) onBackPressedDispatcher.addCallback(pageBackCallback) @@ -65,7 +65,7 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi override fun onWindowInsetsChanged(insets: Insets) { val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding) - binding.root.setPadding( + viewBinding.root.setPadding( basePadding + insets.left, basePadding + insets.top, basePadding + insets.right, @@ -81,21 +81,21 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi } R.id.button_next -> { - binding.groupLogin.isVisible = false - binding.groupPassword.isVisible = true + viewBinding.groupLogin.isVisible = false + viewBinding.groupPassword.isVisible = true pageBackCallback.update() } R.id.button_back -> { - binding.groupPassword.isVisible = false - binding.groupLogin.isVisible = true + viewBinding.groupPassword.isVisible = false + viewBinding.groupLogin.isVisible = true pageBackCallback.update() } R.id.button_done -> { viewModel.obtainToken( - email = binding.editEmail.text.toString(), - password = binding.editPassword.text.toString(), + email = viewBinding.editEmail.text.toString(), + password = viewBinding.editPassword.text.toString(), ) } @@ -120,11 +120,11 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi } private fun onLoadingStateChanged(isLoading: Boolean) { - if (isLoading == binding.layoutProgress.isVisible) { + if (isLoading == viewBinding.layoutProgress.isVisible) { return } - TransitionManager.beginDelayedTransition(binding.root, Fade()) - binding.layoutProgress.isVisible = isLoading + TransitionManager.beginDelayedTransition(viewBinding.root, Fade()) + viewBinding.layoutProgress.isVisible = isLoading pageBackCallback.update() } @@ -198,13 +198,13 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi private inner class PageBackCallback : OnBackPressedCallback(false) { override fun handleOnBackPressed() { - binding.groupLogin.isVisible = true - binding.groupPassword.isVisible = false + viewBinding.groupLogin.isVisible = true + viewBinding.groupPassword.isVisible = false update() } fun update() { - isEnabled = !binding.layoutProgress.isVisible && binding.groupPassword.isVisible + isEnabled = !viewBinding.layoutProgress.isVisible && viewBinding.groupPassword.isVisible } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt index d86bc3c8d..6aea529a5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt @@ -7,11 +7,11 @@ import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty import org.koitharu.kotatsu.sync.data.SyncAuthApi import org.koitharu.kotatsu.sync.domain.SyncAuthResult -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.ext.ifNullOrEmpty import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt index 970c33938..735adb19a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.sync.ui import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.view.ViewGroup.MarginLayoutParams import android.widget.ArrayAdapter @@ -13,7 +12,7 @@ import androidx.fragment.app.FragmentManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.databinding.PreferenceDialogAutocompletetextviewBinding import org.koitharu.kotatsu.settings.DomainValidator import org.koitharu.kotatsu.sync.data.SyncSettings @@ -26,7 +25,7 @@ class SyncHostDialogFragment : AlertDialogFragment { - topMargin = view.resources.getDimensionPixelOffset(R.dimen.screen_padding) + topMargin = binding.root.resources.getDimensionPixelOffset(R.dimen.screen_padding) bottomMargin = topMargin } binding.message.setText(R.string.sync_host_description) - val entries = view.resources.getStringArray(R.array.sync_host_list) + val entries = binding.root.resources.getStringArray(R.array.sync_host_list) val editText = binding.edit editText.setText(syncSettings.host) editText.threshold = 0 - editText.setAdapter(ArrayAdapter(view.context, android.R.layout.simple_spinner_dropdown_item, entries)) + editText.setAdapter(ArrayAdapter(binding.root.context, android.R.layout.simple_spinner_dropdown_item, entries)) binding.dropdown.setOnClickListener { editText.showDropDown() } @@ -60,7 +62,7 @@ class SyncHostDialogFragment : AlertDialogFragment { - val result = binding.edit.text?.toString().orEmpty() + val result = requireViewBinding().edit.text?.toString().orEmpty() syncSettings.host = result parentFragmentManager.setFragmentResult(REQUEST_KEY, bundleOf(KEY_HOST to result)) } diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt index ff0157857..cb9dcecca 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt @@ -7,10 +7,10 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.onError +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.sync.domain.SyncHelper -import org.koitharu.kotatsu.utils.ext.onError -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable class FavouritesSyncAdapter(context: Context) : AbstractThreadedSyncAdapter(context, true) { diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt index 9297ea5fc..279724dd7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt @@ -7,10 +7,10 @@ import android.content.Context import android.content.SyncResult import android.os.Bundle import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.onError +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.sync.domain.SyncHelper -import org.koitharu.kotatsu.utils.ext.onError -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable class HistorySyncAdapter(context: Context) : AbstractThreadedSyncAdapter(context, true) { diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt index ac4d538af..b06b063be 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt @@ -12,10 +12,12 @@ import coil.ImageLoader import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseFragment -import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener -import org.koitharu.kotatsu.base.ui.list.decor.TypedSpacingItemDecoration import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver +import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener +import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration +import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.databinding.FragmentFeedBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.list.ui.adapter.MangaListListener @@ -26,8 +28,6 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.tracker.ui.feed.adapter.FeedAdapter import org.koitharu.kotatsu.tracker.work.TrackWorker -import org.koitharu.kotatsu.utils.ext.addMenuProvider -import org.koitharu.kotatsu.utils.ext.getThemeColor import javax.inject.Inject @AndroidEntryPoint @@ -43,13 +43,13 @@ class FeedFragment : private var feedAdapter: FeedAdapter? = null - override fun onInflateView( + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, ) = FragmentFeedBinding.inflate(inflater, container, false) - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) + override fun onViewBindingCreated(binding: FragmentFeedBinding, savedInstanceState: Bundle?) { + super.onViewBindingCreated(binding, savedInstanceState) feedAdapter = FeedAdapter(coil, viewLifecycleOwner, this) with(binding.recyclerView) { adapter = feedAdapter @@ -80,7 +80,7 @@ class FeedFragment : viewModel.onFeedCleared.observe(viewLifecycleOwner) { onFeedCleared() } - TrackWorker.getIsRunningLiveData(view.context.applicationContext) + TrackWorker.getIsRunningLiveData(binding.root.context.applicationContext) .observe(viewLifecycleOwner, this::onIsTrackerRunningChanged) } @@ -90,7 +90,7 @@ class FeedFragment : } override fun onWindowInsetsChanged(insets: Insets) { - binding.recyclerView.updatePadding( + requireViewBinding().recyclerView.updatePadding( bottom = insets.bottom, ) } @@ -115,7 +115,7 @@ class FeedFragment : private fun onFeedCleared() { val snackbar = Snackbar.make( - binding.recyclerView, + requireViewBinding().recyclerView, R.string.updates_feed_cleared, Snackbar.LENGTH_LONG, ) @@ -124,7 +124,7 @@ class FeedFragment : } private fun onIsTrackerRunningChanged(isRunning: Boolean) { - binding.swipeRefreshLayout.isRefreshing = isRunning + requireViewBinding().swipeRefreshLayout.isRefreshing = isRunning } override fun onScrolledToEnd() { diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt index 3f154324c..88d888039 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt @@ -7,7 +7,7 @@ import android.view.MenuItem import android.view.View import androidx.core.view.MenuProvider import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.dialog.CheckBoxAlertDialog +import org.koitharu.kotatsu.core.ui.dialog.CheckBoxAlertDialog import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.tracker.work.TrackWorker diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt index 2a5c6bcc5..5c80f4a09 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt @@ -6,17 +6,17 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseViewModel -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo +import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.tracker.domain.model.TrackingLogItem import org.koitharu.kotatsu.tracker.ui.feed.model.toFeedItem -import org.koitharu.kotatsu.utils.SingleLiveEvent -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.daysDiff import java.util.Date import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt index a0ddea045..64963e946 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.core.ui.DateTimeAgo +import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.adapter.MangaListListener import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD import org.koitharu.kotatsu.list.ui.adapter.errorFooterAD diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt index ce123e0b2..c7b57d4b6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt @@ -4,16 +4,16 @@ import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.disposeImageRequest +import org.koitharu.kotatsu.core.util.ext.enqueueWith +import org.koitharu.kotatsu.core.util.ext.isBold +import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemFeedBinding import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.ui.feed.model.FeedItem -import org.koitharu.kotatsu.utils.ext.disposeImageRequest -import org.koitharu.kotatsu.utils.ext.enqueueWith -import org.koitharu.kotatsu.utils.ext.isBold -import org.koitharu.kotatsu.utils.ext.newImageRequest -import org.koitharu.kotatsu.utils.ext.source fun feedItemAD( coil: ImageLoader, diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt index 56f213dd1..047b0d7ca 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt @@ -9,7 +9,7 @@ import androidx.fragment.app.commit import com.google.android.material.appbar.AppBarLayout import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner @@ -19,7 +19,7 @@ class UpdatesActivity : AppBarOwner { override val appBar: AppBarLayout - get() = binding.appbar + get() = viewBinding.appbar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -36,7 +36,7 @@ class UpdatesActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.root.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt index bebfb7a58..bb46a503f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt @@ -10,6 +10,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE @@ -23,8 +25,6 @@ import org.koitharu.kotatsu.list.ui.model.toListDetailedModel import org.koitharu.kotatsu.list.ui.model.toListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.utils.asFlowLiveData -import org.koitharu.kotatsu.utils.ext.onFirst import javax.inject.Inject @HiltViewModel 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 fc32bf3ee..06e8d25c7 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 @@ -41,14 +41,14 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.logs.FileLogger import org.koitharu.kotatsu.core.logs.TrackerLogger import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull +import org.koitharu.kotatsu.core.util.ext.trySetForeground import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.tracker.domain.Tracker import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates -import org.koitharu.kotatsu.utils.ext.runCatchingCancellable -import org.koitharu.kotatsu.utils.ext.toBitmapOrNull -import org.koitharu.kotatsu.utils.ext.trySetForeground import java.util.concurrent.TimeUnit @HiltWorker @@ -84,9 +84,7 @@ class TrackWorker @AssistedInject constructor( if (!settings.isTrackerEnabled) { return Result.success(workDataOf(0, 0)) } - if (TAG in tags) { // not expedited - trySetForeground() - } + trySetForeground() val tracks = tracker.getAllTracks() logger.log("Total ${tracks.size} tracks") if (tracks.isEmpty()) { diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LayoutManagerExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/LayoutManagerExt.kt deleted file mode 100644 index 57e9c4a8f..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/LayoutManagerExt.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.koitharu.kotatsu.utils.ext - -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.StaggeredGridLayoutManager - -internal val RecyclerView.LayoutManager?.firstVisibleItemPosition - get() = when (this) { - is LinearLayoutManager -> findFirstVisibleItemPosition() - is StaggeredGridLayoutManager -> findFirstVisibleItemPositions(null)[0] - else -> 0 - } - -internal val RecyclerView.LayoutManager?.isLayoutReversed - get() = when (this) { - is LinearLayoutManager -> reverseLayout - is StaggeredGridLayoutManager -> reverseLayout - else -> false - } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt index f88a0525a..fc263b5d7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt @@ -12,11 +12,11 @@ import coil.size.Size import coil.transform.RoundedCornersTransformation import kotlinx.coroutines.runBlocking import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent +import org.koitharu.kotatsu.core.parser.MangaIntent +import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.replaceWith -import org.koitharu.kotatsu.utils.ext.getDrawableOrThrow class RecentListFactory( private val context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt index b5d3f5eb0..15e453361 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt @@ -13,10 +13,10 @@ import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.BaseActivity -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.prefs.AppWidgetConfig +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter import org.koitharu.kotatsu.widget.shelf.model.CategoryItem @@ -41,10 +41,10 @@ class ShelfConfigActivity : setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) } adapter = CategorySelectAdapter(this) - binding.recyclerView.adapter = adapter - binding.buttonDone.isVisible = true - binding.buttonDone.setOnClickListener(this) - binding.fabAdd.hide() + viewBinding.recyclerView.adapter = adapter + viewBinding.buttonDone.isVisible = true + viewBinding.buttonDone.setOnClickListener(this) + viewBinding.fabAdd.hide() val appWidgetId = intent?.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID, @@ -57,7 +57,7 @@ class ShelfConfigActivity : viewModel.checkedId = config.categoryId viewModel.content.observe(this, this::onContentChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(binding.recyclerView, null)) + viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) } override fun onClick(v: View) { @@ -79,17 +79,17 @@ class ShelfConfigActivity : } override fun onWindowInsetsChanged(insets: Insets) { - binding.fabAdd.updateLayoutParams { + viewBinding.fabAdd.updateLayoutParams { rightMargin = topMargin + insets.right leftMargin = topMargin + insets.left bottomMargin = topMargin + insets.bottom } - binding.recyclerView.updatePadding( + viewBinding.recyclerView.updatePadding( left = insets.left, right = insets.right, bottom = insets.bottom, ) - with(binding.toolbar) { + with(viewBinding.toolbar) { updatePadding( left = insets.left, right = insets.right, diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt index d8d2f2599..1208cb5dd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt @@ -6,9 +6,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine -import org.koitharu.kotatsu.base.ui.BaseViewModel +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.utils.asFlowLiveData import org.koitharu.kotatsu.widget.shelf.model.CategoryItem import javax.inject.Inject diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt index 74caff390..fb914916f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt @@ -12,12 +12,12 @@ import coil.size.Size import coil.transform.RoundedCornersTransformation import kotlinx.coroutines.runBlocking import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.domain.MangaIntent +import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.prefs.AppWidgetConfig +import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.replaceWith -import org.koitharu.kotatsu.utils.ext.getDrawableOrThrow class ShelfListFactory( private val context: Context, diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt index 39f90c22e..10fac5806 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.widget.shelf.adapter import androidx.recyclerview.widget.DiffUtil import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.widget.shelf.model.CategoryItem class CategorySelectAdapter( @@ -30,4 +30,4 @@ class CategorySelectAdapter( return super.getChangePayload(oldItem, newItem) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt index ce4ded99d..9de2ab3b8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt @@ -2,14 +2,14 @@ package org.koitharu.kotatsu.widget.shelf.adapter import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.databinding.ItemCategoryCheckableSingleBinding import org.koitharu.kotatsu.widget.shelf.model.CategoryItem fun categorySelectItemAD( clickListener: OnListItemClickListener ) = adapterDelegateViewBinding( - { inflater, parent -> ItemCategoryCheckableSingleBinding.inflate(inflater, parent, false) } + { inflater, parent -> ItemCategoryCheckableSingleBinding.inflate(inflater, parent, false) }, ) { itemView.setOnClickListener { @@ -22,4 +22,4 @@ fun categorySelectItemAD( isChecked = item.isSelected } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout-w600dp/activity_categories.xml b/app/src/main/res/layout-w600dp/activity_categories.xml index fbd53ee8b..a7c07c39e 100644 --- a/app/src/main/res/layout-w600dp/activity_categories.xml +++ b/app/src/main/res/layout-w600dp/activity_categories.xml @@ -64,7 +64,7 @@ app:icon="@drawable/ic_add" app:layout_anchor="@id/recyclerView" app:layout_anchorGravity="bottom|end" - app:layout_behavior="org.koitharu.kotatsu.base.ui.util.ShrinkOnScrollBehavior" + app:layout_behavior="org.koitharu.kotatsu.core.ui.util.ShrinkOnScrollBehavior" app:layout_dodgeInsetEdges="bottom" /> diff --git a/app/src/main/res/layout-w600dp/activity_main.xml b/app/src/main/res/layout-w600dp/activity_main.xml index 6e09a349a..320e64005 100644 --- a/app/src/main/res/layout-w600dp/activity_main.xml +++ b/app/src/main/res/layout-w600dp/activity_main.xml @@ -40,7 +40,7 @@ android:stateListAnimator="@null" app:liftOnScroll="false"> - - - - - diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index 13d34ca0d..11ca45679 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -48,7 +48,7 @@ app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.BottomSheet" tools:visibility="visible"> - - + - - - - - - - - - - - - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_list.xml b/app/src/main/res/layout/fragment_list.xml index 086aa7c8e..84c59071a 100644 --- a/app/src/main/res/layout/fragment_list.xml +++ b/app/src/main/res/layout/fragment_list.xml @@ -11,7 +11,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - diff --git a/app/src/main/res/layout/fragment_list_simple.xml b/app/src/main/res/layout/fragment_list_simple.xml index 49beabba9..ff3ae6128 100644 --- a/app/src/main/res/layout/fragment_list_simple.xml +++ b/app/src/main/res/layout/fragment_list_simple.xml @@ -7,7 +7,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - \ No newline at end of file + diff --git a/app/src/main/res/layout/item_checkable_new.xml b/app/src/main/res/layout/item_checkable_new.xml index 6e523dad8..cc7a4847b 100644 --- a/app/src/main/res/layout/item_checkable_new.xml +++ b/app/src/main/res/layout/item_checkable_new.xml @@ -1,5 +1,5 @@ - \ No newline at end of file + tools:text="@tools:sample/full_names" /> diff --git a/app/src/main/res/layout/item_color_scheme.xml b/app/src/main/res/layout/item_color_scheme.xml index 9389a70c2..58ec38333 100644 --- a/app/src/main/res/layout/item_color_scheme.xml +++ b/app/src/main/res/layout/item_color_scheme.xml @@ -32,7 +32,7 @@ app:layout_constraintTop_toTopOf="parent" tools:ignore="HardcodedText" /> - - - - - - - - - \ No newline at end of file + app:chipSpacingVertical="6dp" /> diff --git a/app/src/main/res/layout/item_storage.xml b/app/src/main/res/layout/item_storage.xml index 3df31113f..72e9f513b 100644 --- a/app/src/main/res/layout/item_storage.xml +++ b/app/src/main/res/layout/item_storage.xml @@ -11,7 +11,7 @@ android:paddingEnd="?listPreferredItemPaddingEnd" android:paddingBottom="16dp"> - - \ No newline at end of file + diff --git a/app/src/main/res/layout/layout_memory_usage.xml b/app/src/main/res/layout/layout_memory_usage.xml index d03feaa4e..6d6212caa 100644 --- a/app/src/main/res/layout/layout_memory_usage.xml +++ b/app/src/main/res/layout/layout_memory_usage.xml @@ -32,7 +32,7 @@ - - @@ -23,7 +23,7 @@ android:visibility="gone" tools:visibility="visible" /> - + - - - - + - - diff --git a/app/src/main/res/layout/sheet_reader_config.xml b/app/src/main/res/layout/sheet_reader_config.xml index da53770e9..44e59ffee 100644 --- a/app/src/main/res/layout/sheet_reader_config.xml +++ b/app/src/main/res/layout/sheet_reader_config.xml @@ -7,7 +7,7 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - - - - - + Date: Fri, 19 May 2023 14:52:07 +0300 Subject: [PATCH 03/90] Limit cache max-age and action to clear cache manually --- .../org/koitharu/kotatsu/core/AppModule.kt | 11 +++++- .../core/network/CacheLimitInterceptor.kt | 26 +++++++++++++ .../kotatsu/core/network/CommonHeaders.kt | 1 + .../kotatsu/core/prefs/AppSettings.kt | 1 + .../settings/HistorySettingsFragment.kt | 38 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/pref_history.xml | 6 +++ 7 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt index 6e53e3736..8c59de5d9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow +import okhttp3.Cache import okhttp3.CookieJar import okhttp3.OkHttpClient import org.koitharu.kotatsu.BuildConfig @@ -90,14 +91,19 @@ interface AppModule { @Provides @Singleton - fun provideOkHttpClient( + fun provideHttpCache( localStorageManager: LocalStorageManager, + ): Cache = localStorageManager.createHttpCache() + + @Provides + @Singleton + fun provideOkHttpClient( + cache: Cache, commonHeadersInterceptor: CommonHeadersInterceptor, mirrorSwitchInterceptor: MirrorSwitchInterceptor, cookieJar: CookieJar, settings: AppSettings, ): OkHttpClient { - val cache = localStorageManager.createHttpCache() return OkHttpClient.Builder().apply { connectTimeout(20, TimeUnit.SECONDS) readTimeout(60, TimeUnit.SECONDS) @@ -108,6 +114,7 @@ interface AppModule { bypassSSLErrors() } cache(cache) + addNetworkInterceptor(CacheLimitInterceptor()) addInterceptor(GZipInterceptor()) addInterceptor(commonHeadersInterceptor) addInterceptor(CloudFlareInterceptor()) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt new file mode 100644 index 000000000..52710c57b --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt @@ -0,0 +1,26 @@ +package org.koitharu.kotatsu.core.network + +import okhttp3.CacheControl +import okhttp3.Interceptor +import okhttp3.Response +import java.util.concurrent.TimeUnit + +class CacheLimitInterceptor : Interceptor { + + private val defaultMaxAge = TimeUnit.HOURS.toSeconds(1) + private val defaultCacheControl = CacheControl.Builder() + .maxAge(defaultMaxAge.toInt(), TimeUnit.SECONDS) + .build() + .toString() + + override fun intercept(chain: Interceptor.Chain): Response { + val response = chain.proceed(chain.request()) + val responseCacheControl = CacheControl.parse(response.headers) + if (responseCacheControl.noStore || responseCacheControl.maxAgeSeconds <= defaultMaxAge) { + return response + } + return response.newBuilder() + .header(CommonHeaders.CACHE_CONTROL, defaultCacheControl) + .build() + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt index 943e08f2e..f8976acd6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt @@ -13,6 +13,7 @@ object CommonHeaders { const val CONTENT_ENCODING = "Content-Encoding" const val ACCEPT_ENCODING = "Accept-Encoding" const val AUTHORIZATION = "Authorization" + const val CACHE_CONTROL = "Cache-Control" val CACHE_CONTROL_NO_STORE: CacheControl get() = CacheControl.Builder().noStore().build() 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 669b7ea41..03d0c04e8 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 @@ -345,6 +345,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { 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_HTTP_CACHE_CLEAR = "http_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" 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 4ced54381..34b2fdb37 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt @@ -8,7 +8,10 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.runInterruptible +import okhttp3.Cache import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.os.ShortcutsUpdater @@ -39,6 +42,9 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach @Inject lateinit var cookieJar: MutableCookieJar + @Inject + lateinit var cache: Cache + @Inject lateinit var shortcutsUpdater: ShortcutsUpdater @@ -52,6 +58,7 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach super.onViewCreated(view, savedInstanceState) findPreference(AppSettings.KEY_PAGES_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.PAGES) findPreference(AppSettings.KEY_THUMBS_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.THUMBS) + findPreference(AppSettings.KEY_HTTP_CACHE_CLEAR)?.bindSummaryToHttpCacheSize() findPreference(AppSettings.KEY_SEARCH_HISTORY_CLEAR)?.let { pref -> viewLifecycleScope.launch { lifecycle.awaitStateAtLeast(Lifecycle.State.RESUMED) @@ -90,6 +97,11 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach true } + AppSettings.KEY_HTTP_CACHE_CLEAR -> { + clearHttpCache() + true + } + AppSettings.KEY_UPDATES_FEED_CLEAR -> { viewLifecycleScope.launch { trackerRepo.clearLogs() @@ -131,6 +143,32 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach summary = FileSize.BYTES.format(context, size) } + private fun Preference.bindSummaryToHttpCacheSize() = viewLifecycleScope.launch { + val size = runInterruptible(Dispatchers.IO) { cache.size() } + summary = FileSize.BYTES.format(context, size) + } + + private fun clearHttpCache() { + val preference = findPreference(AppSettings.KEY_HTTP_CACHE_CLEAR) ?: return + val ctx = preference.context.applicationContext + viewLifecycleScope.launch { + try { + preference.isEnabled = false + val size = runInterruptible(Dispatchers.IO) { + cache.evictAll() + cache.size() + } + preference.summary = FileSize.BYTES.format(ctx, size) + } catch (e: CancellationException) { + throw e + } catch (e: Exception) { + preference.summary = e.getDisplayMessage(ctx.resources) + } finally { + preference.isEnabled = true + } + } + } + private fun clearSearchHistory(preference: Preference) { MaterialAlertDialogBuilder(context ?: return) .setTitle(R.string.clear_search_history) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 406703d2e..8cfb1c96f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -416,4 +416,5 @@ Do you want to receive personalized manga suggestions? Translations WebView not available: check if WebView provider is installed + Clear network cache diff --git a/app/src/main/res/xml/pref_history.xml b/app/src/main/res/xml/pref_history.xml index a7304418c..de6088bc8 100644 --- a/app/src/main/res/xml/pref_history.xml +++ b/app/src/main/res/xml/pref_history.xml @@ -39,6 +39,12 @@ android:summary="@string/computing_" android:title="@string/clear_pages_cache" /> + + Date: Fri, 19 May 2023 15:31:14 +0300 Subject: [PATCH 04/90] Fix focus changes on sync authorization screen --- .../main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt index cf234eb23..1ef83da4a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt @@ -84,12 +84,14 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi viewBinding.groupLogin.isVisible = false viewBinding.groupPassword.isVisible = true pageBackCallback.update() + viewBinding.editPassword.requestFocus() } R.id.button_back -> { viewBinding.groupPassword.isVisible = false viewBinding.groupLogin.isVisible = true pageBackCallback.update() + viewBinding.editEmail.requestFocus() } R.id.button_done -> { @@ -200,6 +202,7 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi override fun handleOnBackPressed() { viewBinding.groupLogin.isVisible = true viewBinding.groupPassword.isVisible = false + viewBinding.editEmail.requestFocus() update() } From 3729b5f2f0f84c9822ec604eb572b731ca0720c3 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 20 May 2023 08:34:22 +0300 Subject: [PATCH 05/90] Share OkHttpClients --- .../org/koitharu/kotatsu/core/AppModule.kt | 68 +-------------- .../core/github/AppUpdateRepository.kt | 3 +- .../org/koitharu/kotatsu/core/logs/Loggers.kt | 4 +- .../kotatsu/core/network/HttpClients.kt | 11 +++ .../kotatsu/core/network/NetworkModule.kt | 87 +++++++++++++++++++ .../core/parser/MangaDataRepository.kt | 3 +- .../core/parser/MangaLoaderContextImpl.kt | 3 +- .../download/ui/worker/DownloadWorker.kt | 3 +- .../data/{TrackerLogger.kt => Qualifiers.kt} | 2 +- .../kotatsu/reader/domain/PageLoader.kt | 3 +- .../kotatsu/scrobbling/ScrobblingModule.kt | 73 ++++++---------- .../anilist/data/AniListRepository.kt | 10 ++- .../scrobbling/mal/data/MALRepository.kt | 10 ++- .../shikimori/data/ShikimoriRepository.kt | 10 ++- .../koitharu/kotatsu/sync/data/SyncAuthApi.kt | 3 +- 15 files changed, 161 insertions(+), 132 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt rename app/src/main/java/org/koitharu/kotatsu/local/data/{TrackerLogger.kt => Qualifiers.kt} (75%) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt index 8c59de5d9..cbf361112 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt @@ -4,7 +4,6 @@ import android.app.Application import android.content.Context import android.provider.SearchRecentSuggestions import android.text.Html -import android.util.AndroidRuntimeException import androidx.collection.arraySetOf import androidx.room.InvalidationTracker import coil.ComponentRegistry @@ -23,8 +22,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow -import okhttp3.Cache -import okhttp3.CookieJar import okhttp3.OkHttpClient import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.cache.ContentCache @@ -32,15 +29,11 @@ import org.koitharu.kotatsu.core.cache.MemoryContentCache import org.koitharu.kotatsu.core.cache.StubContentCache import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.network.* -import org.koitharu.kotatsu.core.network.cookies.AndroidCookieJar -import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar -import org.koitharu.kotatsu.core.network.cookies.PreferencesCookieJar import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.os.ShortcutsUpdater import org.koitharu.kotatsu.core.parser.MangaLoaderContextImpl import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.favicon.FaviconFetcher -import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.image.CoilImageGetter import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle import org.koitharu.kotatsu.core.util.IncognitoModeIndicator @@ -51,7 +44,6 @@ import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.CbzFetcher import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -60,16 +52,12 @@ import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider import org.koitharu.kotatsu.settings.backup.BackupObserver import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.widget.WidgetUpdater -import java.util.concurrent.TimeUnit import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) interface AppModule { - @Binds - fun bindCookieJar(androidCookieJar: MutableCookieJar): CookieJar - @Binds fun bindMangaLoaderContext(mangaLoaderContextImpl: MangaLoaderContextImpl): MangaLoaderContext @@ -78,53 +66,6 @@ interface AppModule { companion object { - @Provides - @Singleton - fun provideCookieJar( - @ApplicationContext context: Context - ): MutableCookieJar = try { - AndroidCookieJar() - } catch (e: AndroidRuntimeException) { - // WebView is not available - PreferencesCookieJar(context) - } - - @Provides - @Singleton - fun provideHttpCache( - localStorageManager: LocalStorageManager, - ): Cache = localStorageManager.createHttpCache() - - @Provides - @Singleton - fun provideOkHttpClient( - cache: Cache, - commonHeadersInterceptor: CommonHeadersInterceptor, - mirrorSwitchInterceptor: MirrorSwitchInterceptor, - cookieJar: CookieJar, - settings: AppSettings, - ): OkHttpClient { - return OkHttpClient.Builder().apply { - connectTimeout(20, TimeUnit.SECONDS) - readTimeout(60, TimeUnit.SECONDS) - writeTimeout(20, TimeUnit.SECONDS) - cookieJar(cookieJar) - dns(DoHManager(cache, settings)) - if (settings.isSSLBypassEnabled) { - bypassSSLErrors() - } - cache(cache) - addNetworkInterceptor(CacheLimitInterceptor()) - addInterceptor(GZipInterceptor()) - addInterceptor(commonHeadersInterceptor) - addInterceptor(CloudFlareInterceptor()) - addInterceptor(mirrorSwitchInterceptor) - if (BuildConfig.DEBUG) { - addInterceptor(CurlLoggingInterceptor()) - } - }.build() - } - @Provides @Singleton fun provideNetworkState( @@ -143,15 +84,10 @@ interface AppModule { @Singleton fun provideCoil( @ApplicationContext context: Context, - okHttpClient: OkHttpClient, + @MangaHttpClient okHttpClient: OkHttpClient, mangaRepositoryFactory: MangaRepository.Factory, pagesCache: PagesCache, ): ImageLoader { - val httpClientFactory = { - okHttpClient.newBuilder() - .cache(null) - .build() - } val diskCacheFactory = { val rootDir = context.externalCacheDir ?: context.cacheDir DiskCache.Builder() @@ -159,7 +95,7 @@ interface AppModule { .build() } return ImageLoader.Builder(context) - .okHttpClient(httpClientFactory) + .okHttpClient(okHttpClient.newBuilder().cache(null).build()) .interceptorDispatcher(Dispatchers.Default) .fetcherDispatcher(Dispatchers.IO) .decoderDispatcher(Dispatchers.Default) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt index 53a53d273..03047a807 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt @@ -13,6 +13,7 @@ import okhttp3.Request import org.json.JSONArray import org.json.JSONObject import org.koitharu.kotatsu.BuildConfig +import org.koitharu.kotatsu.core.network.BaseHttpClient import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.parsers.util.await @@ -36,7 +37,7 @@ private const val CONTENT_TYPE_APK = "application/vnd.android.package-archive" class AppUpdateRepository @Inject constructor( @ApplicationContext private val context: Context, private val settings: AppSettings, - private val okHttp: OkHttpClient, + @BaseHttpClient private val okHttp: OkHttpClient, ) { private val availableUpdate = MutableStateFlow(null) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt b/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt index 008ca7d92..47eeea605 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt @@ -3,9 +3,9 @@ package org.koitharu.kotatsu.core.logs import javax.inject.Qualifier @Qualifier -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) annotation class TrackerLogger @Qualifier -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) annotation class SyncLogger diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt new file mode 100644 index 000000000..45e1b5d45 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.core.network + +import javax.inject.Qualifier + +@Qualifier +@Retention(AnnotationRetention.SOURCE) +annotation class BaseHttpClient + +@Qualifier +@Retention(AnnotationRetention.SOURCE) +annotation class MangaHttpClient 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 new file mode 100644 index 000000000..e528a21a8 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt @@ -0,0 +1,87 @@ +package org.koitharu.kotatsu.core.network + +import android.content.Context +import android.util.AndroidRuntimeException +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import okhttp3.Cache +import okhttp3.CookieJar +import okhttp3.OkHttpClient +import org.koitharu.kotatsu.BuildConfig +import org.koitharu.kotatsu.core.network.cookies.AndroidCookieJar +import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar +import org.koitharu.kotatsu.core.network.cookies.PreferencesCookieJar +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.local.data.LocalStorageManager +import java.util.concurrent.TimeUnit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +interface NetworkModule { + + @Binds + fun bindCookieJar(androidCookieJar: MutableCookieJar): CookieJar + + companion object { + + @Provides + @Singleton + fun provideCookieJar( + @ApplicationContext context: Context + ): MutableCookieJar = try { + AndroidCookieJar() + } catch (e: AndroidRuntimeException) { + // WebView is not available + PreferencesCookieJar(context) + } + + @Provides + @Singleton + fun provideHttpCache( + localStorageManager: LocalStorageManager, + ): Cache = localStorageManager.createHttpCache() + + @Provides + @Singleton + @BaseHttpClient + fun provideBaseHttpClient( + cache: Cache, + cookieJar: CookieJar, + settings: AppSettings, + ): OkHttpClient = OkHttpClient.Builder().apply { + connectTimeout(20, TimeUnit.SECONDS) + readTimeout(60, TimeUnit.SECONDS) + writeTimeout(20, TimeUnit.SECONDS) + cookieJar(cookieJar) + dns(DoHManager(cache, settings)) + if (settings.isSSLBypassEnabled) { + bypassSSLErrors() + } + cache(cache) + addInterceptor(GZipInterceptor()) + addInterceptor(CloudFlareInterceptor()) + if (BuildConfig.DEBUG) { + addInterceptor(CurlLoggingInterceptor()) + } + }.build() + + @Provides + @Singleton + @MangaHttpClient + fun provideMangaHttpClient( + @BaseHttpClient baseClient: OkHttpClient, + commonHeadersInterceptor: CommonHeadersInterceptor, + mirrorSwitchInterceptor: MirrorSwitchInterceptor, + ): OkHttpClient = baseClient.newBuilder().apply { + addNetworkInterceptor(CacheLimitInterceptor()) + addInterceptor(commonHeadersInterceptor) + addInterceptor(mirrorSwitchInterceptor) + }.build() + + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt index 32862bf59..393f5357f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt @@ -19,6 +19,7 @@ import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.core.network.MangaHttpClient import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage @@ -34,7 +35,7 @@ import kotlin.math.roundToInt @Reusable class MangaDataRepository @Inject constructor( - private val okHttpClient: OkHttpClient, + @MangaHttpClient private val okHttpClient: OkHttpClient, private val db: MangaDatabase, ) { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt index b8e864cba..fe140190d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.OkHttpClient +import org.koitharu.kotatsu.core.network.MangaHttpClient import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.util.ext.toList @@ -24,7 +25,7 @@ import kotlin.coroutines.suspendCoroutine @Singleton class MangaLoaderContextImpl @Inject constructor( - override val httpClient: OkHttpClient, + @MangaHttpClient override val httpClient: OkHttpClient, override val cookieJar: MutableCookieJar, @ApplicationContext private val androidContext: Context, ) : MangaLoaderContext() { diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt index bb26b9614..47cf46cf0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt @@ -36,6 +36,7 @@ import okio.buffer import okio.sink import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.core.network.MangaHttpClient import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings @@ -69,7 +70,7 @@ import javax.inject.Inject class DownloadWorker @AssistedInject constructor( @Assisted appContext: Context, @Assisted params: WorkerParameters, - private val okHttp: OkHttpClient, + @MangaHttpClient private val okHttp: OkHttpClient, private val cache: PagesCache, private val localMangaRepository: LocalMangaRepository, private val mangaDataRepository: MangaDataRepository, diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/TrackerLogger.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt similarity index 75% rename from app/src/main/java/org/koitharu/kotatsu/local/data/TrackerLogger.kt rename to app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt index abc8d7714..ed5bb669e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/TrackerLogger.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt @@ -3,5 +3,5 @@ package org.koitharu.kotatsu.local.data import javax.inject.Qualifier @Qualifier -@Retention(AnnotationRetention.BINARY) +@Retention(AnnotationRetention.SOURCE) annotation class LocalStorageChanges diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt index d59ee6788..1fef8621f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -22,6 +22,7 @@ import okhttp3.OkHttpClient import okhttp3.Request import okio.source import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.core.network.MangaHttpClient import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings @@ -46,7 +47,7 @@ import kotlin.coroutines.CoroutineContext @ActivityRetainedScoped class PageLoader @Inject constructor( lifecycle: ActivityRetainedLifecycle, - private val okHttp: OkHttpClient, + @MangaHttpClient private val okHttp: OkHttpClient, private val cache: PagesCache, private val settings: AppSettings, private val mangaRepositoryFactory: MangaRepository.Factory, diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt index f4300792b..f45ce2123 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt @@ -8,12 +8,9 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import dagger.multibindings.ElementsIntoSet import okhttp3.OkHttpClient -import org.koitharu.kotatsu.BuildConfig -import org.koitharu.kotatsu.core.db.MangaDatabase -import org.koitharu.kotatsu.core.network.CurlLoggingInterceptor +import org.koitharu.kotatsu.core.network.BaseHttpClient import org.koitharu.kotatsu.scrobbling.anilist.data.AniListAuthenticator import org.koitharu.kotatsu.scrobbling.anilist.data.AniListInterceptor -import org.koitharu.kotatsu.scrobbling.anilist.data.AniListRepository import org.koitharu.kotatsu.scrobbling.anilist.domain.AniListScrobbler import org.koitharu.kotatsu.scrobbling.common.data.ScrobblerStorage import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler @@ -21,11 +18,9 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerType import org.koitharu.kotatsu.scrobbling.mal.data.MALAuthenticator import org.koitharu.kotatsu.scrobbling.mal.data.MALInterceptor -import org.koitharu.kotatsu.scrobbling.mal.data.MALRepository import org.koitharu.kotatsu.scrobbling.mal.domain.MALScrobbler import org.koitharu.kotatsu.scrobbling.shikimori.data.ShikimoriAuthenticator import org.koitharu.kotatsu.scrobbling.shikimori.data.ShikimoriInterceptor -import org.koitharu.kotatsu.scrobbling.shikimori.data.ShikimoriRepository import org.koitharu.kotatsu.scrobbling.shikimori.domain.ShikimoriScrobbler import javax.inject.Singleton @@ -35,57 +30,39 @@ object ScrobblingModule { @Provides @Singleton - fun provideShikimoriRepository( - @ApplicationContext context: Context, - @ScrobblerType(ScrobblerService.SHIKIMORI) storage: ScrobblerStorage, - database: MangaDatabase, + @ScrobblerType(ScrobblerService.SHIKIMORI) + fun provideShikimoriHttpClient( + @BaseHttpClient baseHttpClient: OkHttpClient, authenticator: ShikimoriAuthenticator, - ): ShikimoriRepository { - val okHttp = OkHttpClient.Builder().apply { - authenticator(authenticator) - addInterceptor(ShikimoriInterceptor(storage)) - if (BuildConfig.DEBUG) { - addInterceptor(CurlLoggingInterceptor()) - } - }.build() - return ShikimoriRepository(context, okHttp, storage, database) - } + @ScrobblerType(ScrobblerService.SHIKIMORI) storage: ScrobblerStorage, + ): OkHttpClient = baseHttpClient.newBuilder().apply { + authenticator(authenticator) + addInterceptor(ShikimoriInterceptor(storage)) + }.build() @Provides @Singleton - fun provideMALRepository( - @ApplicationContext context: Context, - @ScrobblerType(ScrobblerService.MAL) storage: ScrobblerStorage, - database: MangaDatabase, + @ScrobblerType(ScrobblerService.MAL) + fun provideMALHttpClient( + @BaseHttpClient baseHttpClient: OkHttpClient, authenticator: MALAuthenticator, - ): MALRepository { - val okHttp = OkHttpClient.Builder().apply { - authenticator(authenticator) - addInterceptor(MALInterceptor(storage)) - if (BuildConfig.DEBUG) { - addInterceptor(CurlLoggingInterceptor()) - } - }.build() - return MALRepository(context, okHttp, storage, database) - } + @ScrobblerType(ScrobblerService.MAL) storage: ScrobblerStorage, + ): OkHttpClient = baseHttpClient.newBuilder().apply { + authenticator(authenticator) + addInterceptor(MALInterceptor(storage)) + }.build() @Provides @Singleton - fun provideAniListRepository( - @ApplicationContext context: Context, - @ScrobblerType(ScrobblerService.ANILIST) storage: ScrobblerStorage, - database: MangaDatabase, + @ScrobblerType(ScrobblerService.ANILIST) + fun provideAniListHttpClient( + @BaseHttpClient baseHttpClient: OkHttpClient, authenticator: AniListAuthenticator, - ): AniListRepository { - val okHttp = OkHttpClient.Builder().apply { - authenticator(authenticator) - addInterceptor(AniListInterceptor(storage)) - if (BuildConfig.DEBUG) { - addInterceptor(CurlLoggingInterceptor()) - } - }.build() - return AniListRepository(context, okHttp, storage, database) - } + @ScrobblerType(ScrobblerService.ANILIST) storage: ScrobblerStorage, + ): OkHttpClient = baseHttpClient.newBuilder().apply { + authenticator(authenticator) + addInterceptor(AniListInterceptor(storage)) + }.build() @Provides @Singleton diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt index f2bd44e7f..a1a3da59c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt @@ -23,7 +23,10 @@ import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService +import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerType import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser +import javax.inject.Inject +import javax.inject.Singleton import kotlin.math.roundToInt private const val REDIRECT_URI = "kotatsu://anilist-auth" @@ -34,10 +37,11 @@ private const val REQUEST_QUERY = "query" private const val REQUEST_MUTATION = "mutation" private const val KEY_SCORE_FORMAT = "score_format" -class AniListRepository( +@Singleton +class AniListRepository @Inject constructor( @ApplicationContext context: Context, - private val okHttp: OkHttpClient, - private val storage: ScrobblerStorage, + @ScrobblerType(ScrobblerService.ANILIST) private val okHttp: OkHttpClient, + @ScrobblerType(ScrobblerService.ANILIST) private val storage: ScrobblerStorage, private val db: MangaDatabase, ) : ScrobblerRepository { diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt index f17d51ea7..877cbabf5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt @@ -20,18 +20,22 @@ import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService +import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerType import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import java.security.SecureRandom +import javax.inject.Inject +import javax.inject.Singleton private const val REDIRECT_URI = "kotatsu://mal-auth" private const val BASE_WEB_URL = "https://myanimelist.net" private const val BASE_API_URL = "https://api.myanimelist.net/v2" private const val AVATAR_STUB = "https://cdn.myanimelist.net/images/questionmark_50.gif" -class MALRepository( +@Singleton +class MALRepository @Inject constructor( @ApplicationContext context: Context, - private val okHttp: OkHttpClient, - private val storage: ScrobblerStorage, + @ScrobblerType(ScrobblerService.MAL) private val okHttp: OkHttpClient, + @ScrobblerType(ScrobblerService.MAL) private val storage: ScrobblerStorage, private val db: MangaDatabase, ) : ScrobblerRepository { diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt index 9ddf0aacb..e61791deb 100644 --- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt @@ -23,16 +23,20 @@ import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerMangaInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService +import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerType import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser +import javax.inject.Inject +import javax.inject.Singleton private const val REDIRECT_URI = "kotatsu://shikimori-auth" private const val BASE_URL = "https://shikimori.me/" private const val MANGA_PAGE_SIZE = 10 -class ShikimoriRepository( +@Singleton +class ShikimoriRepository @Inject constructor( @ApplicationContext context: Context, - private val okHttp: OkHttpClient, - private val storage: ScrobblerStorage, + @ScrobblerType(ScrobblerService.SHIKIMORI) private val okHttp: OkHttpClient, + @ScrobblerType(ScrobblerService.SHIKIMORI) private val storage: ScrobblerStorage, private val db: MangaDatabase, ) : ScrobblerRepository { diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt index 822c5736f..b9f6b6683 100644 --- a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt +++ b/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt @@ -5,6 +5,7 @@ import okhttp3.OkHttpClient import okhttp3.Request import org.json.JSONObject import org.koitharu.kotatsu.core.exceptions.SyncApiException +import org.koitharu.kotatsu.core.network.BaseHttpClient import org.koitharu.kotatsu.core.util.ext.toRequestBody import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.parseJson @@ -13,7 +14,7 @@ import javax.inject.Inject @Reusable class SyncAuthApi @Inject constructor( - private val okHttpClient: OkHttpClient, + @BaseHttpClient private val okHttpClient: OkHttpClient, ) { suspend fun authenticate(host: String, email: String, password: String): String { From eb7efaaac97089da775754785cd271e253bd54bd Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 20 May 2023 15:32:09 +0300 Subject: [PATCH 06/90] Add proxy support #376 --- .../org/koitharu/kotatsu/core/logs/Loggers.kt | 4 +- .../kotatsu/core/network/AppProxySelector.kt | 43 +++++++++++++ .../kotatsu/core/network/HttpClients.kt | 4 +- .../kotatsu/core/network/NetworkModule.kt | 1 + .../kotatsu/core/prefs/AppSettings.kt | 17 ++++++ .../koitharu/kotatsu/local/data/Qualifiers.kt | 2 +- .../settings/ContentSettingsFragment.kt | 21 +++++++ .../kotatsu/settings/ProxySettingsFragment.kt | 60 +++++++++++++++++++ .../settings/utils/EditTextBindListener.kt | 2 +- app/src/main/res/values/arrays.xml | 7 ++- app/src/main/res/values/constants.xml | 5 ++ app/src/main/res/values/strings.xml | 4 ++ app/src/main/res/xml/pref_content.xml | 5 ++ app/src/main/res/xml/pref_proxy.xml | 24 ++++++++ 14 files changed, 192 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt create mode 100644 app/src/main/res/xml/pref_proxy.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt b/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt index 47eeea605..008ca7d92 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt @@ -3,9 +3,9 @@ package org.koitharu.kotatsu.core.logs import javax.inject.Qualifier @Qualifier -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) annotation class TrackerLogger @Qualifier -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) annotation class SyncLogger diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt new file mode 100644 index 000000000..5beb6e42a --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt @@ -0,0 +1,43 @@ +package org.koitharu.kotatsu.core.network + +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.util.ext.printStackTraceDebug +import java.io.IOException +import java.net.InetSocketAddress +import java.net.Proxy +import java.net.ProxySelector +import java.net.SocketAddress +import java.net.URI + +class AppProxySelector( + private val settings: AppSettings, +) : ProxySelector() { + + private var cachedProxy: Proxy? = null + + override fun select(uri: URI?): List { + return listOf(getProxy()) + } + + override fun connectFailed(uri: URI?, sa: SocketAddress?, ioe: IOException?) { + ioe?.printStackTraceDebug() + } + + private fun getProxy(): Proxy { + val type = settings.proxyType + val address = settings.proxyAddress + val port = settings.proxyPort + if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { + return Proxy.NO_PROXY + } + cachedProxy?.let { + val addr = it.address() as? InetSocketAddress + if (addr != null && it.type() == type && addr.port == port && addr.hostString == address) { + return it + } + } + val proxy = Proxy(type, InetSocketAddress(address, port)) + cachedProxy = proxy + return proxy + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt b/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt index 45e1b5d45..fb69fe291 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt @@ -3,9 +3,9 @@ package org.koitharu.kotatsu.core.network import javax.inject.Qualifier @Qualifier -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) annotation class BaseHttpClient @Qualifier -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) annotation class MangaHttpClient 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 e528a21a8..a60c5db64 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 @@ -58,6 +58,7 @@ interface NetworkModule { readTimeout(60, TimeUnit.SECONDS) writeTimeout(20, TimeUnit.SECONDS) cookieJar(cookieJar) + proxySelector(AppProxySelector(settings)) dns(DoHManager(cache, settings)) if (settings.isSSLBypassEnabled) { bypassSSLErrors() 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 03d0c04e8..fe2e24192 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 @@ -25,6 +25,7 @@ import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.shelf.domain.ShelfSection import java.io.File +import java.net.Proxy import java.util.Collections import java.util.EnumSet import java.util.Locale @@ -276,6 +277,18 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isSSLBypassEnabled: Boolean get() = prefs.getBoolean(KEY_SSL_BYPASS, false) + val proxyType: Proxy.Type + get() { + val raw = prefs.getString(KEY_PROXY_TYPE, null) ?: return Proxy.Type.DIRECT + return enumValues().find { it.name == raw } ?: Proxy.Type.DIRECT + } + + val proxyAddress: String? + get() = prefs.getString(KEY_PROXY_ADDRESS, null) + + val proxyPort: Int + get() = prefs.getString(KEY_PROXY_PORT, null)?.toIntOrNull() ?: 0 + var localListOrder: SortOrder get() = prefs.getEnumValue(KEY_LOCAL_LIST_ORDER, SortOrder.NEWEST) set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) } @@ -413,6 +426,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_SSL_BYPASS = "ssl_bypass" const val KEY_READER_AUTOSCROLL_SPEED = "as_speed" const val KEY_MIRROR_SWITCHING = "mirror_switching" + const val KEY_PROXY = "proxy" + const val KEY_PROXY_TYPE = "proxy_type" + const val KEY_PROXY_ADDRESS = "proxy_address" + const val KEY_PROXY_PORT = "proxy_port" // About const val KEY_APP_UPDATE = "app_update" diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt b/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt index ed5bb669e..abc8d7714 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt @@ -3,5 +3,5 @@ package org.koitharu.kotatsu.local.data import javax.inject.Qualifier @Qualifier -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) annotation class LocalStorageChanges diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt index bad3d8632..e062e6800 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt @@ -24,6 +24,7 @@ import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File +import java.net.Proxy import javax.inject.Inject @AndroidEntryPoint @@ -62,6 +63,7 @@ class ContentSettingsFragment : if (settings.isSuggestionsEnabled) R.string.enabled else R.string.disabled, ) bindRemoteSourcesSummary() + bindProxySummary() settings.subscribe(this) } @@ -93,6 +95,12 @@ class ContentSettingsFragment : AppSettings.KEY_SSL_BYPASS -> { Snackbar.make(listView, R.string.settings_apply_restart_required, Snackbar.LENGTH_INDEFINITE).show() } + + AppSettings.KEY_PROXY_TYPE, + AppSettings.KEY_PROXY_ADDRESS, + AppSettings.KEY_PROXY_PORT -> { + bindProxySummary() + } } } @@ -130,6 +138,19 @@ class ContentSettingsFragment : } } + private fun bindProxySummary() { + findPreference(AppSettings.KEY_PROXY)?.run { + val type = settings.proxyType + val address = settings.proxyAddress + val port = settings.proxyPort + summary = if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { + context.getString(R.string.disabled) + } else { + "$type $address:$port" + } + } + } + private fun updateDownloadsConstraints() { val preference = findPreference(AppSettings.KEY_DOWNLOADS_WIFI) viewLifecycleScope.launch { diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt new file mode 100644 index 000000000..7b86847c4 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt @@ -0,0 +1,60 @@ +package org.koitharu.kotatsu.settings + +import android.content.SharedPreferences +import android.os.Bundle +import android.view.View +import android.view.inputmethod.EditorInfo +import androidx.preference.EditTextPreference +import androidx.preference.Preference +import dagger.hilt.android.AndroidEntryPoint +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.settings.utils.EditTextBindListener +import java.net.Proxy + +@AndroidEntryPoint +class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy), + SharedPreferences.OnSharedPreferenceChangeListener { + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.pref_proxy) + findPreference(AppSettings.KEY_PROXY_ADDRESS)?.setOnBindEditTextListener( + EditTextBindListener( + inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI, + hint = null, + validator = DomainValidator(), + ), + ) + findPreference(AppSettings.KEY_PROXY_PORT)?.setOnBindEditTextListener( + EditTextBindListener( + inputType = EditorInfo.TYPE_CLASS_NUMBER, + hint = null, + validator = null, + ), + ) + updateDependencies() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + settings.subscribe(this) + } + + override fun onDestroyView() { + settings.unsubscribe(this) + super.onDestroyView() + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + when (key) { + AppSettings.KEY_PROXY_TYPE -> updateDependencies() + } + } + + private fun updateDependencies() { + val isProxyEnabled = settings.proxyType != Proxy.Type.DIRECT + findPreference(AppSettings.KEY_PROXY_ADDRESS)?.isEnabled = isProxyEnabled + findPreference(AppSettings.KEY_PROXY_PORT)?.isEnabled = isProxyEnabled + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt index 7f2ccdd29..a65122501 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt @@ -6,7 +6,7 @@ import org.koitharu.kotatsu.core.util.EditTextValidator class EditTextBindListener( private val inputType: Int, - private val hint: String, + private val hint: String?, private val validator: EditTextValidator?, ) : EditTextPreference.OnBindEditTextListener { diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 612506b1d..4b0ad8866 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -53,4 +53,9 @@ @string/status_on_hold @string/status_dropped - \ No newline at end of file + + @string/disabled + HTTP + SOCKS (v4/v5) + + diff --git a/app/src/main/res/values/constants.xml b/app/src/main/res/values/constants.xml index 060c11acb..536b16a5e 100644 --- a/app/src/main/res/values/constants.xml +++ b/app/src/main/res/values/constants.xml @@ -50,4 +50,9 @@ @string/sync_host_default 86.57.183.214:8081 + + DIRECT + HTTP + SOCKS + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8cfb1c96f..df7cf2741 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -417,4 +417,8 @@ Translations WebView not available: check if WebView provider is installed Clear network cache + Type + Address + Port + Proxy diff --git a/app/src/main/res/xml/pref_content.xml b/app/src/main/res/xml/pref_content.xml index 1ecc73d25..228b40729 100644 --- a/app/src/main/res/xml/pref_content.xml +++ b/app/src/main/res/xml/pref_content.xml @@ -37,6 +37,11 @@ app:allowDividerAbove="true" app:useSimpleSummaryProvider="true" /> + + diff --git a/app/src/main/res/xml/pref_proxy.xml b/app/src/main/res/xml/pref_proxy.xml new file mode 100644 index 000000000..4bf1cad5c --- /dev/null +++ b/app/src/main/res/xml/pref_proxy.xml @@ -0,0 +1,24 @@ + + + + + + + + + + From 84567767a0cf970336cfa6e015837dd01bc21b53 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 20 May 2023 15:47:47 +0300 Subject: [PATCH 07/90] Limit lifetime of memory content cache --- .../kotatsu/core/cache/DeferredLruCache.kt | 5 --- .../kotatsu/core/cache/ExpiringLruCache.kt | 33 ++++++++++++++++++ .../kotatsu/core/cache/ExpiringValue.kt | 34 +++++++++++++++++++ .../kotatsu/core/cache/MemoryContentCache.kt | 15 ++++---- 4 files changed, 75 insertions(+), 12 deletions(-) delete mode 100644 app/src/main/java/org/koitharu/kotatsu/core/cache/DeferredLruCache.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/DeferredLruCache.kt b/app/src/main/java/org/koitharu/kotatsu/core/cache/DeferredLruCache.kt deleted file mode 100644 index 8b9e08aa3..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/core/cache/DeferredLruCache.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.koitharu.kotatsu.core.cache - -import androidx.collection.LruCache - -class DeferredLruCache(maxSize: Int) : LruCache>(maxSize) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt b/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt new file mode 100644 index 000000000..34d46dfca --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt @@ -0,0 +1,33 @@ +package org.koitharu.kotatsu.core.cache + +import androidx.collection.LruCache +import java.util.concurrent.TimeUnit + +class ExpiringLruCache( + val maxSize: Int, + private val lifetime: Long, + private val timeUnit: TimeUnit, +) { + + private val cache = LruCache>(maxSize) + + operator fun get(key: ContentCache.Key): T? { + val value = cache.get(key) ?: return null + if (value.isExpired) { + cache.remove(key) + } + return value.get() + } + + operator fun set(key: ContentCache.Key, value: T) { + cache.put(key, ExpiringValue(value, lifetime, timeUnit)) + } + + fun clear() { + cache.evictAll() + } + + fun trimToSize(size: Int) { + cache.trimToSize(size) + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt b/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt new file mode 100644 index 000000000..2d561bb0c --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt @@ -0,0 +1,34 @@ +package org.koitharu.kotatsu.core.cache + +import android.os.SystemClock +import java.util.concurrent.TimeUnit + +class ExpiringValue( + private val value: T, + lifetime: Long, + timeUnit: TimeUnit, +) { + + private val expiresAt = SystemClock.elapsedRealtime() + timeUnit.toMillis(lifetime) + + val isExpired: Boolean + get() = SystemClock.elapsedRealtime() >= expiresAt + + fun get(): T? = if (isExpired) null else value + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as ExpiringValue<*> + + if (value != other.value) return false + return expiresAt == other.expiresAt + } + + override fun hashCode(): Int { + var result = value?.hashCode() ?: 0 + result = 31 * result + expiresAt.hashCode() + return result + } +} diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt b/app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt index ffa9a904e..722b06d41 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt @@ -6,6 +6,7 @@ import android.content.res.Configuration import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource +import java.util.concurrent.TimeUnit class MemoryContentCache(application: Application) : ContentCache, ComponentCallbacks2 { @@ -13,8 +14,8 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall application.registerComponentCallbacks(this) } - private val detailsCache = DeferredLruCache(4) - private val pagesCache = DeferredLruCache>(4) + private val detailsCache = ExpiringLruCache>(4, 5, TimeUnit.MINUTES) + private val pagesCache = ExpiringLruCache>>(4, 10, TimeUnit.MINUTES) override val isCachingEnabled: Boolean = true @@ -23,7 +24,7 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall } override fun putDetails(source: MangaSource, url: String, details: SafeDeferred) { - detailsCache.put(ContentCache.Key(source, url), details) + detailsCache[ContentCache.Key(source, url)] = details } override suspend fun getPages(source: MangaSource, url: String): List? { @@ -31,7 +32,7 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall } override fun putPages(source: MangaSource, url: String, pages: SafeDeferred>) { - pagesCache.put(ContentCache.Key(source, url), pages) + pagesCache[ContentCache.Key(source, url)] = pages } override fun onConfigurationChanged(newConfig: Configuration) = Unit @@ -43,17 +44,17 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall trimCache(pagesCache, level) } - private fun trimCache(cache: DeferredLruCache<*>, level: Int) { + private fun trimCache(cache: ExpiringLruCache<*>, level: Int) { when (level) { ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL, ComponentCallbacks2.TRIM_MEMORY_COMPLETE, - ComponentCallbacks2.TRIM_MEMORY_MODERATE -> cache.evictAll() + ComponentCallbacks2.TRIM_MEMORY_MODERATE -> cache.clear() ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN, ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW, ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> cache.trimToSize(1) - else -> cache.trimToSize(cache.maxSize() / 2) + else -> cache.trimToSize(cache.maxSize / 2) } } } From a8f5714b35e4a3cc7d90b2fbacf996e5f9ba11c4 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 22 May 2023 18:08:05 +0300 Subject: [PATCH 08/90] Refactor chapters mapping --- .../details/ui/ChaptersBottomSheetMediator.kt | 3 + .../kotatsu/details/ui/ChaptersFragment.kt | 6 +- .../kotatsu/details/ui/ChaptersMapper.kt | 60 +++++++ .../kotatsu/details/ui/DetailsActivity.kt | 34 +--- .../kotatsu/details/ui/DetailsViewModel.kt | 93 ++++++----- .../details/ui/MangaDetailsDelegate.kt | 149 +++++------------- .../details/ui/adapter/ChapterListItemAD.kt | 29 ++-- .../details/ui/model/ChapterListItem.kt | 25 +-- .../ui/model/ListModelConversionExt.kt | 3 - .../kotatsu/reader/ui/ChaptersBottomSheet.kt | 1 - .../main/res/drawable/bg_badge_primary.xml | 11 ++ app/src/main/res/values/strings.xml | 2 + 12 files changed, 199 insertions(+), 217 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt create mode 100644 app/src/main/res/drawable/bg_badge_primary.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt index c6921d6e8..2e0929ae9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt @@ -32,6 +32,9 @@ class ChaptersBottomSheetMediator( override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { isEnabled = isExpanded + if (!isExpanded) { + unlock() + } } override fun onLayoutChange( diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index 93d79c01e..e82993114 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -73,10 +73,6 @@ class ChaptersFragment : if (selectionController?.onItemClick(item.chapter.id) == true) { return } - if (item.hasFlag(ChapterListItem.FLAG_MISSING)) { - (activity as? DetailsActivity)?.showChapterMissingDialog(item.chapter.id) - return - } startActivity( ReaderActivity.newIntent( context = view.context, @@ -193,7 +189,7 @@ class ChaptersFragment : private fun onChaptersChanged(list: List) { val adapter = chaptersAdapter ?: return if (adapter.itemCount == 0) { - val position = list.indexOfFirst { it.hasFlag(ChapterListItem.FLAG_CURRENT) } - 1 + val position = list.indexOfFirst { it.isCurrent } - 1 if (position > 0) { val offset = (resources.getDimensionPixelSize(R.dimen.chapter_list_item_height) * 0.6).roundToInt() adapter.setItems( diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt new file mode 100644 index 000000000..618d623e1 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt @@ -0,0 +1,60 @@ +package org.koitharu.kotatsu.details.ui + +import org.koitharu.kotatsu.core.model.MangaHistory +import org.koitharu.kotatsu.details.ui.model.ChapterListItem +import org.koitharu.kotatsu.details.ui.model.toListItem +import org.koitharu.kotatsu.parsers.model.Manga + +fun mapChapters( + remoteManga: Manga?, + localManga: Manga?, + history: MangaHistory?, + newCount: Int, + branch: String?, +): List { + val remoteChapters = remoteManga?.getChapters(branch).orEmpty() + val localChapters = localManga?.getChapters(branch).orEmpty() + if (remoteChapters.isEmpty() && localChapters.isEmpty()) { + return emptyList() + } + val currentId = history?.chapterId ?: 0L + val newFrom = if (newCount == 0 || remoteChapters.isEmpty()) Int.MAX_VALUE else remoteChapters.size - newCount + val chaptersSize = maxOf(remoteChapters.size, localChapters.size) + val ids = buildSet(chaptersSize) { + remoteChapters.mapTo(this) { it.id } + localChapters.mapTo(this) { it.id } + } + val result = ArrayList(chaptersSize) + val localMap = if (localChapters.isNotEmpty()) { + localChapters.associateByTo(LinkedHashMap(localChapters.size)) { it.id } + } else { + null + } + var isUnread = currentId !in ids + for (chapter in remoteChapters) { + val local = localMap?.remove(chapter.id) + if (chapter.id == currentId) { + isUnread = true + } + result += chapter.toListItem( + isCurrent = chapter.id == currentId, + isUnread = isUnread, + isNew = isUnread && result.size >= newFrom, + isDownloaded = local != null, + ) + } + if (!localMap.isNullOrEmpty()) { + for (chapter in localMap.values) { + if (chapter.id == currentId) { + isUnread = true + } + result += chapter.toListItem( + isCurrent = chapter.id == currentId, + isUnread = isUnread, + isNew = false, + isDownloaded = false, + ) + } + } + return result +} diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 0a97180c6..f090a47fa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -19,7 +19,6 @@ import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updatePadding import androidx.lifecycle.Observer -import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint @@ -45,7 +44,6 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity -import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet import javax.inject.Inject @@ -244,33 +242,6 @@ class DetailsActivity : viewBadge.counter = newChapters } - fun showChapterMissingDialog(chapterId: Long) { - val remoteManga = viewModel.getRemoteManga() - if (remoteManga == null) { - val snackbar = makeSnackbar(getString(R.string.chapter_is_missing), Snackbar.LENGTH_SHORT) - snackbar.show() - return - } - MaterialAlertDialogBuilder(this).apply { - setMessage(R.string.chapter_is_missing_text) - setTitle(R.string.chapter_is_missing) - setNegativeButton(android.R.string.cancel, null) - setPositiveButton(R.string.read) { _, _ -> - startActivity( - ReaderActivity.newIntent( - context = this@DetailsActivity, - manga = remoteManga, - state = ReaderState(chapterId, 0, 0), - ), - ) - } - setNeutralButton(R.string.download) { _, _ -> - viewModel.download(setOf(chapterId)) - } - setCancelable(true) - }.show() - } - private fun showBranchPopupMenu() { var dialog: DialogInterface? = null val listener = OnListItemClickListener { item, _ -> @@ -291,7 +262,8 @@ class DetailsActivity : val manga = viewModel.manga.value ?: return val chapterId = viewModel.historyInfo.value?.history?.chapterId if (chapterId != null && manga.chapters?.none { x -> x.id == chapterId } == true) { - showChapterMissingDialog(chapterId) + val snackbar = makeSnackbar(getString(R.string.chapter_is_missing), Snackbar.LENGTH_SHORT) + snackbar.show() } else { startActivity( ReaderActivity.newIntent( @@ -339,7 +311,7 @@ class DetailsActivity : } if (!isCalled) { isCalled = true - val item = value.find { it.hasFlag(ChapterListItem.FLAG_CURRENT) } ?: value.first() + val item = value.find { it.isCurrent } ?: value.first() MangaPrefetchService.prefetchPages(context, item.chapter) } } 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 69f666b20..0d3101f28 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 @@ -78,6 +78,13 @@ class DetailsViewModel @Inject constructor( val onShowToast = SingleLiveEvent() val onDownloadStarted = SingleLiveEvent() + private val mangaData = combine( + delegate.onlineManga, + delegate.localManga, + ) { o, l -> + o ?: l + }.stateIn(viewModelScope, SharingStarted.Lazily, null) + private val history = historyRepository.observeOne(delegate.mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) @@ -98,16 +105,16 @@ class DetailsViewModel @Inject constructor( private val chaptersReversed = settings.observeAsFlow(AppSettings.KEY_REVERSE_CHAPTERS) { chaptersReverse } .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) - val manga = delegate.manga.filterNotNull().asLiveData(viewModelScope.coroutineContext) + val manga = mangaData.filterNotNull().asLiveData(viewModelScope.coroutineContext) val favouriteCategories = favourite.asLiveData(viewModelScope.coroutineContext) val newChaptersCount = newChapters.asLiveData(viewModelScope.coroutineContext) val isChaptersReversed = chaptersReversed.asLiveData(viewModelScope.coroutineContext) val historyInfo: LiveData = combine( - delegate.manga, + mangaData, delegate.selectedBranch, history, - historyRepository.observeShouldSkip(delegate.manga), + historyRepository.observeShouldSkip(mangaData), ) { m, b, h, im -> HistoryInfo(m, b, h, im) }.asFlowLiveData( @@ -115,28 +122,21 @@ class DetailsViewModel @Inject constructor( defaultValue = HistoryInfo(null, null, null, false), ) - val bookmarks = delegate.manga.flatMapLatest { + val bookmarks = mangaData.flatMapLatest { if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList()) }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) - val localSize = combine( - delegate.manga, - delegate.relatedManga, - ) { m1, m2 -> - val url = when { - m1?.source == MangaSource.LOCAL -> m1.url - m2?.source == MangaSource.LOCAL -> m2.url - else -> null - } - if (url != null) { - val file = url.toUri().toFileOrNull() - file?.computeSize() ?: 0L - } else { - 0L - } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, 0) + val localSize = delegate.localManga + .map { + if (it != null) { + val file = it.url.toUri().toFileOrNull() + file?.computeSize() ?: 0L + } else { + 0L + } + }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, 0) - val description = delegate.manga + val description = mangaData .distinctUntilChangedBy { it?.description.orEmpty() } .transformLatest { val description = it?.description @@ -159,10 +159,12 @@ class DetailsViewModel @Inject constructor( }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) val branches: LiveData> = combine( - delegate.manga, + delegate.onlineManga, + delegate.localManga, delegate.selectedBranch, - ) { m, b -> - val chapters = m?.chapters ?: return@combine emptyList() + ) { m, l, b -> + val chapters = concat(m?.chapters, l?.chapters) + if (chapters.isEmpty()) return@combine emptyList() chapters.groupBy { x -> x.branch } .map { x -> MangaBranch(x.key, x.value.size, x.key == b) } .sortedWith(BranchComparator()) @@ -172,21 +174,24 @@ class DetailsViewModel @Inject constructor( .asFlowLiveData(viewModelScope.coroutineContext, null) val isChaptersEmpty: LiveData = combine( - delegate.manga, + delegate.onlineManga, + delegate.localManga, isLoading.asFlow(), - ) { m, loading -> - m != null && m.chapters.isNullOrEmpty() && !loading + ) { manga, local, loading -> + (manga != null && manga.chapters.isNullOrEmpty()) && + (local != null && local.chapters.isNullOrEmpty()) && + !loading }.asFlowLiveData(viewModelScope.coroutineContext, false) val chapters = combine( combine( - delegate.manga, - delegate.relatedManga, + delegate.onlineManga, + delegate.localManga, history, delegate.selectedBranch, newChapters, - ) { manga, related, history, branch, news -> - delegate.mapChapters(manga, related, history, news, branch) + ) { manga, local, history, branch, news -> + mapChapters(manga, local, history, news, branch) }, chaptersReversed, chaptersQuery, @@ -211,7 +216,7 @@ class DetailsViewModel @Inject constructor( } fun deleteLocal() { - val m = delegate.manga.value + val m = delegate.localManga.value if (m == null) { onShowToast.call(R.string.file_not_found) return @@ -244,7 +249,7 @@ class DetailsViewModel @Inject constructor( } fun getRemoteManga(): Manga? { - return delegate.relatedManga.value?.takeUnless { it.source == MangaSource.LOCAL } + return delegate.onlineManga.value } fun performChapterSearch(query: String?) { @@ -274,7 +279,7 @@ class DetailsViewModel @Inject constructor( fun markChapterAsCurrent(chapterId: Long) { launchJob(Dispatchers.Default) { - val manga = checkNotNull(delegate.manga.value) + val manga = checkNotNull(mangaData.value) val chapters = checkNotNull(manga.getChapters(selectedBranchValue)) val chapterIndex = chapters.indexOfFirst { it.id == chapterId } check(chapterIndex in chapters.indices) { "Chapter not found" } @@ -286,7 +291,7 @@ class DetailsViewModel @Inject constructor( fun download(chaptersIds: Set?) { launchJob(Dispatchers.Default) { downloadScheduler.schedule( - getRemoteManga() ?: checkNotNull(manga.value), + delegate.onlineManga.value ?: checkNotNull(manga.value), chaptersIds, ) onDownloadStarted.emitCall(Unit) @@ -308,7 +313,7 @@ class DetailsViewModel @Inject constructor( private suspend fun onDownloadComplete(downloadedManga: LocalManga?) { downloadedManga ?: return - val currentManga = delegate.manga.value ?: return + val currentManga = mangaData.value ?: return if (currentManga.id != downloadedManga.manga.id) { return } @@ -319,7 +324,7 @@ class DetailsViewModel @Inject constructor( runCatchingCancellable { localMangaRepository.getDetails(downloadedManga.manga) }.onSuccess { - delegate.relatedManga.value = it + delegate.publishManga(it) }.onFailure { it.printStackTraceDebug() } @@ -348,4 +353,18 @@ class DetailsViewModel @Inject constructor( } return scrobbler } + + private fun concat(a: List?, b: List?): List { + return when { + a == null && b == null -> emptyList() + a == null && b != null -> b + a != null && b == null -> a + a != null && b != null -> buildList(a.size + b.size) { + addAll(a) + addAll(b) + } + + else -> error("This shouldn't have happened") + } + } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt index c866a2c52..eee5e04e6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt @@ -1,21 +1,23 @@ package org.koitharu.kotatsu.details.ui import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.ViewModelLifecycle import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import org.koitharu.kotatsu.core.model.MangaHistory +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn import org.koitharu.kotatsu.core.model.getPreferredBranch +import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.details.ui.model.ChapterListItem -import org.koitharu.kotatsu.details.ui.model.toListItem +import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.util.ext.printStackTraceDebug @@ -24,31 +26,44 @@ import javax.inject.Inject @ViewModelScoped class MangaDetailsDelegate @Inject constructor( savedStateHandle: SavedStateHandle, + lifecycle: ViewModelLifecycle, private val mangaDataRepository: MangaDataRepository, private val historyRepository: HistoryRepository, private val localMangaRepository: LocalMangaRepository, private val mangaRepositoryFactory: MangaRepository.Factory, + networkState: NetworkState, ) { + private val viewModelScope = RetainedLifecycleCoroutineScope(lifecycle) + private val intent = MangaIntent(savedStateHandle) - private val mangaData = MutableStateFlow(intent.manga) + private val onlineMangaStateFlow = MutableStateFlow(null) + private val localMangaStateFlow = MutableStateFlow(null) - val selectedBranch = MutableStateFlow(null) + val onlineManga = combine( + onlineMangaStateFlow, + networkState, + ) { m, s -> m.takeIf { s } } + .stateIn(viewModelScope, SharingStarted.Lazily, null) + val localManga = localMangaStateFlow.asStateFlow() - // Remote manga for saved and saved for remote - val relatedManga = MutableStateFlow(null) - val manga: StateFlow - get() = mangaData + val selectedBranch = MutableStateFlow(null) val mangaId = intent.manga?.id ?: intent.mangaId + init { + intent.manga?.let { + publishManga(it) + } + } + suspend fun doLoad() { var manga = mangaDataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", "") - mangaData.value = manga + publishManga(manga) manga = mangaRepositoryFactory.create(manga.source).getDetails(manga) // find default branch val hist = historyRepository.getOne(manga) selectedBranch.value = manga.getPreferredBranch(hist) - mangaData.value = manga - relatedManga.value = runCatchingCancellable { + publishManga(manga) + runCatchingCancellable { if (manga.source == MangaSource.LOCAL) { val m = localMangaRepository.getRemoteManga(manga) ?: return@runCatchingCancellable null mangaRepositoryFactory.create(m.source).getDetails(m) @@ -57,106 +72,18 @@ class MangaDetailsDelegate @Inject constructor( } }.onFailure { error -> error.printStackTraceDebug() - }.getOrNull() - } - - fun mapChapters( - manga: Manga?, - related: Manga?, - history: MangaHistory?, - newCount: Int, - branch: String?, - ): List { - val chapters = manga?.chapters ?: return emptyList() - val relatedChapters = related?.chapters - return if (related?.source != MangaSource.LOCAL && !relatedChapters.isNullOrEmpty()) { - mapChaptersWithSource(chapters, relatedChapters, history?.chapterId, newCount, branch) - } else { - mapChapters(chapters, relatedChapters, history?.chapterId, newCount, branch) - } - } - - private fun mapChapters( - chapters: List, - downloadedChapters: List?, - currentId: Long?, - newCount: Int, - branch: String?, - ): List { - val result = ArrayList(chapters.size) - val currentIndex = chapters.indexOfFirst { it.id == currentId } - val firstNewIndex = chapters.size - newCount - val downloadedIds = downloadedChapters?.mapTo(HashSet(downloadedChapters.size)) { it.id } - for (i in chapters.indices) { - val chapter = chapters[i] - if (chapter.branch != branch) { - continue + }.onSuccess { + if (it != null) { + publishManga(it) } - result += chapter.toListItem( - isCurrent = i == currentIndex, - isUnread = i > currentIndex, - isNew = i >= firstNewIndex, - isMissing = false, - isDownloaded = downloadedIds?.contains(chapter.id) == true, - ) - } - if (result.size < chapters.size / 2) { - result.trimToSize() } - return result } - private fun mapChaptersWithSource( - chapters: List, - sourceChapters: List, - currentId: Long?, - newCount: Int, - branch: String?, - ): List { - val chaptersMap = chapters.associateByTo(HashMap(chapters.size)) { it.id } - val result = ArrayList(sourceChapters.size) - val currentIndex = sourceChapters.indexOfFirst { it.id == currentId } - val firstNewIndex = sourceChapters.size - newCount - for (i in sourceChapters.indices) { - val chapter = sourceChapters[i] - val localChapter = chaptersMap.remove(chapter.id) - if (chapter.branch != branch) { - continue - } - result += localChapter?.toListItem( - isCurrent = i == currentIndex, - isUnread = i > currentIndex, - isNew = i >= firstNewIndex, - isMissing = false, - isDownloaded = false, - ) ?: chapter.toListItem( - isCurrent = i == currentIndex, - isUnread = i > currentIndex, - isNew = i >= firstNewIndex, - isMissing = true, - isDownloaded = false, - ) - } - if (chaptersMap.isNotEmpty()) { // some chapters on device but not online source - result.ensureCapacity(result.size + chaptersMap.size) - chaptersMap.values.mapNotNullTo(result) { - if (it.branch == branch) { - it.toListItem( - isCurrent = false, - isUnread = true, - isNew = false, - isMissing = false, - isDownloaded = false, - ) - } else { - null - } - } - result.sortBy { it.chapter.number } - } - if (result.size < sourceChapters.size / 2) { - result.trimToSize() - } - return result + fun publishManga(manga: Manga) { + if (manga.source == MangaSource.LOCAL) { + localMangaStateFlow + } else { + onlineMangaStateFlow + }.value = manga } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt index ea7dcdd54..6ff818ccf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt @@ -9,11 +9,7 @@ import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemChapterBinding import org.koitharu.kotatsu.details.ui.model.ChapterListItem -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_CURRENT -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_DOWNLOADED -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_MISSING -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_NEW -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_UNREAD +import com.google.android.material.R as materialR fun chapterListItemAD( clickListener: OnListItemClickListener, @@ -31,15 +27,15 @@ fun chapterListItemAD( binding.textViewNumber.text = item.chapter.number.toString() binding.textViewDescription.textAndVisible = item.description() } - when (item.status) { - FLAG_UNREAD -> { - binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_default) - binding.textViewNumber.setTextColor(context.getThemeColor(com.google.android.material.R.attr.colorOnTertiary)) + when { + item.isCurrent -> { + binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_primary) + binding.textViewNumber.setTextColor(context.getThemeColor(materialR.attr.colorOnPrimary)) } - FLAG_CURRENT -> { - binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_accent) - binding.textViewNumber.setTextColor(context.getThemeColor(android.R.attr.textColorPrimaryInverse)) + item.isUnread -> { + binding.textViewNumber.setBackgroundResource(R.drawable.bg_badge_default) + binding.textViewNumber.setTextColor(context.getThemeColor(materialR.attr.colorOnTertiary)) } else -> { @@ -47,12 +43,7 @@ fun chapterListItemAD( binding.textViewNumber.setTextColor(context.getThemeColor(android.R.attr.textColorTertiary)) } } - val isMissing = item.hasFlag(FLAG_MISSING) - binding.textViewTitle.alpha = if (isMissing) 0.3f else 1f - binding.textViewDescription.alpha = if (isMissing) 0.3f else 1f - binding.textViewNumber.alpha = if (isMissing) 0.3f else 1f - - binding.imageViewDownloaded.isVisible = item.hasFlag(FLAG_DOWNLOADED) - binding.imageViewNew.isVisible = item.hasFlag(FLAG_NEW) + binding.imageViewDownloaded.isVisible = item.isDownloaded + binding.imageViewNew.isVisible = item.isNew } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt index 35b7aec12..2a62acb1e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt @@ -22,12 +22,17 @@ class ChapterListItem( return field } - val status: Int - get() = flags and MASK_STATUS + val isCurrent: Boolean + get() = hasFlag(FLAG_CURRENT) - fun hasFlag(flag: Int): Boolean { - return (flags and flag) == flag - } + val isUnread: Boolean + get() = hasFlag(FLAG_UNREAD) + + val isDownloaded: Boolean + get() = hasFlag(FLAG_DOWNLOADED) + + val isNew: Boolean + get() = hasFlag(FLAG_NEW) fun description(): CharSequence? { val scanlator = chapter.scanlator?.takeUnless { it.isBlank() } @@ -38,6 +43,10 @@ class ChapterListItem( } } + private fun hasFlag(flag: Int): Boolean { + return (flags and flag) == flag + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -46,9 +55,7 @@ class ChapterListItem( if (chapter != other.chapter) return false if (flags != other.flags) return false - if (uploadDateMs != other.uploadDateMs) return false - - return true + return uploadDateMs == other.uploadDateMs } override fun hashCode(): Int { @@ -63,8 +70,6 @@ class ChapterListItem( const val FLAG_UNREAD = 2 const val FLAG_CURRENT = 4 const val FLAG_NEW = 8 - const val FLAG_MISSING = 16 const val FLAG_DOWNLOADED = 32 - const val MASK_STATUS = FLAG_UNREAD or FLAG_CURRENT } } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt index 8f555e39c..73d70d3df 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt @@ -2,7 +2,6 @@ package org.koitharu.kotatsu.details.ui.model import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_CURRENT import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_DOWNLOADED -import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_MISSING import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_NEW import org.koitharu.kotatsu.details.ui.model.ChapterListItem.Companion.FLAG_UNREAD import org.koitharu.kotatsu.parsers.model.MangaChapter @@ -11,14 +10,12 @@ fun MangaChapter.toListItem( isCurrent: Boolean, isUnread: Boolean, isNew: Boolean, - isMissing: Boolean, isDownloaded: Boolean, ): ChapterListItem { var flags = 0 if (isCurrent) flags = flags or FLAG_CURRENT if (isUnread) flags = flags or FLAG_UNREAD if (isNew) flags = flags or FLAG_NEW - if (isMissing) flags = flags or FLAG_MISSING if (isDownloaded) flags = flags or FLAG_DOWNLOADED return ChapterListItem( chapter = this, diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt index 29caaca0a..568a79e1e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt @@ -46,7 +46,6 @@ class ChaptersBottomSheet : BaseBottomSheet(), OnListItemC isCurrent = index == currentPosition, isUnread = index > currentPosition, isNew = false, - isMissing = false, isDownloaded = false, ) } diff --git a/app/src/main/res/drawable/bg_badge_primary.xml b/app/src/main/res/drawable/bg_badge_primary.xml new file mode 100644 index 000000000..1393b8638 --- /dev/null +++ b/app/src/main/res/drawable/bg_badge_primary.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index df7cf2741..2a5de47a9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -47,6 +47,7 @@ Theme Light Dark + Follow system Pages Clear @@ -397,6 +398,7 @@ Pause Resume Paused + Remove completed Cancel all Download only via Wi-Fi From c3216871ed8c4e96198a0264302c66ab37eb7ec9 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 22 May 2023 18:16:50 +0300 Subject: [PATCH 09/90] Move sources from java to kotlin dir --- app/build.gradle | 1 + app/src/main/{java => kotlin}/org/koitharu/kotatsu/KotatsuApp.kt | 0 .../org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt | 0 .../org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt | 0 .../org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt | 0 .../org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt | 0 .../org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt | 0 .../org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt | 0 .../org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt | 0 .../kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt | 0 .../org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt | 0 .../org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt | 0 .../koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt | 0 .../koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt | 0 .../kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt | 0 .../org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt | 0 .../org/koitharu/kotatsu/browser/BrowserActivity.kt | 0 .../org/koitharu/kotatsu/browser/BrowserCallback.kt | 0 .../org/koitharu/kotatsu/browser/BrowserClient.kt | 0 .../org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt | 0 .../org/koitharu/kotatsu/browser/ProgressChromeClient.kt | 0 .../org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt | 0 .../koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt | 0 .../org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt | 0 .../org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt | 0 .../main/{java => kotlin}/org/koitharu/kotatsu/core/AppModule.kt | 0 .../org/koitharu/kotatsu/core/backup/BackupEntry.kt | 0 .../org/koitharu/kotatsu/core/backup/BackupRepository.kt | 0 .../org/koitharu/kotatsu/core/backup/BackupZipInput.kt | 0 .../org/koitharu/kotatsu/core/backup/BackupZipOutput.kt | 0 .../org/koitharu/kotatsu/core/backup/CompositeResult.kt | 0 .../org/koitharu/kotatsu/core/backup/JsonDeserializer.kt | 0 .../org/koitharu/kotatsu/core/backup/JsonSerializer.kt | 0 .../org/koitharu/kotatsu/core/cache/ContentCache.kt | 0 .../org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt | 0 .../org/koitharu/kotatsu/core/cache/ExpiringValue.kt | 0 .../org/koitharu/kotatsu/core/cache/MemoryContentCache.kt | 0 .../org/koitharu/kotatsu/core/cache/SafeDeferred.kt | 0 .../org/koitharu/kotatsu/core/cache/StubContentCache.kt | 0 .../org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt | 0 .../org/koitharu/kotatsu/core/db/MangaDatabase.kt | 0 .../main/{java => kotlin}/org/koitharu/kotatsu/core/db/Tables.kt | 0 .../org/koitharu/kotatsu/core/db/dao/MangaDao.kt | 0 .../org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/db/dao/TagsDao.kt | 0 .../org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt | 0 .../org/koitharu/kotatsu/core/db/entity/EntityMapping.kt | 0 .../org/koitharu/kotatsu/core/db/entity/MangaEntity.kt | 0 .../org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt | 0 .../org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt | 0 .../org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt | 0 .../org/koitharu/kotatsu/core/db/entity/TagEntity.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt | 0 .../org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt | 0 .../org/koitharu/kotatsu/core/exceptions/CaughtException.kt | 0 .../kotatsu/core/exceptions/CloudFlareProtectedException.kt | 0 .../org/koitharu/kotatsu/core/exceptions/CompositeException.kt | 0 .../koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt | 0 .../org/koitharu/kotatsu/core/exceptions/SyncApiException.kt | 0 .../koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt | 0 .../koitharu/kotatsu/core/exceptions/WrongPasswordException.kt | 0 .../kotatsu/core/exceptions/resolve/DialogErrorObserver.kt | 0 .../koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt | 0 .../kotatsu/core/exceptions/resolve/ExceptionResolver.kt | 0 .../kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt | 0 .../org/koitharu/kotatsu/core/github/AppUpdateRepository.kt | 0 .../org/koitharu/kotatsu/core/github/AppVersion.kt | 0 .../org/koitharu/kotatsu/core/github/VersionId.kt | 0 .../org/koitharu/kotatsu/core/logs/FileLogger.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/logs/Loggers.kt | 0 .../org/koitharu/kotatsu/core/logs/LoggersModule.kt | 0 .../org/koitharu/kotatsu/core/model/FavouriteCategory.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/model/Manga.kt | 0 .../org/koitharu/kotatsu/core/model/MangaHistory.kt | 0 .../org/koitharu/kotatsu/core/model/MangaSource.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/model/ZoomMode.kt | 0 .../org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt | 0 .../koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt | 0 .../kotatsu/core/model/parcelable/ParcelableMangaChapters.kt | 0 .../kotatsu/core/model/parcelable/ParcelableMangaPages.kt | 0 .../kotatsu/core/model/parcelable/ParcelableMangaTags.kt | 0 .../org/koitharu/kotatsu/core/network/AppProxySelector.kt | 0 .../org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt | 0 .../org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt | 0 .../org/koitharu/kotatsu/core/network/CommonHeaders.kt | 0 .../koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt | 0 .../org/koitharu/kotatsu/core/network/DoHManager.kt | 0 .../org/koitharu/kotatsu/core/network/DoHProvider.kt | 0 .../org/koitharu/kotatsu/core/network/GZipInterceptor.kt | 0 .../org/koitharu/kotatsu/core/network/HttpClients.kt | 0 .../org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt | 0 .../org/koitharu/kotatsu/core/network/NetworkModule.kt | 0 .../org/koitharu/kotatsu/core/network/SSLBypass.kt | 0 .../koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt | 0 .../org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt | 0 .../koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt | 0 .../kotatsu/core/network/cookies/PreferencesCookieJar.kt | 0 .../org/koitharu/kotatsu/core/os/NetworkState.kt | 0 .../org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt | 0 .../org/koitharu/kotatsu/core/os/VoiceInputContract.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaDataRepository.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaIntent.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaParser.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaRepository.kt | 0 .../org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt | 0 .../org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt | 0 .../org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt | 0 .../org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt | 0 .../org/koitharu/kotatsu/core/prefs/AppSettings.kt | 0 .../org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt | 0 .../org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt | 0 .../org/koitharu/kotatsu/core/prefs/ColorScheme.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/prefs/ListMode.kt | 0 .../org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt | 0 .../org/koitharu/kotatsu/core/prefs/ReaderMode.kt | 0 .../org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt | 0 .../org/koitharu/kotatsu/core/prefs/SourceSettings.kt | 0 .../org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt | 0 .../org/koitharu/kotatsu/core/ui/BaseActivity.kt | 0 .../org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt | 0 .../org/koitharu/kotatsu/core/ui/BaseFragment.kt | 0 .../org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt | 0 .../org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseService.kt | 0 .../org/koitharu/kotatsu/core/ui/BaseViewModel.kt | 0 .../org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt | 0 .../kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt | 0 .../org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt | 0 .../org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt | 0 .../org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt | 0 .../koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt | 0 .../kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt | 0 .../org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt | 0 .../org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt | 0 .../org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt | 0 .../org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt | 0 .../koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt | 0 .../org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt | 0 .../org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt | 0 .../kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt | 0 .../org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt | 0 .../koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt | 0 .../kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt | 0 .../org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt | 0 .../org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt | 0 .../org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt | 0 .../org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt | 0 .../koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt | 0 .../kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt | 0 .../kotatsu/core/ui/list/SectionedSelectionController.kt | 0 .../kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt | 0 .../core/ui/list/decor/AbstractSelectionItemDecoration.kt | 0 .../koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt | 0 .../kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt | 0 .../koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt | 0 .../kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt | 0 .../org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt | 0 .../kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt | 0 .../org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt | 0 .../org/koitharu/kotatsu/core/ui/model/SortOrder.kt | 0 .../org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt | 0 .../org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt | 0 .../koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt | 0 .../org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt | 0 .../koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt | 0 .../org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt | 0 .../org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt | 0 .../org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt | 0 .../org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt | 0 .../koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt | 0 .../org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt | 0 .../org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt | 0 .../org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt | 0 .../org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt | 0 .../org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt | 0 .../core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt | 0 .../kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt | 0 .../org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt | 0 .../org/koitharu/kotatsu/core/util/AlphanumComparator.kt | 0 .../org/koitharu/kotatsu/core/util/BufferedObserver.kt | 0 .../org/koitharu/kotatsu/core/util/CancellableSource.kt | 0 .../org/koitharu/kotatsu/core/util/CompositeMutex.kt | 0 .../org/koitharu/kotatsu/core/util/EditTextValidator.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/FileSize.kt | 0 .../org/koitharu/kotatsu/core/util/FlowLiveData.kt | 0 .../org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt | 0 .../org/koitharu/kotatsu/core/util/GridTouchHelper.kt | 0 .../org/koitharu/kotatsu/core/util/IdlingDetector.kt | 0 .../org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt | 0 .../org/koitharu/kotatsu/core/util/MediatorStateFlow.kt | 0 .../org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt | 0 .../kotatsu/core/util/RetainedLifecycleCoroutineScope.kt | 0 .../org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt | 0 .../org/koitharu/kotatsu/core/util/ShareHelper.kt | 0 .../org/koitharu/kotatsu/core/util/SingleLiveEvent.kt | 0 .../org/koitharu/kotatsu/core/util/TaggedActivityResult.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/Throttler.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ViewBadge.kt | 0 .../org/koitharu/kotatsu/core/util/WorkManagerHelper.kt | 0 .../org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Android.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Bundle.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Coil.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Collections.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Coroutines.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Cursor.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Date.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Display.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/File.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Flow.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Fragment.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Graphics.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Http.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/IO.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Insets.kt | 0 .../org/koitharu/kotatsu/core/util/ext/LiveData.kt | 0 .../org/koitharu/kotatsu/core/util/ext/LocaleList.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Network.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Other.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Preferences.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Primitive.kt | 0 .../org/koitharu/kotatsu/core/util/ext/RecyclerView.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Resources.kt | 0 .../org/koitharu/kotatsu/core/util/ext/String.kt | 0 .../org/koitharu/kotatsu/core/util/ext/TextView.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Theme.kt | 0 .../org/koitharu/kotatsu/core/util/ext/Throwable.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/util/ext/View.kt | 0 .../org/koitharu/kotatsu/core/util/ext/ViewModel.kt | 0 .../kotatsu/core/util/progress/ImageRequestIndicatorListener.kt | 0 .../kotatsu/core/util/progress/IntPercentLabelFormatter.kt | 0 .../koitharu/kotatsu/core/util/progress/PausingProgressJob.kt | 0 .../org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt | 0 .../org/koitharu/kotatsu/core/util/progress/ProgressJob.kt | 0 .../koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt | 0 .../org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/core/zip/ZipOutput.kt | 0 .../org/koitharu/kotatsu/details/domain/BranchComparator.kt | 0 .../org/koitharu/kotatsu/details/service/MangaPrefetchService.kt | 0 .../kotatsu/details/service/PrefetchCompanionEntryPoint.kt | 0 .../koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt | 0 .../org/koitharu/kotatsu/details/ui/ChaptersFragment.kt | 0 .../org/koitharu/kotatsu/details/ui/ChaptersMapper.kt | 0 .../org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt | 0 .../org/koitharu/kotatsu/details/ui/DetailsActivity.kt | 0 .../org/koitharu/kotatsu/details/ui/DetailsFragment.kt | 0 .../org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt | 0 .../org/koitharu/kotatsu/details/ui/DetailsViewModel.kt | 0 .../org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt | 0 .../org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt | 0 .../org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt | 0 .../org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt | 0 .../org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt | 0 .../org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt | 0 .../kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt | 0 .../org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt | 0 .../org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt | 0 .../koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt | 0 .../org/koitharu/kotatsu/details/ui/model/MangaBranch.kt | 0 .../koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt | 0 .../kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt | 0 .../kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt | 0 .../kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt | 0 .../org/koitharu/kotatsu/download/domain/DownloadState.kt | 0 .../org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt | 0 .../koitharu/kotatsu/download/ui/list/DownloadItemListener.kt | 0 .../org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt | 0 .../org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt | 0 .../org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt | 0 .../koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt | 0 .../kotatsu/download/ui/list/DownloadsSelectionDecoration.kt | 0 .../org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt | 0 .../kotatsu/download/ui/worker/DownloadNotificationFactory.kt | 0 .../kotatsu/download/ui/worker/DownloadStartedObserver.kt | 0 .../org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt | 0 .../org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt | 0 .../org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt | 0 .../org/koitharu/kotatsu/explore/domain/ExploreRepository.kt | 0 .../org/koitharu/kotatsu/explore/ui/ExploreFragment.kt | 0 .../org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt | 0 .../org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt | 0 .../org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt | 0 .../org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt | 0 .../kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt | 0 .../koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt | 0 .../kotatsu/explore/ui/adapter/ExploreListEventListener.kt | 0 .../org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt | 0 .../org/koitharu/kotatsu/favourites/data/EntityMapping.kt | 0 .../koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt | 0 .../koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt | 0 .../org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt | 0 .../org/koitharu/kotatsu/favourites/data/FavouriteManga.kt | 0 .../org/koitharu/kotatsu/favourites/data/FavouritesDao.kt | 0 .../koitharu/kotatsu/favourites/domain/FavouritesRepository.kt | 0 .../org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt | 0 .../favourites/ui/categories/CategoriesSelectionCallback.kt | 0 .../favourites/ui/categories/CategoriesSelectionDecoration.kt | 0 .../favourites/ui/categories/FavouriteCategoriesActivity.kt | 0 .../favourites/ui/categories/FavouriteCategoriesListListener.kt | 0 .../favourites/ui/categories/FavouritesCategoriesViewModel.kt | 0 .../favourites/ui/categories/adapter/CategoriesAdapter.kt | 0 .../kotatsu/favourites/ui/categories/adapter/CategoryAD.kt | 0 .../favourites/ui/categories/adapter/CategoryListModel.kt | 0 .../ui/categories/edit/FavouritesCategoryEditActivity.kt | 0 .../ui/categories/edit/FavouritesCategoryEditViewModel.kt | 0 .../ui/categories/select/FavouriteCategoriesBottomSheet.kt | 0 .../favourites/ui/categories/select/MangaCategoriesViewModel.kt | 0 .../ui/categories/select/adapter/MangaCategoriesAdapter.kt | 0 .../favourites/ui/categories/select/adapter/MangaCategoryAD.kt | 0 .../favourites/ui/categories/select/model/MangaCategoryItem.kt | 0 .../kotatsu/favourites/ui/list/FavouritesListFragment.kt | 0 .../kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt | 0 .../kotatsu/favourites/ui/list/FavouritesListViewModel.kt | 0 .../org/koitharu/kotatsu/history/data/EntityMapping.kt | 0 .../org/koitharu/kotatsu/history/data/HistoryDao.kt | 0 .../org/koitharu/kotatsu/history/data/HistoryEntity.kt | 0 .../org/koitharu/kotatsu/history/data/HistoryWithManga.kt | 0 .../org/koitharu/kotatsu/history/domain/HistoryRepository.kt | 0 .../org/koitharu/kotatsu/history/domain/MangaWithHistory.kt | 0 .../org/koitharu/kotatsu/history/ui/HistoryActivity.kt | 0 .../org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt | 0 .../org/koitharu/kotatsu/history/ui/HistoryListFragment.kt | 0 .../org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt | 0 .../org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt | 0 .../koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt | 0 .../org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt | 0 .../org/koitharu/kotatsu/image/ui/ImageActivity.kt | 0 .../org/koitharu/kotatsu/list/domain/ListExtraProvider.kt | 0 .../org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt | 0 .../org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt | 0 .../org/koitharu/kotatsu/list/ui/MangaListFragment.kt | 0 .../org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt | 0 .../org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt | 0 .../org/koitharu/kotatsu/list/ui/MangaListViewModel.kt | 0 .../org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt | 0 .../koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt | 0 .../koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt | 0 .../kotatsu/list/ui/adapter/MangaDetailsClickListener.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt | 0 .../koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt | 0 .../org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt | 0 .../koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterItem.kt | 0 .../org/koitharu/kotatsu/list/ui/filter/FilterState.kt | 0 .../koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt | 0 .../org/koitharu/kotatsu/list/ui/model/EmptyHint.kt | 0 .../org/koitharu/kotatsu/list/ui/model/EmptyState.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ErrorState.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ListHeader.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ListHeader2.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ListModel.kt | 0 .../org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt | 0 .../org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt | 0 .../org/koitharu/kotatsu/list/ui/model/LoadingState.kt | 0 .../org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt | 0 .../org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt | 0 .../org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt | 0 .../org/koitharu/kotatsu/list/ui/model/MangaListModel.kt | 0 .../{java => kotlin}/org/koitharu/kotatsu/local/data/CacheDir.kt | 0 .../org/koitharu/kotatsu/local/data/CbzFetcher.kt | 0 .../org/koitharu/kotatsu/local/data/CbzFilter.kt | 0 .../org/koitharu/kotatsu/local/data/ImageFileFilter.kt | 0 .../org/koitharu/kotatsu/local/data/LocalManga.kt | 0 .../org/koitharu/kotatsu/local/data/LocalStorageManager.kt | 0 .../org/koitharu/kotatsu/local/data/MangaIndex.kt | 0 .../org/koitharu/kotatsu/local/data/PagesCache.kt | 0 .../org/koitharu/kotatsu/local/data/Qualifiers.kt | 0 .../org/koitharu/kotatsu/local/data/TempFileFilter.kt | 0 .../koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt | 0 .../org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt | 0 .../org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt | 0 .../org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt | 0 .../koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt | 0 .../org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt | 0 .../org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt | 0 .../koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt | 0 .../org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt | 0 .../org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt | 0 .../org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt | 0 .../org/koitharu/kotatsu/local/ui/ImportWorker.kt | 0 .../org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt | 0 .../org/koitharu/kotatsu/local/ui/LocalListFragment.kt | 0 .../org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt | 0 .../org/koitharu/kotatsu/local/ui/LocalListViewModel.kt | 0 .../org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt | 0 .../org/koitharu/kotatsu/main/ui/ExitCallback.kt | 0 .../org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt | 0 .../org/koitharu/kotatsu/main/ui/MainActivity.kt | 0 .../org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt | 0 .../org/koitharu/kotatsu/main/ui/MainViewModel.kt | 0 .../org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt | 0 .../org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt | 0 .../koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt | 0 .../org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt | 0 .../org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt | 0 .../org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt | 0 .../org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt | 0 .../org/koitharu/kotatsu/reader/data/ModelMapping.kt | 0 .../org/koitharu/kotatsu/reader/domain/ChapterPages.kt | 0 .../org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt | 0 .../org/koitharu/kotatsu/reader/domain/PageLoader.kt | 0 .../org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt | 0 .../org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt | 0 .../org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt | 0 .../org/koitharu/kotatsu/reader/ui/PageSaveContract.kt | 0 .../org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderActivity.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderContent.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderManager.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderState.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderToastView.kt | 0 .../org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt | 0 .../org/koitharu/kotatsu/reader/ui/ScrollTimer.kt | 0 .../kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt | 0 .../ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt | 0 .../kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt | 0 .../koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt | 0 .../koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt | 0 .../org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt | 0 .../koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt | 0 .../reader/ui/pager/reversed/ReversedPageAnimTransformer.kt | 0 .../kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt | 0 .../kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt | 0 .../kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt | 0 .../kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt | 0 .../org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt | 0 .../kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt | 0 .../kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt | 0 .../koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt | 0 .../kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt | 0 .../koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt | 0 .../kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt | 0 .../koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt | 0 .../koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt | 0 .../kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt | 0 .../kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt | 0 .../kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt | 0 .../kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt | 0 .../koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt | 0 .../kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt | 0 .../org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt | 0 .../kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt | 0 .../kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt | 0 .../kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt | 0 .../kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt | 0 .../kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt | 0 .../org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt | 0 .../org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt | 0 .../org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt | 0 .../kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt | 0 .../kotatsu/scrobbling/anilist/data/AniListInterceptor.kt | 0 .../kotatsu/scrobbling/anilist/data/AniListRepository.kt | 0 .../org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt | 0 .../kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt | 0 .../kotatsu/scrobbling/common/data/ScrobblerRepository.kt | 0 .../koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt | 0 .../org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt | 0 .../koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt | 0 .../org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblerService.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblerType.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt | 0 .../kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt | 0 .../scrobbling/common/ui/config/ScrobblerConfigActivity.kt | 0 .../scrobbling/common/ui/config/ScrobblerConfigViewModel.kt | 0 .../scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt | 0 .../scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt | 0 .../common/ui/config/adapter/ScrobblingMangaAdapter.kt | 0 .../common/ui/selector/ScrobblingSelectorBottomSheet.kt | 0 .../scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt | 0 .../scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt | 0 .../ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt | 0 .../common/ui/selector/adapter/ScrobblerSelectorAdapter.kt | 0 .../scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt | 0 .../kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt | 0 .../org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt | 0 .../org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt | 0 .../org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt | 0 .../org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt | 0 .../kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt | 0 .../kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt | 0 .../kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt | 0 .../kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt | 0 .../org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt | 0 .../org/koitharu/kotatsu/search/ui/MangaListActivity.kt | 0 .../org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt | 0 .../org/koitharu/kotatsu/search/ui/SearchActivity.kt | 0 .../org/koitharu/kotatsu/search/ui/SearchFragment.kt | 0 .../org/koitharu/kotatsu/search/ui/SearchViewModel.kt | 0 .../org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt | 0 .../org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt | 0 .../org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt | 0 .../kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt | 0 .../koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt | 0 .../kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt | 0 .../kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt | 0 .../kotatsu/search/ui/suggestion/SearchSuggestionListener.kt | 0 .../kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt | 0 .../kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt | 0 .../search/ui/suggestion/adapter/SearchSuggestionAdapter.kt | 0 .../search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt | 0 .../search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt | 0 .../search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt | 0 .../search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt | 0 .../kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt | 0 .../org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt | 0 .../org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt | 0 .../org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt | 0 .../org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/ContentSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/DomainValidator.kt | 0 .../org/koitharu/kotatsu/settings/HistorySettingsFragment.kt | 0 .../kotatsu/settings/NotificationSettingsLegacyFragment.kt | 0 .../org/koitharu/kotatsu/settings/ProxySettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/RootSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/SettingsActivity.kt | 0 .../org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt | 0 .../org/koitharu/kotatsu/settings/SourceSettingsExt.kt | 0 .../org/koitharu/kotatsu/settings/SourceSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/SyncSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt | 0 .../koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt | 0 .../org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt | 0 .../org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt | 0 .../org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt | 0 .../org/koitharu/kotatsu/settings/backup/BackupObserver.kt | 0 .../koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt | 0 .../org/koitharu/kotatsu/settings/backup/BackupViewModel.kt | 0 .../koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt | 0 .../org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt | 0 .../kotatsu/settings/newsources/NewSourcesDialogFragment.kt | 0 .../koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt | 0 .../koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt | 0 .../koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt | 0 .../org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt | 0 .../koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt | 0 .../kotatsu/settings/onboard/adapter/SourceLocaleListener.kt | 0 .../kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt | 0 .../org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt | 0 .../koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt | 0 .../koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt | 0 .../org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt | 0 .../koitharu/kotatsu/settings/sources/SourcesListViewModel.kt | 0 .../kotatsu/settings/sources/adapter/SourceConfigAdapter.kt | 0 .../settings/sources/adapter/SourceConfigAdapterDelegates.kt | 0 .../kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt | 0 .../kotatsu/settings/sources/adapter/SourceConfigListener.kt | 0 .../koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt | 0 .../koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt | 0 .../org/koitharu/kotatsu/settings/tools/ToolsFragment.kt | 0 .../org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt | 0 .../org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt | 0 .../org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt | 0 .../koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt | 0 .../kotatsu/settings/tracker/TrackerSettingsViewModel.kt | 0 .../tracker/categories/TrackerCategoriesConfigAdapter.kt | 0 .../settings/tracker/categories/TrackerCategoriesConfigSheet.kt | 0 .../tracker/categories/TrackerCategoriesConfigViewModel.kt | 0 .../kotatsu/settings/tracker/categories/TrackerCategoryAD.kt | 0 .../org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt | 0 .../koitharu/kotatsu/settings/utils/ActivityListPreference.kt | 0 .../kotatsu/settings/utils/AutoCompleteTextViewPreference.kt | 0 .../org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt | 0 .../kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt | 0 .../koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt | 0 .../org/koitharu/kotatsu/settings/utils/LinksPreference.kt | 0 .../settings/utils/MultiAutoCompleteTextViewPreference.kt | 0 .../org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt | 0 .../org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt | 0 .../org/koitharu/kotatsu/settings/utils/SliderPreference.kt | 0 .../koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt | 0 .../koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt | 0 .../org/koitharu/kotatsu/shelf/domain/ShelfContent.kt | 0 .../org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt | 0 .../org/koitharu/kotatsu/shelf/domain/ShelfSection.kt | 0 .../org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt | 0 .../org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt | 0 .../org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt | 0 .../org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt | 0 .../koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt | 0 .../org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt | 0 .../org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt | 0 .../org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt | 0 .../koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt | 0 .../koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt | 0 .../org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt | 0 .../kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt | 0 .../koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt | 0 .../koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt | 0 .../koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt | 0 .../kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt | 0 .../org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt | 0 .../org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt | 0 .../org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt | 0 .../org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt | 0 .../org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt | 0 .../koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt | 0 .../org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt | 0 .../org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt | 0 .../org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt | 0 .../org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt | 0 .../org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt | 0 .../org/koitharu/kotatsu/sync/data/SyncAuthApi.kt | 0 .../org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt | 0 .../org/koitharu/kotatsu/sync/data/SyncInterceptor.kt | 0 .../org/koitharu/kotatsu/sync/data/SyncSettings.kt | 0 .../org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt | 0 .../org/koitharu/kotatsu/sync/domain/SyncController.kt | 0 .../org/koitharu/kotatsu/sync/domain/SyncHelper.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncProvider.kt | 0 .../org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt | 0 .../koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt | 0 .../kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt | 0 .../koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt | 0 .../org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt | 0 .../org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt | 0 .../org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt | 0 .../org/koitharu/kotatsu/tracker/data/EntityMapping.kt | 0 .../org/koitharu/kotatsu/tracker/data/TrackEntity.kt | 0 .../org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt | 0 .../org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt | 0 .../org/koitharu/kotatsu/tracker/data/TracksDao.kt | 0 .../org/koitharu/kotatsu/tracker/domain/Tracker.kt | 0 .../org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt | 0 .../org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt | 0 .../org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt | 0 .../org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt | 0 .../org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt | 0 .../kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt | 0 .../org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt | 0 .../org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt | 0 .../org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt | 0 .../org/koitharu/kotatsu/tracker/work/TrackWorker.kt | 0 .../koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt | 0 .../org/koitharu/kotatsu/tracker/work/TrackingItem.kt | 0 .../org/koitharu/kotatsu/widget/WidgetUpdater.kt | 0 .../org/koitharu/kotatsu/widget/recent/RecentListFactory.kt | 0 .../org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt | 0 .../org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt | 0 .../org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt | 0 .../org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt | 0 .../org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt | 0 .../org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt | 0 .../org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt | 0 .../kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt | 0 .../kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt | 0 .../org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt | 0 711 files changed, 1 insertion(+) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/KotatsuApp.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/BrowserActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/BrowserCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/BrowserClient.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/ProgressChromeClient.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/AppModule.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/BackupEntry.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/BackupRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/BackupZipInput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/CompositeResult.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/JsonDeserializer.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/backup/JsonSerializer.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/ContentCache.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/ExpiringValue.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/SafeDeferred.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/cache/StubContentCache.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/MangaDatabase.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/Tables.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/dao/MangaDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/dao/TagsDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/entity/TagEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/CaughtException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/CompositeException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/SyncApiException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/WrongPasswordException.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/github/AppVersion.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/github/VersionId.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/logs/FileLogger.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/logs/Loggers.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/logs/LoggersModule.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/FavouriteCategory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/Manga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/MangaHistory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/MangaSource.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/ZoomMode.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaChapters.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaPages.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/AppProxySelector.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/CommonHeaders.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/DoHManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/DoHProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/GZipInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/HttpClients.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/NetworkModule.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/SSLBypass.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/os/NetworkState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/os/VoiceInputContract.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaIntent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaParser.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/AppSettings.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/ColorScheme.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/ListMode.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/ReaderMode.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/prefs/SourceSettings.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/BaseViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/model/SortOrder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/AlphanumComparator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/BufferedObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/CancellableSource.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/CompositeMutex.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/EditTextValidator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/FileSize.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/FlowLiveData.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/GridTouchHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/IdlingDetector.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ShareHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/Throttler.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ViewBadge.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Android.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Bundle.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Coil.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Collections.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Coroutines.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Cursor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Date.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Display.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/File.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Flow.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Fragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Graphics.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Http.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/IO.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Insets.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/LiveData.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/LocaleList.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Network.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Other.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Preferences.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Primitive.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Resources.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/String.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/TextView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Theme.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/Throwable.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/View.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/ext/ViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/core/zip/ZipOutput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/domain/BranchComparator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/service/PrefetchCompanionEntryPoint.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/DetailsActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/DetailsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/model/MangaBranch.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/domain/DownloadState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/adapter/ExploreListEventListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/EntityMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/FavouriteManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoriesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/categories/select/model/MangaCategoryItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/data/EntityMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/data/HistoryDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/data/HistoryEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/data/HistoryWithManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/domain/HistoryRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/HistoryActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/image/ui/ImageActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/MangaListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/FilterState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/EmptyHint.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/EmptyState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ErrorState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ListHeader.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ListModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/LoadingState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/CacheDir.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/CbzFetcher.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/CbzFilter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/ImageFileFilter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/LocalManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/LocalStorageManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/MangaIndex.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/PagesCache.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/Qualifiers.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/TempFileFilter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/ImportWorker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/LocalListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/ExitCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/MainActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/MainViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/data/ModelMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/domain/ChapterPages.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/domain/PageLoader.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/PageSaveContract.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderContent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/ScrollTimer.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageAnimTransformer.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/anilist/data/AniListInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerType.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/MangaListActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/SearchActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/SearchFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/SearchViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/DomainValidator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/RootSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SettingsActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SourceSettingsExt.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/BackupObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/AutoCompleteTextViewPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/LinksPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/MultiAutoCompleteTextViewPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/SliderPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/data/SyncSettings.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/domain/SyncController.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/domain/SyncHelper.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/data/EntityMapping.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/data/TrackEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/data/TracksDao.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/domain/Tracker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/work/TrackWorker.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/tracker/work/TrackingItem.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/WidgetUpdater.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt (100%) rename app/src/main/{java => kotlin}/org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt (100%) diff --git a/app/build.gradle b/app/build.gradle index 99d288a1d..d81bce6d9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,6 +42,7 @@ android { } sourceSets { androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) + main.java.srcDirs += 'src/main/kotlin/' } compileOptions { sourceCompatibility JavaVersion.VERSION_17 diff --git a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/BookmarkEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/BookmarksDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/data/EntityMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/domain/Bookmark.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/domain/BookmarksRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarksGroupAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/model/BookmarksGroup.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/BrowserActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/BrowserCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/BrowserClient.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/BrowserClient.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/OnHistoryChangedListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/ProgressChromeClient.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/ProgressChromeClient.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/ProgressChromeClient.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/ProgressChromeClient.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/WebViewBackPressedCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareClient.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/AppModule.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupEntry.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupEntry.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/BackupEntry.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupEntry.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/BackupRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipInput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipInput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/BackupZipOutput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/CompositeResult.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/CompositeResult.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/CompositeResult.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/CompositeResult.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/JsonDeserializer.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/JsonDeserializer.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/JsonDeserializer.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/JsonDeserializer.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/backup/JsonSerializer.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/backup/JsonSerializer.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/backup/JsonSerializer.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/backup/JsonSerializer.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/ContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/ContentCache.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringValue.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/ExpiringValue.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringValue.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/SafeDeferred.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/SafeDeferred.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/SafeDeferred.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/SafeDeferred.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/cache/StubContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/cache/StubContentCache.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/DatabasePrePopulateCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/MangaDatabase.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/MangaDatabase.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/Tables.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/Tables.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/Tables.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/Tables.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/MangaDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/dao/MangaDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/MangaDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/PreferencesDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TagsDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TagsDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/dao/TagsDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TagsDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/EntityMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaPrefsEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaTagsEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/MangaWithTags.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/entity/TagEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/TagEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/entity/TagEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/entity/TagEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration10To11.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration11To12.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration12To13.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration13To14.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration14To15.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration1To2.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration2To3.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration3To4.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration4To5.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration5To6.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration6To7.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration7To8.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration8To9.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/db/migrations/Migration9To10.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CaughtException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/CaughtException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CaughtException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CloudFlareProtectedException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CompositeException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/CompositeException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/EmptyHistoryException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/SyncApiException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/SyncApiException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/SyncApiException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/SyncApiException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/UnsupportedFileException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/WrongPasswordException.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrongPasswordException.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/WrongPasswordException.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/WrongPasswordException.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/github/AppUpdateRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/github/AppVersion.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/github/AppVersion.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/github/AppVersion.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/github/AppVersion.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/github/VersionId.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/github/VersionId.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/github/VersionId.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/github/VersionId.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/logs/FileLogger.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/logs/FileLogger.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/logs/FileLogger.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/logs/Loggers.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/logs/Loggers.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/logs/Loggers.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/logs/LoggersModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/logs/LoggersModule.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/logs/LoggersModule.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/logs/LoggersModule.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/FavouriteCategory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/FavouriteCategory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/Manga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaHistory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/MangaHistory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaHistory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/MangaSource.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/ZoomMode.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/ZoomMode.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/ZoomMode.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/ZoomMode.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/Parcelable.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaChapters.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaChapters.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaChapters.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaChapters.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaPages.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaPages.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaPages.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaPages.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/model/parcelable/ParcelableMangaTags.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/AppProxySelector.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/CacheLimitInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/CloudFlareInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/CommonHeaders.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeaders.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/CommonHeaders.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/CommonHeadersInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/DoHManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/DoHManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/DoHManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/DoHProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/DoHProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/DoHProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/DoHProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/GZipInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/GZipInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/GZipInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/HttpClients.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/HttpClients.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/HttpClients.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/MirrorSwitchInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/NetworkModule.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/NetworkModule.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/NetworkModule.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/SSLBypass.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/SSLBypass.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/SSLBypass.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/AndroidCookieJar.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/CookieWrapper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/MutableCookieJar.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/network/cookies/PreferencesCookieJar.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/NetworkState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/os/NetworkState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/os/NetworkState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/os/VoiceInputContract.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/VoiceInputContract.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/os/VoiceInputContract.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/os/VoiceInputContract.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaIntent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaIntent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaParser.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaParser.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaParser.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaParser.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconUri.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppWidgetConfig.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ColorScheme.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ColorScheme.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/ColorScheme.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ColorScheme.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ListMode.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ListMode.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/ListMode.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ListMode.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/NetworkPolicy.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderMode.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/ReaderMode.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ReaderMode.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/ScreenshotsPolicy.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/prefs/SourceSettings.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/BaseViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/BaseViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/CoroutineIntentService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/DefaultActivityLifecycleCallbacks.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/AppBottomSheetDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/CheckBoxAlertDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/ErrorDetailsDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/RecyclerViewAlertDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/RememberSelectionDialogListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/StorageSelectDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/dialog/TwoButtonsAlertDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/CoilImageGetter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/CoverSizeResolver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/FaviconFallbackDrawable.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/RegionBitmapDecoder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/image/TrimTransformation.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/FitHeightGridLayoutManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/FitHeightLinearLayoutManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/NestedScrollStateHandle.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnTipCloseListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/PaginationScrollListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/SectionedSelectionController.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/AbstractDividerItemDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/AbstractSelectionItemDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/SpacingItemDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/decor/TypedSpacingItemDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/BubbleAnimator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScroller.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/ScrollbarAnimator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/model/DateTimeAgo.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/model/SortOrder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/model/SortOrder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/model/SortOrder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/model/SortOrder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActionModeDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActionModeListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ActivityRecreationHandle.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/BaseActivityEntryPoint.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CollapseActionViewCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/DefaultTextWatcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/RecyclerViewOwner.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleAction.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleHandle.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ShrinkOnScrollBehavior.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/SpanSizeResolver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/StatusBarDimHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/WindowInsetsDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/BottomSheetHeaderBar.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/CheckableImageView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ChipsView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/CoverImageView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/HideBottomNavigationOnScrollBehavior.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ListItemTextView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SegmentedBarView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SelectableTextView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/ShapeView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/SlidingBottomNavigationView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TwoLinesItemView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/WindowInsetHolder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/AlphanumComparator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/AlphanumComparator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/AlphanumComparator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/AlphanumComparator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/BufferedObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/BufferedObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/BufferedObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/BufferedObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/CancellableSource.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/CancellableSource.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/CancellableSource.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/CancellableSource.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/CompositeMutex.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeMutex.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/CompositeMutex.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeMutex.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/EditTextValidator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/EditTextValidator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/EditTextValidator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/EditTextValidator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/FileSize.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/FileSize.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/FileSize.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/FileSize.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/FlowLiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/FlowLiveData.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/GoneOnInvisibleListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/GridTouchHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/GridTouchHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/GridTouchHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/GridTouchHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/IdlingDetector.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/IdlingDetector.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/IdlingDetector.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/IdlingDetector.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/IncognitoModeIndicator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/MediatorStateFlow.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/RecyclerViewScrollCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/RetainedLifecycleCoroutineScope.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ScreenOrientationHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ShareHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ShareHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ShareHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/Throttler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Throttler.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/Throttler.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/Throttler.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ViewBadge.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ViewBadge.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ViewBadge.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ViewBadge.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/WorkManagerHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/WorkServiceStopHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Android.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Android.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Bundle.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Bundle.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Bundle.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Bundle.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coil.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coil.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coil.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coil.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Collections.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Collections.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coroutines.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Coroutines.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Coroutines.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Cursor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Cursor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Cursor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Cursor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Date.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Date.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Date.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Date.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Display.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Display.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Display.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Display.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/File.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/File.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Flow.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Flow.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Fragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Fragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Fragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Fragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Graphics.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Graphics.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Graphics.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Graphics.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Http.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Http.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/IO.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/IO.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/IO.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/IO.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Insets.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Insets.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Insets.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Insets.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/LiveData.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/LocaleList.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LocaleList.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/LocaleList.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LocaleList.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Network.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Network.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Network.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Network.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Other.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Other.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Preferences.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Preferences.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Preferences.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Preferences.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Primitive.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Primitive.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Primitive.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Primitive.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/RecyclerView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Resources.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Resources.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Resources.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Resources.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/String.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/String.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/TextView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/TextView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/TextView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/TextView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Theme.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Theme.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/Throwable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/Throwable.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/View.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/View.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/ext/ViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/ViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/ext/ViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/ViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ImageRequestIndicatorListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/IntPercentLabelFormatter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/PausingProgressJob.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressDeferred.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressJob.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/ProgressResponseBody.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/util/progress/TimeLeftEstimator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/core/zip/ZipOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/core/zip/ZipOutput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/core/zip/ZipOutput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/domain/BranchComparator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/BranchComparator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/domain/BranchComparator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/domain/BranchComparator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/service/PrefetchCompanionEntryPoint.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/PrefetchCompanionEntryPoint.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/service/PrefetchCompanionEntryPoint.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/service/PrefetchCompanionEntryPoint.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersBottomSheetMediator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/BranchAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/BranchesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ChapterListItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/HistoryInfo.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/ListModelConversionExt.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/model/MangaBranch.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/MangaBranch.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/model/MangaBranch.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/model/MangaBranch.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingItemDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrollingInfoAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/domain/DownloadState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadItemModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadNotificationFactory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/PausingHandle.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/PausingReceiver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreGridSpanSizeLookup.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreDiffCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreListEventListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreListEventListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/adapter/ExploreListEventListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreListEventListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/EntityMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteCategoryEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouriteManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/FavouritesActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesListListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoriesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoriesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoriesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoriesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoriesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/adapter/MangaCategoryAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/model/MangaCategoryItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/model/MangaCategoryItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/model/MangaCategoryItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/model/MangaCategoryItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/EntityMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/data/EntityMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/data/EntityMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/data/HistoryDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/data/HistoryEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/data/HistoryWithManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryWithManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/data/HistoryWithManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryWithManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/domain/HistoryRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/image/ui/ImageActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/image/ui/ImageActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/image/ui/ImageActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/ItemSizeResolver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/ListModeBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/BadgeADUtil.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/EmptyHintAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/EmptyStateListAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ErrorFooterAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ErrorStateListAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeader2AD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeaderAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListHeaderClickListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/ListStateHolderListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/LoadingFooterAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/LoadingStateAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaDetailsClickListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/RelatedDateItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterAdapterDelegates.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterDiffCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/FilterState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/OnFilterChangedListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/EmptyHint.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/EmptyHint.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/EmptyHint.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/EmptyHint.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/EmptyState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/EmptyState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/EmptyState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/EmptyState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ErrorFooter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ErrorState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ErrorState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ErrorState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ErrorState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListHeader.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListHeader.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListHeader2.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/LoadingFooter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/LoadingState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/LoadingState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/LoadingState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaGridModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaItemModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaListDetailedModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/MangaListModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/CacheDir.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/CacheDir.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/CacheDir.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/CacheDir.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/CbzFetcher.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/CbzFetcher.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/CbzFetcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/CbzFilter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/CbzFilter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/CbzFilter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/ImageFileFilter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/ImageFileFilter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/ImageFileFilter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/ImageFileFilter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/LocalManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/LocalManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalStorageManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/LocalStorageManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalStorageManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/MangaIndex.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/MangaIndex.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/PagesCache.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/Qualifiers.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/Qualifiers.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/Qualifiers.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/TempFileFilter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/TempFileFilter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/TempFileFilter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/TempFileFilter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaDirOutput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaOutput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaUtil.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/output/LocalMangaZipOutput.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/util/ExtraCloseableSource.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportWorker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/ImportWorker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportWorker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/ExitCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/ExitCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/ExitCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActionButtonBehavior.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/MainViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/AppBarOwner.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/BottomNavOwner.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/NoModalBottomSheetOwner.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/owners/SnackbarOwner.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/data/ModelMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/data/ModelMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/data/ModelMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/data/ModelMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChapterPages.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChapterPages.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/domain/ChapterPages.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChapterPages.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/domain/PageLoader.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ReaderColorFilter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageLabelFormatter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveContract.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveContract.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveContract.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveContract.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderContent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderContent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderContent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderContent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderControlDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderInfoBarView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderSliderListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderToastView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ScrollTimer.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ScrollTimer.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/ScrollTimer.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ScrollTimer.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ShadowViewTarget.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BasePageHolder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/OnBoundsScrollListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderPage.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageAnimTransformer.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageAnimTransformer.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageAnimTransformer.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageAnimTransformer.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPageHolder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedPagesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageAnimTransformer.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerPaginationListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonLayoutManager.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonScalingFrame.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/MangaPageFetcher.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/OnPageSelectListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PageThumbnail.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/TargetScrollObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/ScrobblingModule.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListAuthenticator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/AniListRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/data/ScoreFormat.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/anilist/domain/AniListScrobbler.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblerStorage.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/data/ScrobblingEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerMangaInfo.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerType.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerType.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerType.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerType.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblerUser.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingInfo.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/model/ScrobblingStatus.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingHeaderAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerHintAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerMangaSelectionDecoration.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblerSelectorAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/adapter/ScrobblingMangaAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/model/ScrobblerHint.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALAuthenticator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/data/MALRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/mal/domain/MALScrobbler.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriAuthenticator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/data/ShikimoriRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/shikimori/domain/ShikimoriScrobbler.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/domain/MangaSearchRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/MangaListActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/MangaListActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/MangaListActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/MangaSuggestionsProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/SearchActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/SearchViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/MultiSearchAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionItemCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionQueryAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionSourceAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionTagsAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/model/SearchSuggestionItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchBehavior.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchEditText.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/search/ui/widget/SearchToolbar.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/AppearanceSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/DomainValidator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/DomainValidator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/NotificationSettingsLegacyFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/ReaderSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/RootSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SettingsActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SuggestionsSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/SyncSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AppUpdateDialog.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/AppBackupAgent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/SourcesSelectAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocaleListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/adapter/SourceLocalesAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/model/SourceLocale.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigAdapterDelegates.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigDiffCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/adapter/SourceConfigListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/auth/SourceAuthActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/model/SourceConfigItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/model/StorageUsage.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/views/MemoryUsageView.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoryAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/AboutLinksPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/ActivityListPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/AutoCompleteTextViewPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/AutoCompleteTextViewPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/AutoCompleteTextViewPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/AutoCompleteTextViewPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextDefaultSummaryProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/EditTextSummaryProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/LinksPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/LinksPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/LinksPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/LinksPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/MultiAutoCompleteTextViewPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/MultiAutoCompleteTextViewPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/MultiAutoCompleteTextViewPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/MultiAutoCompleteTextViewPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/MultiSummaryProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/RingtonePickContract.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/SliderPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/SliderPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/SliderPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/TagsAutoCompleteProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/ThemeChooserPreference.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfSelectionCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/MangaItemDiffCallback.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ScrollKeepObserver.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfGroupAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/adapter/ShelfListEventListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsListener.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/size/ShelfSizeBottomSheet.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/model/ShelfSectionModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/data/SuggestionWithManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/MangaSuggestion.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/SuggestionRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/domain/TagsBlacklist.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncAuthApi.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncAuthenticator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncInterceptor.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncSettings.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/data/SyncSettings.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/data/SyncSettings.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncAuthResult.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncController.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncController.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncController.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncHelper.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/domain/SyncHelper.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/domain/SyncHelper.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAccountAuthenticator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthenticatorService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncSettingsIntent.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/favourites/FavouritesSyncService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/history/HistorySyncService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/data/EntityMapping.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/EntityMapping.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogEntity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TrackLogWithManga.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/data/TracksDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/data/TracksDao.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/MangaTracking.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/model/TrackingLogItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedMenuProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/FeedItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/model/ListModelConversionExt.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackerNotificationChannels.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackingItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackingItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackingItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackingItem.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/WidgetUpdater.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/WidgetUpdater.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfListFactory.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfWidgetProvider.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfWidgetService.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectAdapter.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/adapter/CategorySelectItemAD.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt similarity index 100% rename from app/src/main/java/org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/model/CategoryItem.kt From dc358ae6a21635b2a58bac88a9eb76a06eab32d1 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 24 May 2023 11:52:09 +0300 Subject: [PATCH 10/90] Refactor manga loading --- .../kotatsu/core/model/DoubleManga.kt | 76 ++++++++ .../org/koitharu/kotatsu/core/model/Manga.kt | 4 + .../kotatsu/core/parser/MangaIntent.kt | 11 +- .../details/domain/DetailsInteractor.kt | 94 ++++++++++ .../kotatsu/details/ui/ChaptersFragment.kt | 12 +- .../kotatsu/details/ui/ChaptersMapper.kt | 2 +- .../kotatsu/details/ui/DetailsViewModel.kt | 175 +++++++----------- .../details/ui/MangaDetailsDelegate.kt | 89 --------- .../history/domain/HistoryRepository.kt | 15 -- .../kotatsu/local/domain/DoubleMangaLoader.kt | 66 +++++++ .../local/domain/LocalMangaRepository.kt | 8 +- .../kotatsu/reader/domain/ChaptersLoader.kt | 28 ++- .../kotatsu/reader/ui/ReaderActivity.kt | 2 +- .../kotatsu/reader/ui/ReaderViewModel.kt | 71 +++---- .../ui/config/ReaderConfigBottomSheet.kt | 2 +- .../ui/thumbnails/PagesThumbnailsViewModel.kt | 16 +- app/src/main/res/raw/tags_redlist | 3 + 17 files changed, 397 insertions(+), 277 deletions(-) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt new file mode 100644 index 000000000..460286fa1 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt @@ -0,0 +1,76 @@ +package org.koitharu.kotatsu.core.model + +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.reader.data.filterChapters + +data class DoubleManga( + private val remoteManga: Result?, + private val localManga: Result?, +) { + + constructor(manga: Manga) : this( + remoteManga = if (manga.source != MangaSource.LOCAL) Result.success(manga) else null, + localManga = if (manga.source == MangaSource.LOCAL) Result.success(manga) else null, + ) + + val remote: Manga? + get() = remoteManga?.getOrNull() + + val local: Manga? + get() = localManga?.getOrNull() + + val any: Manga? + get() = remote ?: local + + val hasRemote: Boolean + get() = remoteManga?.isSuccess == true + + val hasLocal: Boolean + get() = localManga?.isSuccess == true + + val chapters: List? by lazy(LazyThreadSafetyMode.PUBLICATION) { + mergeChapters() + } + + fun requireAny(): Manga { + val result = remoteManga?.getOrNull() ?: localManga?.getOrNull() + if (result != null) { + return result + } + throw ( + remoteManga?.exceptionOrNull() + ?: localManga?.exceptionOrNull() + ?: IllegalStateException("No online either local manga available") + ) + } + + fun filterChapters(branch: String?) = DoubleManga( + remoteManga?.map { it.filterChapters(branch) }, + localManga?.map { it.filterChapters(branch) }, + ) + + private fun mergeChapters(): List? { + val remoteChapters = remote?.chapters + val localChapters = local?.chapters + if (localChapters == null && remoteChapters == null) { + return null + } + val localMap = if (!localChapters.isNullOrEmpty()) { + localChapters.associateByTo(LinkedHashMap(localChapters.size)) { it.id } + } else { + null + } + val result = ArrayList(maxOf(remoteChapters?.size ?: 0, localChapters?.size ?: 0)) + remoteChapters?.forEach { r -> + localMap?.remove(r.id)?.let { l -> + result.add(l) + } ?: result.add(r) + } + localMap?.values?.let { + result.addAll(it) + } + return result + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt index 4ed4c7885..cbfc5e1f8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt @@ -5,6 +5,7 @@ import org.koitharu.kotatsu.core.util.ext.iterator import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mapToSet fun Collection.ids() = mapToSet { it.id } @@ -54,3 +55,6 @@ fun Manga.getPreferredBranch(history: MangaHistory?): String? { } return candidates.ifEmpty { groups }.maxByOrNull { it.value.size }?.key } + +val Manga.isLocal: Boolean + get() = source == MangaSource.LOCAL diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt index 5c3d54a17..8ab582147 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaIntent.kt @@ -12,28 +12,31 @@ import org.koitharu.kotatsu.parsers.model.Manga class MangaIntent private constructor( @JvmField val manga: Manga?, - @JvmField val mangaId: Long, + @JvmField val id: Long, @JvmField val uri: Uri?, ) { constructor(intent: Intent?) : this( manga = intent?.getParcelableExtraCompat(KEY_MANGA)?.manga, - mangaId = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE, + id = intent?.getLongExtra(KEY_ID, ID_NONE) ?: ID_NONE, uri = intent?.data, ) constructor(savedStateHandle: SavedStateHandle) : this( manga = savedStateHandle.get(KEY_MANGA)?.manga, - mangaId = savedStateHandle[KEY_ID] ?: ID_NONE, + id = savedStateHandle[KEY_ID] ?: ID_NONE, uri = savedStateHandle[BaseActivity.EXTRA_DATA], ) constructor(args: Bundle?) : this( manga = args?.getParcelableCompat(KEY_MANGA)?.manga, - mangaId = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE, + id = args?.getLong(KEY_ID, ID_NONE) ?: ID_NONE, uri = null, ) + val mangaId: Long + get() = if (id != ID_NONE) id else manga?.id ?: uri?.lastPathSegment?.toLongOrNull() ?: ID_NONE + companion object { const val ID_NONE = 0L diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt new file mode 100644 index 000000000..3968e4399 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt @@ -0,0 +1,94 @@ +package org.koitharu.kotatsu.details.domain + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map +import org.koitharu.kotatsu.core.model.DoubleManga +import org.koitharu.kotatsu.core.model.isLocal +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler +import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo +import org.koitharu.kotatsu.tracker.domain.TrackingRepository +import org.koitharu.kotatsu.util.ext.printStackTraceDebug +import java.io.IOException +import javax.inject.Inject + +class DetailsInteractor @Inject constructor( + private val historyRepository: HistoryRepository, + private val favouritesRepository: FavouritesRepository, + private val localMangaRepository: LocalMangaRepository, + private val trackingRepository: TrackingRepository, + private val settings: AppSettings, + private val scrobblers: Set<@JvmSuppressWildcards Scrobbler>, +) { + + fun observeIsFavourite(mangaId: Long): Flow { + return favouritesRepository.observeCategoriesIds(mangaId) + .map { it.isNotEmpty() } + } + + fun observeNewChapters(mangaId: Long): Flow { + return settings.observeAsFlow(AppSettings.KEY_TRACKER_ENABLED) { isTrackerEnabled } + .flatMapLatest { isEnabled -> + if (isEnabled) { + trackingRepository.observeNewChaptersCount(mangaId) + } else { + flowOf(0) + } + } + } + + fun observeScrobblingInfo(mangaId: Long): Flow> { + return combine( + scrobblers.map { it.observeScrobblingInfo(mangaId) }, + ) { scrobblingInfo -> + scrobblingInfo.filterNotNull() + } + } + + suspend fun deleteLocalManga(manga: Manga) { + val victim = if (manga.isLocal) manga else localMangaRepository.findSavedManga(manga)?.manga + checkNotNull(victim) { "Cannot find saved manga for ${manga.title}" } + val original = if (manga.isLocal) localMangaRepository.getRemoteManga(manga) else manga + localMangaRepository.delete(victim) || throw IOException("Unable to delete file") + runCatchingCancellable { + historyRepository.deleteOrSwap(victim, original) + }.onFailure { + it.printStackTraceDebug() + } + } + + fun observeIncognitoMode(mangaFlow: Flow): Flow { + return mangaFlow + .distinctUntilChangedBy { it?.isNsfw } + .flatMapLatest { manga -> + if (manga != null) { + historyRepository.observeShouldSkip(manga) + } else { + settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled } + } + } + } + + suspend fun updateLocal(subject: DoubleManga?, localManga: LocalManga): DoubleManga? { + return if (subject?.any?.id == localManga.manga.id) { + subject.copy( + localManga = runCatchingCancellable { + localMangaRepository.getDetails(localManga.manga) + }, + ) + } else { + subject + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index e82993114..e3b3c1e64 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -160,12 +160,14 @@ class ChaptersFragment : val selectedIds = selectionController?.peekCheckedIds() ?: return false val allItems = chaptersAdapter?.items.orEmpty() val items = allItems.withIndex().filter { (_, x) -> x.chapter.id in selectedIds } - menu.findItem(R.id.action_save).isVisible = items.none { (_, x) -> - x.chapter.source == MangaSource.LOCAL - } - menu.findItem(R.id.action_delete).isVisible = items.all { (_, x) -> - x.chapter.source == MangaSource.LOCAL + var canSave = true + var canDelete = true + items.forEach { (_, x) -> + val isLocal = x.isDownloaded || x.chapter.source == MangaSource.LOCAL + if (isLocal) canSave = false else canDelete = false } + menu.findItem(R.id.action_save).isVisible = canSave + menu.findItem(R.id.action_delete).isVisible = canDelete menu.findItem(R.id.action_select_all).isVisible = items.size < allItems.size menu.findItem(R.id.action_mark_current).isVisible = items.size == 1 mode.title = items.size.toString() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt index 618d623e1..27a937c0c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersMapper.kt @@ -52,7 +52,7 @@ fun mapChapters( isCurrent = chapter.id == currentId, isUnread = isUnread, isNew = false, - isDownloaded = false, + isDownloaded = remoteManga != null, ) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index 0d3101f28..927e9b80c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -8,6 +8,7 @@ import androidx.core.net.toUri import androidx.core.text.getSpans import androidx.core.text.parseAsHtml import androidx.lifecycle.LiveData +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asFlow import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope @@ -25,82 +26,74 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.update import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository +import org.koitharu.kotatsu.core.model.DoubleManga +import org.koitharu.kotatsu.core.model.getPreferredBranch +import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.util.SingleLiveEvent import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.core.util.ext.computeSize +import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.core.util.ext.toFileOrNull import org.koitharu.kotatsu.details.domain.BranchComparator +import org.koitharu.kotatsu.details.domain.DetailsInteractor import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.HistoryInfo import org.koitharu.kotatsu.details.ui.model.MangaBranch import org.koitharu.kotatsu.download.ui.worker.DownloadWorker -import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.DoubleMangaLoader import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingStatus -import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.util.ext.printStackTraceDebug -import java.io.IOException import javax.inject.Inject @HiltViewModel class DetailsViewModel @Inject constructor( private val historyRepository: HistoryRepository, - favouritesRepository: FavouritesRepository, - private val localMangaRepository: LocalMangaRepository, - trackingRepository: TrackingRepository, private val bookmarksRepository: BookmarksRepository, private val settings: AppSettings, private val scrobblers: Set<@JvmSuppressWildcards Scrobbler>, private val imageGetter: Html.ImageGetter, - private val delegate: MangaDetailsDelegate, @LocalStorageChanges private val localStorageChanges: SharedFlow, private val downloadScheduler: DownloadWorker.Scheduler, + private val interactor: DetailsInteractor, + savedStateHandle: SavedStateHandle, + private val mangaLoader: DoubleMangaLoader, ) : BaseViewModel() { + private val intent = MangaIntent(savedStateHandle) + private val mangaId = intent.mangaId + private val doubleManga: MutableStateFlow = MutableStateFlow(intent.manga?.let { DoubleManga(it) }) private var loadingJob: Job val onShowToast = SingleLiveEvent() val onDownloadStarted = SingleLiveEvent() - private val mangaData = combine( - delegate.onlineManga, - delegate.localManga, - ) { o, l -> - o ?: l - }.stateIn(viewModelScope, SharingStarted.Lazily, null) + private val mangaData = doubleManga.map { it?.any } + .stateIn(viewModelScope, SharingStarted.Eagerly, doubleManga.value?.any) - private val history = historyRepository.observeOne(delegate.mangaId) + private val history = historyRepository.observeOne(mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) - private val favourite = favouritesRepository.observeCategoriesIds(delegate.mangaId).map { it.isNotEmpty() } + private val favourite = interactor.observeIsFavourite(mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) - private val newChapters = settings.observeAsFlow(AppSettings.KEY_TRACKER_ENABLED) { isTrackerEnabled } - .flatMapLatest { isEnabled -> - if (isEnabled) { - trackingRepository.observeNewChaptersCount(delegate.mangaId) - } else { - flowOf(0) - } - }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, 0) + private val newChapters = interactor.observeNewChapters(mangaId) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, 0) private val chaptersQuery = MutableStateFlow("") + private val selectedBranch = MutableStateFlow(null) private val chaptersReversed = settings.observeAsFlow(AppSettings.KEY_REVERSE_CHAPTERS) { chaptersReverse } .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) @@ -112,9 +105,9 @@ class DetailsViewModel @Inject constructor( val historyInfo: LiveData = combine( mangaData, - delegate.selectedBranch, + selectedBranch, history, - historyRepository.observeShouldSkip(mangaData), + interactor.observeIncognitoMode(mangaData), ) { m, b, h, im -> HistoryInfo(m, b, h, im) }.asFlowLiveData( @@ -126,10 +119,11 @@ class DetailsViewModel @Inject constructor( if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList()) }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) - val localSize = delegate.localManga + val localSize = doubleManga .map { - if (it != null) { - val file = it.url.toUri().toFileOrNull() + val local = it?.local + if (local != null) { + val file = local.url.toUri().toFileOrNull() file?.computeSize() ?: 0L } else { 0L @@ -152,46 +146,38 @@ class DetailsViewModel @Inject constructor( val isScrobblingAvailable: Boolean get() = scrobblers.any { it.isAvailable } - val scrobblingInfo: LiveData> = combine( - scrobblers.map { it.observeScrobblingInfo(delegate.mangaId) }, - ) { scrobblingInfo -> - scrobblingInfo.filterNotNull() - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + val scrobblingInfo: LiveData> = interactor.observeScrobblingInfo(mangaId) + .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) val branches: LiveData> = combine( - delegate.onlineManga, - delegate.localManga, - delegate.selectedBranch, - ) { m, l, b -> - val chapters = concat(m?.chapters, l?.chapters) - if (chapters.isEmpty()) return@combine emptyList() + doubleManga, + selectedBranch, + ) { m, b -> + val chapters = m?.chapters + if (chapters.isNullOrEmpty()) return@combine emptyList() chapters.groupBy { x -> x.branch } .map { x -> MangaBranch(x.key, x.value.size, x.key == b) } .sortedWith(BranchComparator()) }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) - val selectedBranchName = delegate.selectedBranch + val selectedBranchName = selectedBranch .asFlowLiveData(viewModelScope.coroutineContext, null) val isChaptersEmpty: LiveData = combine( - delegate.onlineManga, - delegate.localManga, + doubleManga, isLoading.asFlow(), - ) { manga, local, loading -> - (manga != null && manga.chapters.isNullOrEmpty()) && - (local != null && local.chapters.isNullOrEmpty()) && - !loading + ) { manga, loading -> + manga?.any != null && manga.chapters.isNullOrEmpty() && !loading }.asFlowLiveData(viewModelScope.coroutineContext, false) val chapters = combine( combine( - delegate.onlineManga, - delegate.localManga, + doubleManga, history, - delegate.selectedBranch, + selectedBranch, newChapters, - ) { manga, local, history, branch, news -> - mapChapters(manga, local, history, news, branch) + ) { manga, history, branch, news -> + mapChapters(manga?.remote, manga?.local, history, news, branch) }, chaptersReversed, chaptersQuery, @@ -200,7 +186,7 @@ class DetailsViewModel @Inject constructor( }.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default) val selectedBranchValue: String? - get() = delegate.selectedBranch.value + get() = selectedBranch.value init { loadingJob = doLoad() @@ -216,20 +202,14 @@ class DetailsViewModel @Inject constructor( } fun deleteLocal() { - val m = delegate.localManga.value + val m = doubleManga.value?.local if (m == null) { onShowToast.call(R.string.file_not_found) return } launchLoadingJob(Dispatchers.Default) { - val manga = if (m.source == MangaSource.LOCAL) m else localMangaRepository.findSavedManga(m)?.manga - checkNotNull(manga) { "Cannot find saved manga for ${m.title}" } - val original = localMangaRepository.getRemoteManga(manga) - localMangaRepository.delete(manga) || throw IOException("Unable to delete file") - runCatchingCancellable { - historyRepository.deleteOrSwap(manga, original) - } - onMangaRemoved.emitCall(manga) + interactor.deleteLocalManga(m) + onMangaRemoved.emitCall(m) } } @@ -245,11 +225,7 @@ class DetailsViewModel @Inject constructor( } fun setSelectedBranch(branch: String?) { - delegate.selectedBranch.value = branch - } - - fun getRemoteManga(): Manga? { - return delegate.onlineManga.value + selectedBranch.value = branch } fun performChapterSearch(query: String?) { @@ -260,7 +236,7 @@ class DetailsViewModel @Inject constructor( val scrobbler = getScrobbler(index) ?: return launchJob(Dispatchers.Default) { scrobbler.updateScrobblingInfo( - mangaId = delegate.mangaId, + mangaId = mangaId, rating = rating, status = status, comment = null, @@ -272,26 +248,32 @@ class DetailsViewModel @Inject constructor( val scrobbler = getScrobbler(index) ?: return launchJob(Dispatchers.Default) { scrobbler.unregisterScrobbling( - mangaId = delegate.mangaId, + mangaId = mangaId, ) } } fun markChapterAsCurrent(chapterId: Long) { launchJob(Dispatchers.Default) { - val manga = checkNotNull(mangaData.value) - val chapters = checkNotNull(manga.getChapters(selectedBranchValue)) + val manga = checkNotNull(doubleManga.value) + val chapters = checkNotNull(manga.filterChapters(selectedBranchValue).chapters) val chapterIndex = chapters.indexOfFirst { it.id == chapterId } check(chapterIndex in chapters.indices) { "Chapter not found" } val percent = chapterIndex / chapters.size.toFloat() - historyRepository.addOrUpdate(manga = manga, chapterId = chapterId, page = 0, scroll = 0, percent = percent) + historyRepository.addOrUpdate( + manga = manga.requireAny(), + chapterId = chapterId, + page = 0, + scroll = 0, + percent = percent, + ) } } fun download(chaptersIds: Set?) { launchJob(Dispatchers.Default) { downloadScheduler.schedule( - delegate.onlineManga.value ?: checkNotNull(manga.value), + doubleManga.requireValue().requireAny(), chaptersIds, ) onDownloadStarted.emitCall(Unit) @@ -299,7 +281,12 @@ class DetailsViewModel @Inject constructor( } private fun doLoad() = launchLoadingJob(Dispatchers.Default) { - delegate.doLoad() + val result = mangaLoader.load(intent) + val manga = result.requireAny() + // find default branch + val hist = historyRepository.getOne(manga) + selectedBranch.value = manga.getPreferredBranch(hist) + doubleManga.value = result } private fun List.filterSearch(query: String): List { @@ -313,21 +300,9 @@ class DetailsViewModel @Inject constructor( private suspend fun onDownloadComplete(downloadedManga: LocalManga?) { downloadedManga ?: return - val currentManga = mangaData.value ?: return - if (currentManga.id != downloadedManga.manga.id) { - return - } - if (currentManga.source == MangaSource.LOCAL) { - reload() - } else { - viewModelScope.launch(Dispatchers.Default) { - runCatchingCancellable { - localMangaRepository.getDetails(downloadedManga.manga) - }.onSuccess { - delegate.publishManga(it) - }.onFailure { - it.printStackTraceDebug() - } + launchJob { + doubleManga.update { + interactor.updateLocal(it, downloadedManga) } } } @@ -353,18 +328,4 @@ class DetailsViewModel @Inject constructor( } return scrobbler } - - private fun concat(a: List?, b: List?): List { - return when { - a == null && b == null -> emptyList() - a == null && b != null -> b - a != null && b == null -> a - a != null && b != null -> buildList(a.size + b.size) { - addAll(a) - addAll(b) - } - - else -> error("This shouldn't have happened") - } - } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt deleted file mode 100644 index eee5e04e6..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/MangaDetailsDelegate.kt +++ /dev/null @@ -1,89 +0,0 @@ -package org.koitharu.kotatsu.details.ui - -import androidx.lifecycle.SavedStateHandle -import dagger.hilt.android.ViewModelLifecycle -import dagger.hilt.android.scopes.ViewModelScoped -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.stateIn -import org.koitharu.kotatsu.core.model.getPreferredBranch -import org.koitharu.kotatsu.core.os.NetworkState -import org.koitharu.kotatsu.core.parser.MangaDataRepository -import org.koitharu.kotatsu.core.parser.MangaIntent -import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.local.domain.LocalMangaRepository -import org.koitharu.kotatsu.parsers.exception.NotFoundException -import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.util.runCatchingCancellable -import org.koitharu.kotatsu.util.ext.printStackTraceDebug -import javax.inject.Inject - -@ViewModelScoped -class MangaDetailsDelegate @Inject constructor( - savedStateHandle: SavedStateHandle, - lifecycle: ViewModelLifecycle, - private val mangaDataRepository: MangaDataRepository, - private val historyRepository: HistoryRepository, - private val localMangaRepository: LocalMangaRepository, - private val mangaRepositoryFactory: MangaRepository.Factory, - networkState: NetworkState, -) { - private val viewModelScope = RetainedLifecycleCoroutineScope(lifecycle) - - private val intent = MangaIntent(savedStateHandle) - private val onlineMangaStateFlow = MutableStateFlow(null) - private val localMangaStateFlow = MutableStateFlow(null) - - val onlineManga = combine( - onlineMangaStateFlow, - networkState, - ) { m, s -> m.takeIf { s } } - .stateIn(viewModelScope, SharingStarted.Lazily, null) - val localManga = localMangaStateFlow.asStateFlow() - - val selectedBranch = MutableStateFlow(null) - val mangaId = intent.manga?.id ?: intent.mangaId - - init { - intent.manga?.let { - publishManga(it) - } - } - - suspend fun doLoad() { - var manga = mangaDataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", "") - publishManga(manga) - manga = mangaRepositoryFactory.create(manga.source).getDetails(manga) - // find default branch - val hist = historyRepository.getOne(manga) - selectedBranch.value = manga.getPreferredBranch(hist) - publishManga(manga) - runCatchingCancellable { - if (manga.source == MangaSource.LOCAL) { - val m = localMangaRepository.getRemoteManga(manga) ?: return@runCatchingCancellable null - mangaRepositoryFactory.create(m.source).getDetails(m) - } else { - localMangaRepository.findSavedManga(manga)?.manga - } - }.onFailure { error -> - error.printStackTraceDebug() - }.onSuccess { - if (it != null) { - publishManga(it) - } - } - } - - fun publishManga(manga: Manga) { - if (manga.source == MangaSource.LOCAL) { - localMangaStateFlow - } else { - onlineMangaStateFlow - }.value = manga - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt index 784f74280..3cc4a81b0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt @@ -4,9 +4,7 @@ import androidx.room.withTransaction import dagger.Reusable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import org.koitharu.kotatsu.core.db.MangaDatabase @@ -17,7 +15,6 @@ import org.koitharu.kotatsu.core.db.entity.toMangaTag import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.ui.util.ReversibleHandle import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.history.data.HistoryEntity @@ -161,18 +158,6 @@ class HistoryRepository @Inject constructor( .distinctUntilChanged() } - fun observeShouldSkip(mangaFlow: Flow): Flow { - return mangaFlow - .distinctUntilChangedBy { it?.isNsfw } - .flatMapLatest { m -> - if (m != null) { - observeShouldSkip(m) - } else { - settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled } - } - } - } - private suspend fun recover(ids: Collection) { db.withTransaction { for (id in ids) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt new file mode 100644 index 000000000..5cf8325c1 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt @@ -0,0 +1,66 @@ +package org.koitharu.kotatsu.local.domain + +import dagger.Reusable +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import org.koitharu.kotatsu.core.model.DoubleManga +import org.koitharu.kotatsu.core.model.isLocal +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaIntent +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.parsers.exception.NotFoundException +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import javax.inject.Inject + +@Reusable +class DoubleMangaLoader @Inject constructor( + private val mangaDataRepository: MangaDataRepository, + private val localMangaRepository: LocalMangaRepository, + private val mangaRepositoryFactory: MangaRepository.Factory, +) { + + suspend fun load(manga: Manga): DoubleManga = coroutineScope { + val remoteDeferred = async(Dispatchers.Default) { loadRemote(manga) } + val localDeferred = async(Dispatchers.Default) { loadLocal(manga) } + DoubleManga( + remoteManga = remoteDeferred.await(), + localManga = localDeferred.await(), + ) + } + + suspend fun load(mangaId: Long): DoubleManga { + val manga = mangaDataRepository.findMangaById(mangaId) ?: throwNFE() + return load(manga) + } + + suspend fun load(intent: MangaIntent): DoubleManga { + val manga = mangaDataRepository.resolveIntent(intent) ?: throwNFE() + return load(manga) + } + + private suspend fun loadLocal(manga: Manga): Result? { + return runCatchingCancellable { + if (manga.isLocal) { + localMangaRepository.getDetails(manga) + } else { + localMangaRepository.findSavedManga(manga)?.manga + } ?: return null + } + } + + private suspend fun loadRemote(manga: Manga): Result? { + return runCatchingCancellable { + val seed = if (manga.isLocal) { + localMangaRepository.getRemoteManga(manga) + } else { + manga + } ?: return null + val repository = mangaRepositoryFactory.create(seed.source) + repository.getDetails(seed) + } + } + + private fun throwNFE(): Nothing = throw NotFoundException("Cannot find manga", "") +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt index 9763882a7..6d3964978 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch import kotlinx.coroutines.runInterruptible +import org.koitharu.kotatsu.core.model.isLocal import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.util.CompositeMutex import org.koitharu.kotatsu.core.util.ext.deleteAwait @@ -99,8 +100,11 @@ class LocalMangaRepository @Inject constructor( suspend fun deleteChapters(manga: Manga, ids: Set) { lockManga(manga.id) try { - LocalMangaUtil(manga).deleteChapters(ids) - localStorageChanges.emit(LocalManga(manga)) + val subject = if (manga.isLocal) manga else checkNotNull(findSavedManga(manga)) { + "Manga is not stored on local storage" + }.manga + LocalMangaUtil(subject).deleteChapters(ids) + localStorageChanges.emit(LocalManga(subject)) } finally { unlockManga(manga.id) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt index 334efab8a..6cff4c94f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt @@ -4,8 +4,8 @@ import android.util.LongSparseArray import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import javax.inject.Inject @@ -17,17 +17,27 @@ class ChaptersLoader @Inject constructor( private val mangaRepositoryFactory: MangaRepository.Factory, ) { - val chapters = LongSparseArray() + private val chapters = LongSparseArray() private val chapterPages = ChapterPages() private val mutex = Mutex() - suspend fun loadPrevNextChapter(manga: Manga, currentId: Long, isNext: Boolean) { + val size: Int + get() = chapters.size() + + suspend fun init(manga: DoubleManga) = mutex.withLock { + chapters.clear() + manga.chapters?.forEach { + chapters.put(it.id, it) + } + } + + suspend fun loadPrevNextChapter(manga: DoubleManga, currentId: Long, isNext: Boolean) { val chapters = manga.chapters ?: return val predicate: (MangaChapter) -> Boolean = { it.id == currentId } val index = if (isNext) chapters.indexOfFirst(predicate) else chapters.indexOfLast(predicate) if (index == -1) return val newChapter = chapters.getOrNull(if (isNext) index + 1 else index - 1) ?: return - val newPages = loadChapter(manga, newChapter.id) + val newPages = loadChapter(newChapter.id) mutex.withLock { if (chapterPages.chaptersSize > 1) { // trim pages @@ -47,14 +57,16 @@ class ChaptersLoader @Inject constructor( } } - suspend fun loadSingleChapter(manga: Manga, chapterId: Long) { - val pages = loadChapter(manga, chapterId) + suspend fun loadSingleChapter(chapterId: Long) { + val pages = loadChapter(chapterId) mutex.withLock { chapterPages.clear() chapterPages.addLast(chapterId, pages) } } + fun peekChapter(chapterId: Long): MangaChapter? = chapters[chapterId] + fun getPages(chapterId: Long): List { return chapterPages.subList(chapterId) } @@ -69,9 +81,9 @@ class ChaptersLoader @Inject constructor( fun snapshot() = chapterPages.toList() - private suspend fun loadChapter(manga: Manga, chapterId: Long): List { + private suspend fun loadChapter(chapterId: Long): List { val chapter = checkNotNull(chapters[chapterId]) { "Requested chapter not found" } - val repo = mangaRepositoryFactory.create(manga.source) + val repo = mangaRepositoryFactory.create(chapter.source) return repo.getPages(chapter).mapIndexed { index, page -> ReaderPage(page, index, chapterId) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index 3fff9ab9a..6dfb02e93 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -183,7 +183,7 @@ class ReaderActivity : val state = viewModel.getCurrentState() ?: return false PagesThumbnailsSheet.show( supportFragmentManager, - viewModel.manga ?: return false, + viewModel.manga?.any ?: return false, state.chapterId, state.page, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index f092a5c06..029bf76b3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.reader.ui import android.net.Uri -import android.util.LongSparseArray import androidx.activity.result.ActivityResultLauncher import androidx.annotation.AnyThread import androidx.annotation.MainThread @@ -16,6 +15,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine @@ -33,6 +33,7 @@ import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository +import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.os.ShortcutsUpdater import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaIntent @@ -50,12 +51,11 @@ import org.koitharu.kotatsu.core.util.ext.processLifecycleScope import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.local.domain.DoubleMangaLoader import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.runCatchingCancellable -import org.koitharu.kotatsu.reader.data.filterChapters import org.koitharu.kotatsu.reader.domain.ChaptersLoader import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings @@ -79,6 +79,7 @@ class ReaderViewModel @Inject constructor( private val pageLoader: PageLoader, private val chaptersLoader: ChaptersLoader, private val shortcutsUpdater: ShortcutsUpdater, + private val mangaLoader: DoubleMangaLoader, ) : BaseViewModel() { private val intent = MangaIntent(savedStateHandle) @@ -90,9 +91,9 @@ class ReaderViewModel @Inject constructor( private var bookmarkJob: Job? = null private var stateChangeJob: Job? = null private val currentState = MutableStateFlow(savedStateHandle[ReaderActivity.EXTRA_STATE]) - private val mangaData = MutableStateFlow(intent.manga) - private val chapters: LongSparseArray - get() = chaptersLoader.chapters + private val mangaData = MutableStateFlow(intent.manga?.let { DoubleManga(it) }) + private val mangaFlow: Flow + get() = mangaData.map { it?.any } val readerMode = MutableLiveData() val onPageSaved = SingleLiveEvent() @@ -100,7 +101,7 @@ class ReaderViewModel @Inject constructor( val uiState = MutableLiveData(null) val content = MutableLiveData(ReaderContent(emptyList(), null)) - val manga: Manga? + val manga: DoubleManga? get() = mangaData.value val readerAnimation = settings.observeAsLiveData( @@ -124,13 +125,13 @@ class ReaderViewModel @Inject constructor( val readerSettings = ReaderSettings( parentScope = viewModelScope, settings = settings, - colorFilterFlow = mangaData.flatMapLatest { + colorFilterFlow = mangaFlow.flatMapLatest { if (it == null) flowOf(null) else dataRepository.observeColorFilter(it.id) }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null), ) val isScreenshotsBlockEnabled = combine( - mangaData, + mangaFlow, settings.observeAsFlow(AppSettings.KEY_SCREENSHOTS_POLICY) { screenshotsPolicy }, ) { manga, policy -> policy == ScreenshotsPolicy.BLOCK_ALL || @@ -138,7 +139,7 @@ class ReaderViewModel @Inject constructor( }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) val isBookmarkAdded: LiveData = currentState.flatMapLatest { state -> - val manga = mangaData.value + val manga = mangaData.value?.any if (state == null || manga == null) { flowOf(false) } else { @@ -154,7 +155,7 @@ class ReaderViewModel @Inject constructor( if (key == AppSettings.KEY_READER_SLIDER) notifyStateChanged() }.launchIn(viewModelScope + Dispatchers.Default) launchJob(Dispatchers.Default) { - val mangaId = mangaData.filterNotNull().first().id + val mangaId = mangaFlow.filterNotNull().first().id shortcutsUpdater.notifyMangaOpened(mangaId) } } @@ -166,7 +167,7 @@ class ReaderViewModel @Inject constructor( fun switchMode(newMode: ReaderMode) { launchJob { - val manga = checkNotNull(mangaData.value) + val manga = checkNotNull(mangaData.value?.any) dataRepository.saveReaderMode( manga = manga, mode = newMode, @@ -189,7 +190,7 @@ class ReaderViewModel @Inject constructor( } val readerState = state ?: currentState.value ?: return historyRepository.saveStateAsync( - manga = mangaData.value ?: return, + manga = mangaData.value?.any ?: return, state = readerState, percent = computePercent(readerState.chapterId, readerState.page), ) @@ -242,7 +243,7 @@ class ReaderViewModel @Inject constructor( loadingJob = launchLoadingJob(Dispatchers.Default) { prevJob?.cancelAndJoin() content.postValue(ReaderContent(emptyList(), null)) - chaptersLoader.loadSingleChapter(mangaData.requireValue(), id) + chaptersLoader.loadSingleChapter(id) content.postValue(ReaderContent(chaptersLoader.snapshot(), ReaderState(id, page, 0))) } } @@ -285,7 +286,7 @@ class ReaderViewModel @Inject constructor( val state = checkNotNull(currentState.value) val page = checkNotNull(getCurrentPage()) { "Page not found" } val bookmark = Bookmark( - manga = checkNotNull(mangaData.value), + manga = checkNotNull(mangaData.value?.any), pageId = page.id, chapterId = state.chapterId, page = state.page, @@ -305,7 +306,7 @@ class ReaderViewModel @Inject constructor( } bookmarkJob = launchJob { loadingJob?.join() - val manga = checkNotNull(mangaData.value) + val manga = checkNotNull(mangaData.value?.any) val page = checkNotNull(getCurrentPage()) { "Page not found" } bookmarksRepository.removeBookmark(manga.id, page.id) onShowToast.call(R.string.bookmark_removed) @@ -314,32 +315,31 @@ class ReaderViewModel @Inject constructor( private fun loadImpl() { loadingJob = launchLoadingJob(Dispatchers.Default) { - var manga = dataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", "") + var manga = + DoubleManga(dataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", "")) mangaData.value = manga - val repo = mangaRepositoryFactory.create(manga.source) - manga = repo.getDetails(manga) - manga.chapters?.forEach { - chapters.put(it.id, it) - } + manga = mangaLoader.load(intent) + chaptersLoader.init(manga) // determine mode - val mode = detectReaderMode(manga, repo) + val singleManga = manga.requireAny() + val mode = detectReaderMode(singleManga) // obtain state if (currentState.value == null) { - currentState.value = historyRepository.getOne(manga)?.let { + currentState.value = historyRepository.getOne(singleManga)?.let { ReaderState(it) - } ?: ReaderState(manga, preselectedBranch) + } ?: ReaderState(singleManga, preselectedBranch) } - val branch = chapters[currentState.value?.chapterId ?: 0L]?.branch + val branch = chaptersLoader.peekChapter(currentState.value?.chapterId ?: 0L)?.branch mangaData.value = manga.filterChapters(branch) readerMode.emitValue(mode) - chaptersLoader.loadSingleChapter(manga, requireNotNull(currentState.value).chapterId) + chaptersLoader.loadSingleChapter(requireNotNull(currentState.value).chapterId) // save state if (!isIncognito) { currentState.value?.let { val percent = computePercent(it.chapterId, it.page) - historyRepository.addOrUpdate(manga, it.chapterId, it.page, it.scroll, percent) + historyRepository.addOrUpdate(singleManga, it.chapterId, it.page, it.scroll, percent) } } notifyStateChanged() @@ -367,15 +367,16 @@ class ReaderViewModel @Inject constructor( } } - private suspend fun detectReaderMode(manga: Manga, repo: MangaRepository): ReaderMode { + private suspend fun detectReaderMode(manga: Manga): ReaderMode { dataRepository.getReaderMode(manga.id)?.let { return it } val defaultMode = settings.defaultReaderMode if (!settings.isReaderModeDetectionEnabled || defaultMode == ReaderMode.WEBTOON) { return defaultMode } - val chapter = currentState.value?.chapterId?.let(chapters::get) + val chapter = currentState.value?.chapterId?.let { chaptersLoader.peekChapter(it) } ?: manga.chapters?.randomOrNull() ?: error("There are no chapters in this manga") + val repo = mangaRepositoryFactory.create(manga.source) val pages = repo.getPages(chapter) return runCatchingCancellable { val isWebtoon = dataRepository.determineMangaIsWebtoon(repo, pages) @@ -390,12 +391,12 @@ class ReaderViewModel @Inject constructor( @WorkerThread private fun notifyStateChanged() { val state = getCurrentState() - val chapter = state?.chapterId?.let(chapters::get) + val chapter = state?.chapterId?.let { chaptersLoader.peekChapter(it) } val newState = ReaderUiState( - mangaName = manga?.title, + mangaName = manga?.any?.title, chapterName = chapter?.name, chapterNumber = chapter?.number ?: 0, - chaptersTotal = manga?.getChapters(chapter?.branch)?.size ?: 0, + chaptersTotal = manga?.any?.getChapters(chapter?.branch)?.size ?: 0, totalPages = if (chapter != null) chaptersLoader.getPagesCount(chapter.id) else 0, currentPage = state?.page ?: 0, isSliderEnabled = settings.isReaderSliderEnabled, @@ -405,8 +406,8 @@ class ReaderViewModel @Inject constructor( } private fun computePercent(chapterId: Long, pageIndex: Int): Float { - val branch = chapters[chapterId]?.branch - val chapters = manga?.getChapters(branch) ?: return PROGRESS_NONE + val branch = chaptersLoader.peekChapter(chapterId)?.branch + val chapters = manga?.any?.getChapters(branch) ?: return PROGRESS_NONE val chaptersCount = chapters.size val chapterIndex = chapters.indexOfFirst { x -> x.id == chapterId } val pagesCount = chaptersLoader.getPagesCount(chapterId) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt index d83552079..714819f51 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt @@ -108,7 +108,7 @@ class ReaderConfigBottomSheet : R.id.button_color_filter -> { val page = viewModel.getCurrentPage() ?: return - val manga = viewModel.manga ?: return + val manga = viewModel.manga?.any ?: return startActivity(ColorFilterConfigActivity.newIntent(v.context, manga, page)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt index bf9e86070..934245a5c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -12,8 +12,8 @@ import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter +import org.koitharu.kotatsu.local.domain.DoubleMangaLoader import org.koitharu.kotatsu.parsers.util.SuspendLazy -import org.koitharu.kotatsu.reader.data.filterChapters import org.koitharu.kotatsu.reader.domain.ChaptersLoader import javax.inject.Inject @@ -22,6 +22,7 @@ class PagesThumbnailsViewModel @Inject constructor( savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, private val chaptersLoader: ChaptersLoader, + private val mangaLoader: DoubleMangaLoader, ) : BaseViewModel() { private val currentPageIndex: Int = savedStateHandle[PagesThumbnailsSheet.ARG_CURRENT_PAGE] ?: -1 @@ -30,13 +31,9 @@ class PagesThumbnailsViewModel @Inject constructor( private val repository = mangaRepositoryFactory.create(manga.source) private val mangaDetails = SuspendLazy { - repository.getDetails(manga).let { - chaptersLoader.chapters.clear() + mangaLoader.load(manga).let { val b = manga.chapters?.find { ch -> ch.id == initialChapterId }?.branch branch.emitValue(b) - it.getChapters(b)?.forEach { ch -> - chaptersLoader.chapters.put(ch.id, ch) - } it.filterChapters(b) } } @@ -50,7 +47,8 @@ class PagesThumbnailsViewModel @Inject constructor( init { loadingJob = launchJob(Dispatchers.Default) { - chaptersLoader.loadSingleChapter(mangaDetails.get(), initialChapterId) + chaptersLoader.init(mangaDetails.get()) + chaptersLoader.loadSingleChapter(initialChapterId) updateList() } } @@ -80,14 +78,14 @@ class PagesThumbnailsViewModel @Inject constructor( val mangaChapters = mangaDetails.tryGet().getOrNull()?.chapters.orEmpty() val hasPrevChapter = snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id val hasNextChapter = snapshot.lastOrNull()?.chapterId != mangaChapters.lastOrNull()?.id - val pages = buildList(snapshot.size + chaptersLoader.chapters.size() + 2) { + val pages = buildList(snapshot.size + chaptersLoader.size + 2) { if (hasPrevChapter) { add(LoadingFooter(-1)) } var previousChapterId = 0L for (page in snapshot) { if (page.chapterId != previousChapterId) { - chaptersLoader.chapters[page.chapterId]?.let { + chaptersLoader.peekChapter(page.chapterId)?.let { add(ListHeader(it.name, 0, null)) } previousChapterId = page.chapterId diff --git a/app/src/main/res/raw/tags_redlist b/app/src/main/res/raw/tags_redlist index ecc5d9f11..537f2ecb8 100644 --- a/app/src/main/res/raw/tags_redlist +++ b/app/src/main/res/raw/tags_redlist @@ -18,3 +18,6 @@ scat тентакли футанари инцест +boys' love +girls' love +bdsm From 47f346b42c4cb0e51e0b676adc21cb1482805b1f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 24 May 2023 14:27:04 +0300 Subject: [PATCH 11/90] Respect system DataSaver --- .../kotatsu/core/prefs/AppSettings.kt | 34 ++++++++++++++----- .../details/service/MangaPrefetchService.kt | 2 +- .../kotatsu/reader/domain/PageLoader.kt | 2 +- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index fe2e24192..bf6cab962 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -2,7 +2,9 @@ package org.koitharu.kotatsu.core.prefs import android.content.Context import android.content.SharedPreferences +import android.net.ConnectivityManager import android.net.Uri +import android.os.Build import android.provider.Settings import androidx.annotation.FloatRange import androidx.appcompat.app.AppCompatDelegate @@ -179,10 +181,14 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isUnstableUpdatesAllowed: Boolean get() = prefs.getBoolean(KEY_UPDATES_UNSTABLE, false) - fun isContentPrefetchEnabled(): Boolean { - val policy = NetworkPolicy.from(prefs.getString(KEY_PREFETCH_CONTENT, null), NetworkPolicy.NEVER) - return policy.isNetworkAllowed(connectivityManager) - } + val isContentPrefetchEnabled: Boolean + get() { + if (isBackgroundNetworkRestricted()) { + return false + } + val policy = NetworkPolicy.from(prefs.getString(KEY_PREFETCH_CONTENT, null), NetworkPolicy.NEVER) + return policy.isNetworkAllowed(connectivityManager) + } var sourcesOrder: List get() = prefs.getString(KEY_SOURCES_ORDER, null) @@ -301,10 +307,14 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { get() = prefs.getFloat(KEY_READER_AUTOSCROLL_SPEED, 0f) set(@FloatRange(from = 0.0, to = 1.0) value) = prefs.edit { putFloat(KEY_READER_AUTOSCROLL_SPEED, value) } - fun isPagesPreloadEnabled(): Boolean { - val policy = NetworkPolicy.from(prefs.getString(KEY_PAGES_PRELOAD, null), NetworkPolicy.NON_METERED) - return policy.isNetworkAllowed(connectivityManager) - } + val isPagesPreloadEnabled: Boolean + get() { + if (isBackgroundNetworkRestricted()) { + return false + } + val policy = NetworkPolicy.from(prefs.getString(KEY_PAGES_PRELOAD, null), NetworkPolicy.NON_METERED) + return policy.isNetworkAllowed(connectivityManager) + } fun getMangaSources(includeHidden: Boolean): List { val list = remoteSources.toMutableList() @@ -342,6 +352,14 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { fun observe() = prefs.observe() + private fun isBackgroundNetworkRestricted(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + connectivityManager.restrictBackgroundStatus == ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED + } else { + false + } + } + companion object { const val PAGE_SWITCH_TAPS = "taps" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt index 4a549c6e7..189c3e00c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt @@ -116,7 +116,7 @@ class MangaPrefetchService : CoroutineIntentService() { return false } val entryPoint = EntryPointAccessors.fromApplication(context, PrefetchCompanionEntryPoint::class.java) - return entryPoint.contentCache.isCachingEnabled && entryPoint.settings.isContentPrefetchEnabled() + return entryPoint.contentCache.isCachingEnabled && entryPoint.settings.isContentPrefetchEnabled } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt index 1fef8621f..49701829a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -74,7 +74,7 @@ class PageLoader @Inject constructor( } fun isPrefetchApplicable(): Boolean { - return repository is RemoteMangaRepository && settings.isPagesPreloadEnabled() + return repository is RemoteMangaRepository && settings.isPagesPreloadEnabled } @AnyThread From 5a0c54e00ff26fc5a6eac00fb32fae49ca421c4d Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 27 May 2023 12:25:49 +0300 Subject: [PATCH 12/90] Replace LiveData with StateFlow --- .../kotatsu/core/os/ShortcutsUpdaterTest.kt | 4 +- .../settings/backup/AppBackupAgentTest.kt | 2 +- .../kotlin/org/koitharu/kotatsu/KotatsuApp.kt | 2 +- .../kotatsu/bookmarks/ui/BookmarksFragment.kt | 6 +- .../bookmarks/ui/BookmarksViewModel.kt | 17 ++- .../org/koitharu/kotatsu/core/AppModule.kt | 2 +- .../exceptions/resolve/DialogErrorObserver.kt | 5 +- .../core/exceptions/resolve/ErrorObserver.kt | 4 +- .../resolve/SnackbarErrorObserver.kt | 5 +- .../org/koitharu/kotatsu/core/model/Manga.kt | 4 + .../kotatsu/core/os/ShortcutsUpdater.kt | 2 +- .../core/parser/MangaDataRepository.kt | 70 --------- .../kotatsu/core/parser/MangaRepository.kt | 2 +- .../kotatsu/core/prefs/AppSettings.kt | 2 +- .../kotatsu/core/prefs/AppSettingsObserver.kt | 20 +-- .../koitharu/kotatsu/core/ui/BaseViewModel.kt | 29 ++-- .../core/ui/util/CountedBooleanLiveData.kt | 31 ---- .../core/ui/util/ReversibleActionObserver.kt | 9 +- .../org/koitharu/kotatsu/core/util/Event.kt | 36 +++++ .../kotatsu/core/util/FlowLiveData.kt | 86 ----------- .../kotatsu/core/util/SingleLiveEvent.kt | 50 ------- .../kotatsu/core/util/ext/EventFlow.kt | 18 +++ .../koitharu/kotatsu/core/util/ext/Flow.kt | 10 ++ .../kotatsu/core/util/ext/FlowObserver.kt | 35 +++++ .../kotatsu/core/util/ext/LiveData.kt | 32 ----- .../details/domain/DetailsInteractor.kt | 24 +--- .../domain/DoubleMangaLoadUseCase.kt} | 19 ++- .../domain}/model/DoubleManga.kt | 2 +- .../details/service/MangaPrefetchService.kt | 2 +- .../kotatsu/details/ui/ChaptersFragment.kt | 1 + .../kotatsu/details/ui/DetailsActivity.kt | 29 ++-- .../kotatsu/details/ui/DetailsFragment.kt | 6 +- .../kotatsu/details/ui/DetailsViewModel.kt | 107 +++++++------- .../scrobbling/ScrobblingInfoBottomSheet.kt | 10 +- .../kotatsu/download/domain/DownloadState.kt | 4 +- .../download/ui/list/DownloadsActivity.kt | 8 +- .../download/ui/list/DownloadsViewModel.kt | 22 +-- .../ui/worker/DownloadStartedObserver.kt | 6 +- .../download/ui/worker/DownloadWorker.kt | 4 +- .../explore/domain/ExploreRepository.kt | 2 +- .../kotatsu/explore/ui/ExploreFragment.kt | 8 +- .../kotatsu/explore/ui/ExploreViewModel.kt | 30 ++-- .../categories/FavouriteCategoriesActivity.kt | 4 +- .../FavouritesCategoriesViewModel.kt | 30 ++-- .../edit/FavouritesCategoryEditActivity.kt | 6 +- .../edit/FavouritesCategoryEditViewModel.kt | 33 ++--- .../select/FavouriteCategoriesBottomSheet.kt | 4 +- .../select/MangaCategoriesViewModel.kt | 6 +- .../ui/list/FavouritesListFragment.kt | 1 + .../ui/list/FavouritesListViewModel.kt | 25 ++-- .../{domain => data}/HistoryRepository.kt | 5 +- .../history/domain/HistoryUpdateUseCase.kt | 38 +++++ .../domain/{ => model}/MangaWithHistory.kt | 4 +- .../kotatsu/history/ui/HistoryListFragment.kt | 1 + .../history/ui/HistoryListViewModel.kt | 33 ++--- .../ui/util/ReadingProgressDrawable.kt | 2 +- .../history/ui/util/ReadingProgressView.kt | 2 +- .../kotatsu/list/ui/MangaListFragment.kt | 8 +- .../kotatsu/list/ui/MangaListViewModel.kt | 27 ++-- .../list/ui/adapter/MangaGridItemAD.kt | 2 +- .../ui/adapter/MangaListDetailedItemAD.kt | 2 +- .../list/ui/filter/FilterBottomSheet.kt | 1 + .../list/ui/filter/FilterCoordinator.kt | 15 +- .../list/ui/model/ListModelConversionExt.kt | 2 +- .../{domain => data}/LocalMangaRepository.kt | 7 +- .../data/importer/SingleMangaImporter.kt | 2 +- .../local/data/input/LocalMangaDirInput.kt | 2 +- .../local/data/input/LocalMangaInput.kt | 2 +- .../local/data/input/LocalMangaZipInput.kt | 2 +- .../local/domain/DeleteLocalMangaUseCase.kt | 42 ++++++ .../{data => domain/model}/LocalManga.kt | 6 +- .../local/ui/LocalChaptersRemoveService.kt | 4 +- .../kotatsu/local/ui/LocalListFragment.kt | 3 +- .../kotatsu/local/ui/LocalListViewModel.kt | 46 +++--- .../local/ui/LocalStorageCleanupWorker.kt | 2 +- .../koitharu/kotatsu/main/ui/MainActivity.kt | 6 +- .../koitharu/kotatsu/main/ui/MainViewModel.kt | 35 +++-- .../main/ui/protect/ProtectActivity.kt | 6 +- .../main/ui/protect/ProtectViewModel.kt | 5 +- .../kotatsu/reader/domain/ChaptersLoader.kt | 2 +- .../reader/domain/DetectReaderModeUseCase.kt | 97 +++++++++++++ .../kotatsu/reader/ui/PageSaveHelper.kt | 12 +- .../kotatsu/reader/ui/ReaderActivity.kt | 32 +++-- .../kotatsu/reader/ui/ReaderViewModel.kt | 136 ++++++------------ .../colorfilter/ColorFilterConfigActivity.kt | 4 +- .../ColorFilterConfigBackPressedDispatcher.kt | 1 + .../colorfilter/ColorFilterConfigViewModel.kt | 26 ++-- .../ui/config/ReaderConfigBottomSheet.kt | 8 +- .../reader/ui/pager/BaseReaderFragment.kt | 1 + .../pager/reversed/ReversedReaderFragment.kt | 1 + .../ui/pager/standard/PagerReaderFragment.kt | 1 + .../ui/pager/webtoon/WebtoonReaderFragment.kt | 1 + .../ui/thumbnails/PagesThumbnailsSheet.kt | 4 +- .../ui/thumbnails/PagesThumbnailsViewModel.kt | 17 ++- .../remotelist/ui/RemoteListViewModel.kt | 15 +- .../ui/config/ScrobblerConfigActivity.kt | 4 +- .../ui/config/ScrobblerConfigViewModel.kt | 25 ++-- .../selector/ScrobblingSelectorBottomSheet.kt | 6 +- .../selector/ScrobblingSelectorViewModel.kt | 29 ++-- .../kotatsu/search/ui/SearchActivity.kt | 1 + .../kotatsu/search/ui/SearchViewModel.kt | 8 +- .../search/ui/multi/MultiSearchActivity.kt | 14 +- .../search/ui/multi/MultiSearchViewModel.kt | 25 ++-- .../ui/suggestion/SearchSuggestionFragment.kt | 1 + .../suggestion/SearchSuggestionViewModel.kt | 12 +- .../settings/about/AboutSettingsFragment.kt | 4 +- .../settings/about/AboutSettingsViewModel.kt | 5 +- .../settings/backup/BackupDialogFragment.kt | 6 +- .../settings/backup/BackupViewModel.kt | 9 +- .../settings/backup/RestoreDialogFragment.kt | 6 +- .../settings/backup/RestoreViewModel.kt | 9 +- .../newsources/NewSourcesDialogFragment.kt | 1 + .../newsources/NewSourcesViewModel.kt | 19 ++- .../settings/onboard/OnboardDialogFragment.kt | 1 + .../settings/onboard/OnboardViewModel.kt | 4 +- .../settings/protect/ProtectSetupActivity.kt | 1 + .../settings/protect/ProtectSetupViewModel.kt | 16 ++- .../settings/sources/SourcesListFragment.kt | 4 +- .../settings/sources/SourcesListViewModel.kt | 47 +++--- .../kotatsu/settings/tools/ToolsFragment.kt | 1 + .../kotatsu/settings/tools/ToolsViewModel.kt | 23 ++- .../tracker/TrackerSettingsFragment.kt | 1 + .../tracker/TrackerSettingsViewModel.kt | 7 +- .../TrackerCategoriesConfigSheet.kt | 1 + .../TrackerCategoriesConfigViewModel.kt | 6 +- ...itory.kt => ShelfContentObserveUseCase.kt} | 34 +---- .../shelf/domain/{ => model}/ShelfContent.kt | 4 +- .../shelf/domain/{ => model}/ShelfSection.kt | 2 +- .../kotatsu/shelf/ui/ShelfFragment.kt | 8 +- .../kotatsu/shelf/ui/ShelfViewModel.kt | 49 ++++--- .../shelf/ui/config/ShelfSettingsActivity.kt | 3 +- .../config/ShelfSettingsAdapterDelegates.kt | 2 +- .../shelf/ui/config/ShelfSettingsItemModel.kt | 10 +- .../shelf/ui/config/ShelfSettingsViewModel.kt | 10 +- .../suggestions/ui/SuggestionsViewModel.kt | 11 +- .../suggestions/ui/SuggestionsWorker.kt | 2 +- .../kotatsu/sync/ui/SyncAuthActivity.kt | 6 +- .../kotatsu/sync/ui/SyncAuthViewModel.kt | 17 +-- .../kotatsu/tracker/domain/Tracker.kt | 6 +- .../kotatsu/tracker/ui/feed/FeedFragment.kt | 6 +- .../kotatsu/tracker/ui/feed/FeedViewModel.kt | 13 +- .../tracker/ui/updates/UpdatesViewModel.kt | 12 +- .../kotatsu/tracker/work/TrackWorker.kt | 15 +- .../widget/recent/RecentListFactory.kt | 2 +- .../widget/recent/RecentWidgetService.kt | 2 +- .../widget/shelf/ShelfConfigActivity.kt | 4 +- .../widget/shelf/ShelfConfigViewModel.kt | 16 ++- 147 files changed, 1042 insertions(+), 1034 deletions(-) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/EventFlow.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt rename app/src/main/kotlin/org/koitharu/kotatsu/{local/domain/DoubleMangaLoader.kt => details/domain/DoubleMangaLoadUseCase.kt} (79%) rename app/src/main/kotlin/org/koitharu/kotatsu/{core => details/domain}/model/DoubleManga.kt (97%) rename app/src/main/kotlin/org/koitharu/kotatsu/history/{domain => data}/HistoryRepository.kt (96%) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryUpdateUseCase.kt rename app/src/main/kotlin/org/koitharu/kotatsu/history/domain/{ => model}/MangaWithHistory.kt (77%) rename app/src/main/kotlin/org/koitharu/kotatsu/local/{domain => data}/LocalMangaRepository.kt (95%) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DeleteLocalMangaUseCase.kt rename app/src/main/kotlin/org/koitharu/kotatsu/local/{data => domain/model}/LocalManga.kt (92%) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/DetectReaderModeUseCase.kt rename app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/{ShelfRepository.kt => ShelfContentObserveUseCase.kt} (74%) rename app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/{ => model}/ShelfContent.kt (89%) rename app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/{ => model}/ShelfSection.kt (62%) diff --git a/app/src/androidTest/java/org/koitharu/kotatsu/core/os/ShortcutsUpdaterTest.kt b/app/src/androidTest/java/org/koitharu/kotatsu/core/os/ShortcutsUpdaterTest.kt index 4b1784bed..6b9de214f 100644 --- a/app/src/androidTest/java/org/koitharu/kotatsu/core/os/ShortcutsUpdaterTest.kt +++ b/app/src/androidTest/java/org/koitharu/kotatsu/core/os/ShortcutsUpdaterTest.kt @@ -8,7 +8,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest -import javax.inject.Inject import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue @@ -19,7 +18,8 @@ import org.junit.runner.RunWith import org.koitharu.kotatsu.SampleData import org.koitharu.kotatsu.awaitForIdle import org.koitharu.kotatsu.core.db.MangaDatabase -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository +import javax.inject.Inject @HiltAndroidTest @RunWith(AndroidJUnit4::class) diff --git a/app/src/androidTest/java/org/koitharu/kotatsu/settings/backup/AppBackupAgentTest.kt b/app/src/androidTest/java/org/koitharu/kotatsu/settings/backup/AppBackupAgentTest.kt index f885ddb36..9984821cc 100644 --- a/app/src/androidTest/java/org/koitharu/kotatsu/settings/backup/AppBackupAgentTest.kt +++ b/app/src/androidTest/java/org/koitharu/kotatsu/settings/backup/AppBackupAgentTest.kt @@ -17,7 +17,7 @@ import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import java.io.File import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt index b8a5ac19d..164095e81 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/KotatsuApp.kt @@ -22,8 +22,8 @@ import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.WorkServiceStopHelper import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.local.data.PagesCache -import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.reader.domain.PageLoader import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt index e76ee3ed0..f2db6cb49 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt @@ -30,6 +30,8 @@ import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.core.ui.util.ReversibleAction import org.koitharu.kotatsu.core.ui.util.reverseAsync import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding import org.koitharu.kotatsu.details.ui.DetailsActivity @@ -81,8 +83,8 @@ class BookmarksFragment : binding.recyclerView.addItemDecoration(spacingDecoration) viewModel.content.observe(viewLifecycleOwner, ::onListChanged) - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) - viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onActionDone.observeEvent(viewLifecycleOwner, ::onActionDone) } override fun onDestroyView() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt index 614691d49..d08ce07b4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksViewModel.kt @@ -1,18 +1,21 @@ package org.koitharu.kotatsu.bookmarks.ui -import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository import org.koitharu.kotatsu.bookmarks.ui.model.BookmarksGroup import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState @@ -25,9 +28,9 @@ class BookmarksViewModel @Inject constructor( private val repository: BookmarksRepository, ) : BaseViewModel() { - val onActionDone = SingleLiveEvent() + val onActionDone = MutableEventFlow() - val content: LiveData> = repository.observeBookmarks() + val content: StateFlow> = repository.observeBookmarks() .map { list -> if (list.isEmpty()) { listOf( @@ -43,12 +46,12 @@ class BookmarksViewModel @Inject constructor( } } .catch { e -> emit(listOf(e.toErrorState(canRetry = false))) } - .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) fun removeBookmarks(ids: Map>) { launchJob(Dispatchers.Default) { val handle = repository.removeBookmarks(ids) - onActionDone.emitCall(ReversibleAction(R.string.bookmarks_removed, handle)) + onActionDone.call(ReversibleAction(R.string.bookmarks_removed, handle)) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt index cbf361112..39b9b701b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt @@ -42,9 +42,9 @@ import org.koitharu.kotatsu.core.util.ext.connectivityManager import org.koitharu.kotatsu.core.util.ext.isLowRamDevice import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.CbzFetcher -import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.PagesCache +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.reader.ui.thumbnails.MangaPageFetcher diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt index 68949cc36..1edf3b662 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/DialogErrorObserver.kt @@ -22,10 +22,7 @@ class DialogErrorObserver( fragment: Fragment?, ) : this(host, fragment, null, null) - override fun onChanged(value: Throwable?) { - if (value == null) { - return - } + override suspend fun emit(value: Throwable) { val listener = DialogListener(value) val dialogBuilder = MaterialAlertDialogBuilder(activity ?: host.context) .setMessage(value.getDisplayMessage(host.context.resources)) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt index 3af75685e..a64fb9edf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ErrorObserver.kt @@ -7,8 +7,8 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.Observer import androidx.lifecycle.coroutineScope +import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.util.ext.findActivity @@ -19,7 +19,7 @@ abstract class ErrorObserver( protected val fragment: Fragment?, private val resolver: ExceptionResolver?, private val onResolved: Consumer?, -) : Observer { +) : FlowCollector { protected val activity = host.context.findActivity() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt index 9a1ef14d5..e39897cfc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/SnackbarErrorObserver.kt @@ -22,10 +22,7 @@ class SnackbarErrorObserver( fragment: Fragment?, ) : this(host, fragment, null, null) - override fun onChanged(value: Throwable?) { - if (value == null) { - return - } + override suspend fun emit(value: Throwable) { val snackbar = Snackbar.make(host, value.getDisplayMessage(host.context.resources), Snackbar.LENGTH_SHORT) if (activity is BottomNavOwner) { snackbar.anchorView = activity.bottomNav diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt index cbfc5e1f8..ce0b3e7f1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/Manga.kt @@ -24,6 +24,10 @@ fun Collection.countChaptersByBranch(): Int { return acc.values.max() } +fun Manga.findChapter(id: Long): MangaChapter? { + return chapters?.find { it.id == id } +} + fun Manga.getPreferredBranch(history: MangaHistory?): String? { val ch = chapters if (ch.isNullOrEmpty()) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt index 43c904696..4481c4038 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt @@ -27,7 +27,7 @@ import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow import org.koitharu.kotatsu.core.util.ext.processLifecycleScope -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.reader.ui.ReaderActivity diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt index 393f5357f..45c2e5df9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaDataRepository.kt @@ -1,37 +1,24 @@ package org.koitharu.kotatsu.core.parser -import android.graphics.BitmapFactory -import android.net.Uri -import android.util.Size import androidx.room.withTransaction import dagger.Reusable -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map -import kotlinx.coroutines.runInterruptible import okhttp3.OkHttpClient -import okhttp3.Request import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.MangaPrefsEntity import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toMangaTags -import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.MangaHttpClient import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.reader.domain.ReaderColorFilter -import java.io.File -import java.io.InputStream -import java.util.zip.ZipFile import javax.inject.Inject -import kotlin.math.roundToInt @Reusable class MangaDataRepository @Inject constructor( @@ -104,67 +91,10 @@ class MangaDataRepository @Inject constructor( } } - /** - * Automatic determine type of manga by page size - * @return ReaderMode.WEBTOON if page is wide - */ - suspend fun determineMangaIsWebtoon(repository: MangaRepository, pages: List): Boolean { - val pageIndex = (pages.size * 0.3).roundToInt() - val page = requireNotNull(pages.getOrNull(pageIndex)) { "No pages" } - val url = repository.getPageUrl(page) - val uri = Uri.parse(url) - val size = if (uri.scheme == "cbz") { - runInterruptible(Dispatchers.IO) { - val zip = ZipFile(uri.schemeSpecificPart) - val entry = zip.getEntry(uri.fragment) - zip.getInputStream(entry).use { - getBitmapSize(it) - } - } - } else { - val request = Request.Builder() - .url(url) - .get() - .tag(MangaSource::class.java, page.source) - .cacheControl(CommonHeaders.CACHE_CONTROL_NO_STORE) - .build() - okHttpClient.newCall(request).await().use { - runInterruptible(Dispatchers.IO) { - getBitmapSize(it.body?.byteStream()) - } - } - } - return size.width * MIN_WEBTOON_RATIO < size.height - } - private fun newEntity(mangaId: Long) = MangaPrefsEntity( mangaId = mangaId, mode = -1, cfBrightness = 0f, cfContrast = 0f, ) - - companion object { - - private const val MIN_WEBTOON_RATIO = 2 - - suspend fun getImageMimeType(file: File): String? = runInterruptible(Dispatchers.IO) { - val options = BitmapFactory.Options().apply { - inJustDecodeBounds = true - } - BitmapFactory.decodeFile(file.path, options)?.recycle() - options.outMimeType - } - - private fun getBitmapSize(input: InputStream?): Size { - val options = BitmapFactory.Options().apply { - inJustDecodeBounds = true - } - BitmapFactory.decodeStream(input, null, options)?.recycle() - val imageHeight: Int = options.outHeight - val imageWidth: Int = options.outWidth - check(imageHeight > 0 && imageWidth > 0) - return Size(imageWidth, imageHeight) - } - } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt index b90b10b52..36bbbc0c7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaRepository.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.core.parser import androidx.annotation.AnyThread import org.koitharu.kotatsu.core.cache.ContentCache -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index bf6cab962..09c883755 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -25,7 +25,7 @@ import org.koitharu.kotatsu.core.util.ext.toUriOrNull import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.shelf.domain.ShelfSection +import org.koitharu.kotatsu.shelf.domain.model.ShelfSection import java.io.File import java.net.Proxy import java.util.Collections diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt index 606ae9d84..ed6d14f68 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettingsObserver.kt @@ -1,13 +1,11 @@ package org.koitharu.kotatsu.core.prefs -import androidx.lifecycle.liveData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transform -import kotlin.coroutines.CoroutineContext fun AppSettings.observeAsFlow(key: String, valueProducer: AppSettings.() -> T) = flow { var lastValue: T = valueProducer() @@ -23,25 +21,9 @@ fun AppSettings.observeAsFlow(key: String, valueProducer: AppSettings.() -> } } -fun AppSettings.observeAsLiveData( - context: CoroutineContext, - key: String, - valueProducer: AppSettings.() -> T, -) = liveData(context) { - emit(valueProducer()) - observe().collect { - if (it == key) { - val value = valueProducer() - if (value != latestValue) { - emit(value) - } - } - } -} - fun AppSettings.observeAsStateFlow( - key: String, scope: CoroutineScope, + key: String, valueProducer: AppSettings.() -> T, ): StateFlow = observe().transform { if (it == key) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt index 12cda4167..74948fcdb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseViewModel.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.core.ui -import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.CancellationException @@ -8,9 +7,16 @@ import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import org.koitharu.kotatsu.core.ui.util.CountedBooleanLiveData -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.EventFlow +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.util.ext.printStackTraceDebug import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -18,16 +24,17 @@ import kotlin.coroutines.EmptyCoroutineContext abstract class BaseViewModel : ViewModel() { @JvmField - protected val loadingCounter = CountedBooleanLiveData() + protected val loadingCounter = MutableStateFlow(0) @JvmField - protected val errorEvent = SingleLiveEvent() + protected val errorEvent = MutableEventFlow() - val onError: LiveData + val onError: EventFlow get() = errorEvent - val isLoading: LiveData - get() = loadingCounter + val isLoading: StateFlow + get() = loadingCounter.map { it > 0 } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false) protected fun launchJob( context: CoroutineContext = EmptyCoroutineContext, @@ -51,7 +58,11 @@ abstract class BaseViewModel : ViewModel() { private fun createErrorHandler() = CoroutineExceptionHandler { _, throwable -> throwable.printStackTraceDebug() if (throwable !is CancellationException) { - errorEvent.postCall(throwable) + errorEvent.call(throwable) } } + + protected fun MutableStateFlow.increment() = update { it + 1 } + + protected fun MutableStateFlow.decrement() = update { it - 1 } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt deleted file mode 100644 index a737c0af9..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/CountedBooleanLiveData.kt +++ /dev/null @@ -1,31 +0,0 @@ -package org.koitharu.kotatsu.core.ui.util - -import androidx.annotation.AnyThread -import androidx.lifecycle.LiveData -import java.util.concurrent.atomic.AtomicInteger - -class CountedBooleanLiveData : LiveData(false) { - - private val counter = AtomicInteger(0) - - @AnyThread - fun increment() { - if (counter.getAndIncrement() == 0) { - postValue(true) - } - } - - @AnyThread - fun decrement() { - if (counter.decrementAndGet() == 0) { - postValue(false) - } - } - - @AnyThread - fun reset() { - if (counter.getAndSet(0) != 0) { - postValue(false) - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt index 4f6319f66..b66e64cbb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/ReversibleActionObserver.kt @@ -1,18 +1,15 @@ package org.koitharu.kotatsu.core.ui.util import android.view.View -import androidx.lifecycle.Observer import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.flow.FlowCollector import org.koitharu.kotatsu.R class ReversibleActionObserver( private val snackbarHost: View, -) : Observer { +) : FlowCollector { - override fun onChanged(value: ReversibleAction?) { - if (value == null) { - return - } + override suspend fun emit(value: ReversibleAction) { val handle = value.handle val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG val snackbar = Snackbar.make(snackbarHost, value.stringResId, length) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt new file mode 100644 index 000000000..e14d2703c --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt @@ -0,0 +1,36 @@ +package org.koitharu.kotatsu.core.util + +import kotlinx.coroutines.flow.FlowCollector + +class Event( + private val data: T, +) { + private var isConsumed = false + + suspend fun consume(collector: FlowCollector) { + if (isConsumed) { + collector.emit(data) + isConsumed = true + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Event<*> + + if (data != other.data) return false + return isConsumed == other.isConsumed + } + + override fun hashCode(): Int { + var result = data?.hashCode() ?: 0 + result = 31 * result + isConsumed.hashCode() + return result + } + + override fun toString(): String { + return "Event(data=$data, isConsumed=$isConsumed)" + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt deleted file mode 100644 index 7b3693902..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/FlowLiveData.kt +++ /dev/null @@ -1,86 +0,0 @@ -package org.koitharu.kotatsu.core.util - -import androidx.lifecycle.LiveData -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext - -private const val DEFAULT_TIMEOUT = 5_000L - -/** - * Similar to a CoroutineLiveData but optimized for using within infinite flows - */ -class FlowLiveData( - private val flow: Flow, - defaultValue: T, - context: CoroutineContext = EmptyCoroutineContext, - private val timeoutInMs: Long = DEFAULT_TIMEOUT, -) : LiveData(defaultValue) { - - private val scope = CoroutineScope(Dispatchers.Main.immediate + context + SupervisorJob(context[Job])) - private var job: Job? = null - private var cancellationJob: Job? = null - - override fun onActive() { - super.onActive() - cancellationJob?.cancel() - cancellationJob = null - if (job?.isActive == true) { - return - } - job = scope.launch { - flow.collect(Collector()) - } - } - - override fun onInactive() { - super.onInactive() - cancellationJob?.cancel() - cancellationJob = scope.launch(Dispatchers.Main.immediate) { - delay(timeoutInMs) - if (!hasActiveObservers()) { - job?.cancel() - job = null - } - } - } - - private inner class Collector : FlowCollector { - - private var previousValue: Any? = value - private val dispatcher = Dispatchers.Main.immediate - - override suspend fun emit(value: T) { - if (previousValue != value) { - previousValue = value - if (dispatcher.isDispatchNeeded(EmptyCoroutineContext)) { - withContext(dispatcher) { - setValue(value) - } - } else { - setValue(value) - } - } - } - } -} - -fun Flow.asFlowLiveData( - context: CoroutineContext = EmptyCoroutineContext, - defaultValue: T, - timeoutInMs: Long = DEFAULT_TIMEOUT, -): LiveData = FlowLiveData(this, defaultValue, context, timeoutInMs) - -fun StateFlow.asFlowLiveData( - context: CoroutineContext = EmptyCoroutineContext, - timeoutInMs: Long = DEFAULT_TIMEOUT, -): LiveData = FlowLiveData(this, value, context, timeoutInMs) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt deleted file mode 100644 index 504690d6f..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SingleLiveEvent.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.koitharu.kotatsu.core.util - -import androidx.annotation.AnyThread -import androidx.annotation.MainThread -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import androidx.lifecycle.Observer -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.util.concurrent.atomic.AtomicBoolean -import kotlin.coroutines.EmptyCoroutineContext - -class SingleLiveEvent : LiveData() { - - private val pending = AtomicBoolean(false) - - override fun observe(owner: LifecycleOwner, observer: Observer) { - super.observe(owner) { - if (pending.compareAndSet(true, false)) { - observer.onChanged(it) - } - } - } - - override fun setValue(value: T) { - pending.set(true) - super.setValue(value) - } - - @MainThread - fun call(newValue: T) { - setValue(newValue) - } - - @AnyThread - fun postCall(newValue: T) { - postValue(newValue) - } - - suspend fun emitCall(newValue: T) { - val dispatcher = Dispatchers.Main.immediate - if (dispatcher.isDispatchNeeded(EmptyCoroutineContext)) { - withContext(dispatcher) { - setValue(newValue) - } - } else { - setValue(newValue) - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/EventFlow.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/EventFlow.kt new file mode 100644 index 000000000..11fc25beb --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/EventFlow.kt @@ -0,0 +1,18 @@ +package org.koitharu.kotatsu.core.util.ext + +import androidx.annotation.AnyThread +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import org.koitharu.kotatsu.core.util.Event + +@Suppress("FunctionName") +fun MutableEventFlow() = MutableStateFlow?>(null) + +typealias EventFlow = StateFlow?> + +typealias MutableEventFlow = MutableStateFlow?> + +@AnyThread +fun MutableEventFlow.call(data: T) { + value = Event(data) +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt index 3db3bb15e..2aa0c1e62 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Flow.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.transformLatest +import org.koitharu.kotatsu.R fun Flow.onFirst(action: suspend (T) -> Unit): Flow { var isFirstCall = true @@ -52,3 +53,12 @@ fun Flow>.flatten(): Flow = flow { } } } + +fun Flow.zipWithPrevious(): Flow> = flow { + var previous: T? = null + collect { value -> + val result = previous to value + previous = value + emit(result) + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt new file mode 100644 index 000000000..bfd2db25f --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt @@ -0,0 +1,35 @@ +package org.koitharu.kotatsu.core.util.ext + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import org.koitharu.kotatsu.BuildConfig +import org.koitharu.kotatsu.core.util.Event + +fun Flow.observe(owner: LifecycleOwner, collector: FlowCollector) { + if (BuildConfig.DEBUG) { + require((this as? StateFlow)?.value !is Event<*>) + } + val start = if (this is StateFlow) CoroutineStart.UNDISPATCHED else CoroutineStart.DEFAULT + owner.lifecycleScope.launch(start = start) { + owner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + collect(collector) + } + } +} + +fun Flow?>.observeEvent(owner: LifecycleOwner, collector: FlowCollector) { + owner.lifecycleScope.launch { + owner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + collect { + it?.consume(collector) + } + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt deleted file mode 100644 index ed8d96b62..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/LiveData.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.koitharu.kotatsu.core.util.ext - -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.koitharu.kotatsu.core.util.BufferedObserver -import kotlin.coroutines.EmptyCoroutineContext - -fun LiveData.requireValue(): T = checkNotNull(value) { - "LiveData value is null" -} - -fun LiveData.observeWithPrevious(owner: LifecycleOwner, observer: BufferedObserver) { - var previous: T? = null - this.observe(owner) { - observer.onChanged(it, previous) - previous = it - } -} - -suspend fun MutableLiveData.emitValue(newValue: T) { - val dispatcher = Dispatchers.Main.immediate - if (dispatcher.isDispatchNeeded(EmptyCoroutineContext)) { - withContext(dispatcher) { - value = newValue - } - } else { - value = newValue - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt index 3968e4399..350c66772 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DetailsInteractor.kt @@ -6,23 +6,21 @@ import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map -import org.koitharu.kotatsu.core.model.DoubleManga -import org.koitharu.kotatsu.core.model.isLocal import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.details.domain.model.DoubleManga import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.local.data.LocalManga -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.local.data.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import org.koitharu.kotatsu.util.ext.printStackTraceDebug -import java.io.IOException import javax.inject.Inject +@Deprecated("") class DetailsInteractor @Inject constructor( private val historyRepository: HistoryRepository, private val favouritesRepository: FavouritesRepository, @@ -56,18 +54,6 @@ class DetailsInteractor @Inject constructor( } } - suspend fun deleteLocalManga(manga: Manga) { - val victim = if (manga.isLocal) manga else localMangaRepository.findSavedManga(manga)?.manga - checkNotNull(victim) { "Cannot find saved manga for ${manga.title}" } - val original = if (manga.isLocal) localMangaRepository.getRemoteManga(manga) else manga - localMangaRepository.delete(victim) || throw IOException("Unable to delete file") - runCatchingCancellable { - historyRepository.deleteOrSwap(victim, original) - }.onFailure { - it.printStackTraceDebug() - } - } - fun observeIncognitoMode(mangaFlow: Flow): Flow { return mangaFlow .distinctUntilChangedBy { it?.isNsfw } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt similarity index 79% rename from app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt index 5cf8325c1..143d1ae24 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DoubleMangaLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/DoubleMangaLoadUseCase.kt @@ -1,27 +1,26 @@ -package org.koitharu.kotatsu.local.domain +package org.koitharu.kotatsu.details.domain -import dagger.Reusable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.model.isLocal import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.details.domain.model.DoubleManga +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import javax.inject.Inject -@Reusable -class DoubleMangaLoader @Inject constructor( +class DoubleMangaLoadUseCase @Inject constructor( private val mangaDataRepository: MangaDataRepository, private val localMangaRepository: LocalMangaRepository, private val mangaRepositoryFactory: MangaRepository.Factory, ) { - suspend fun load(manga: Manga): DoubleManga = coroutineScope { + suspend operator fun invoke(manga: Manga): DoubleManga = coroutineScope { val remoteDeferred = async(Dispatchers.Default) { loadRemote(manga) } val localDeferred = async(Dispatchers.Default) { loadLocal(manga) } DoubleManga( @@ -30,14 +29,14 @@ class DoubleMangaLoader @Inject constructor( ) } - suspend fun load(mangaId: Long): DoubleManga { + suspend operator fun invoke(mangaId: Long): DoubleManga { val manga = mangaDataRepository.findMangaById(mangaId) ?: throwNFE() - return load(manga) + return invoke(manga) } - suspend fun load(intent: MangaIntent): DoubleManga { + suspend operator fun invoke(intent: MangaIntent): DoubleManga { val manga = mangaDataRepository.resolveIntent(intent) ?: throwNFE() - return load(manga) + return invoke(manga) } private suspend fun loadLocal(manga: Manga): Result? { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/model/DoubleManga.kt similarity index 97% rename from app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/details/domain/model/DoubleManga.kt index 460286fa1..732f59902 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/DoubleManga.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/domain/model/DoubleManga.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.core.model +package org.koitharu.kotatsu.details.domain.model import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt index 189c3e00c..ad889e3ce 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/service/MangaPrefetchService.kt @@ -10,7 +10,7 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaChapters import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.ui.CoroutineIntentService import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index e3b3c1e64..07a6f8902 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -16,6 +16,7 @@ import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.FragmentChaptersBinding import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index f090a47fa..64abbc9f8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -18,10 +18,11 @@ import androidx.core.graphics.Insets import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updatePadding -import androidx.lifecycle.Observer import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.filterNotNull import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga @@ -32,6 +33,8 @@ import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar import org.koitharu.kotatsu.core.util.ViewBadge +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.setNavigationBarTransparentCompat import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ActivityDetailsBinding @@ -90,10 +93,10 @@ class DetailsActivity : ChaptersMenuProvider(viewModel, null) } - viewModel.manga.observe(this, ::onMangaUpdated) + viewModel.manga.filterNotNull().observe(this, ::onMangaUpdated) viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged) - viewModel.onMangaRemoved.observe(this, ::onMangaRemoved) - viewModel.onError.observe( + viewModel.onMangaRemoved.observeEvent(this, ::onMangaRemoved) + viewModel.onError.observeEvent( this, SnackbarErrorObserver( host = viewBinding.containerDetails, @@ -106,11 +109,11 @@ class DetailsActivity : }, ), ) - viewModel.onShowToast.observe(this) { + viewModel.onShowToast.observeEvent(this) { makeSnackbar(getString(it), Snackbar.LENGTH_SHORT).show() } viewModel.historyInfo.observe(this, ::onHistoryChanged) - viewModel.selectedBranchName.observe(this) { + viewModel.selectedBranch.observe(this) { viewBinding.headerChapters?.subtitle = it viewBinding.textViewSubtitle?.textAndVisible = it } @@ -124,7 +127,7 @@ class DetailsActivity : viewBinding.buttonDropdown.isVisible = it.size > 1 } viewModel.chapters.observe(this, PrefetchObserver(this)) - viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(viewBinding.containerDetails)) + viewModel.onDownloadStarted.observeEvent(this, DownloadStartedObserver(viewBinding.containerDetails)) addMenuProvider( DetailsMenuProvider( @@ -165,12 +168,12 @@ class DetailsActivity : } R.id.action_pages_thumbs -> { - val history = viewModel.historyInfo.value?.history + val history = viewModel.historyInfo.value.history PagesThumbnailsSheet.show( fm = supportFragmentManager, manga = viewModel.manga.value ?: return false, chapterId = history?.chapterId - ?: viewModel.chapters.value?.firstOrNull()?.chapter?.id + ?: viewModel.chapters.value.firstOrNull()?.chapter?.id ?: return false, currentPage = history?.page ?: 0, ) @@ -253,14 +256,14 @@ class DetailsActivity : .setCancelable(true) .setNegativeButton(android.R.string.cancel, null) .setTitle(R.string.translations) - .setItems(viewModel.branches.value.orEmpty()) + .setItems(viewModel.branches.value) .create() .also { it.show() } } private fun openReader(isIncognitoMode: Boolean) { val manga = viewModel.manga.value ?: return - val chapterId = viewModel.historyInfo.value?.history?.chapterId + val chapterId = viewModel.historyInfo.value.history?.chapterId if (chapterId != null && manga.chapters?.none { x -> x.id == chapterId } == true) { val snackbar = makeSnackbar(getString(R.string.chapter_is_missing), Snackbar.LENGTH_SHORT) snackbar.show() @@ -301,11 +304,11 @@ class DetailsActivity : private class PrefetchObserver( private val context: Context, - ) : Observer?> { + ) : FlowCollector?> { private var isCalled = false - override fun onChanged(value: List?) { + override suspend fun emit(value: List?) { if (value.isNullOrEmpty()) { return } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 875e7fb7a..dbd6318e3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -18,6 +18,7 @@ import coil.request.ImageRequest import coil.util.CoilUtils import com.google.android.material.chip.Chip import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.filterNotNull import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter @@ -34,6 +35,7 @@ import org.koitharu.kotatsu.core.util.ext.drawableTop import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty import org.koitharu.kotatsu.core.util.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.textAndVisible @@ -42,7 +44,7 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.HistoryInfo import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingItemDecoration import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.image.ui.ImageActivity import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner import org.koitharu.kotatsu.parsers.model.Manga @@ -82,7 +84,7 @@ class DetailsFragment : binding.infoLayout.textViewSource.setOnClickListener(this) binding.textViewDescription.movementMethod = LinkMovementMethod.getInstance() binding.chipsTags.onChipClickListener = this - viewModel.manga.observe(viewLifecycleOwner, ::onMangaUpdated) + viewModel.manga.filterNotNull().observe(viewLifecycleOwner, ::onMangaUpdated) viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged) viewModel.historyInfo.observe(viewLifecycleOwner, ::onHistoryChanged) viewModel.bookmarks.observe(viewLifecycleOwner, ::onBookmarksChanged) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index 927e9b80c..7579b3301 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -7,10 +7,7 @@ import android.text.style.ForegroundColorSpan import androidx.core.net.toUri import androidx.core.text.getSpans import androidx.core.text.parseAsHtml -import androidx.lifecycle.LiveData import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.asFlow -import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -18,9 +15,9 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChangedBy -import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -31,27 +28,28 @@ import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository -import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.model.getPreferredBranch import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.computeSize import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.core.util.ext.toFileOrNull import org.koitharu.kotatsu.details.domain.BranchComparator import org.koitharu.kotatsu.details.domain.DetailsInteractor +import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase +import org.koitharu.kotatsu.details.domain.model.DoubleManga import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.HistoryInfo import org.koitharu.kotatsu.details.ui.model.MangaBranch import org.koitharu.kotatsu.download.ui.worker.DownloadWorker -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.domain.DoubleMangaLoader +import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblingInfo @@ -69,7 +67,8 @@ class DetailsViewModel @Inject constructor( private val downloadScheduler: DownloadWorker.Scheduler, private val interactor: DetailsInteractor, savedStateHandle: SavedStateHandle, - private val mangaLoader: DoubleMangaLoader, + private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase, + private val doubleMangaLoadUseCase: DoubleMangaLoadUseCase, ) : BaseViewModel() { private val intent = MangaIntent(savedStateHandle) @@ -77,47 +76,46 @@ class DetailsViewModel @Inject constructor( private val doubleManga: MutableStateFlow = MutableStateFlow(intent.manga?.let { DoubleManga(it) }) private var loadingJob: Job - val onShowToast = SingleLiveEvent() - val onDownloadStarted = SingleLiveEvent() + val onShowToast = MutableEventFlow() + val onDownloadStarted = MutableEventFlow() - private val mangaData = doubleManga.map { it?.any } + val manga = doubleManga.map { it?.any } .stateIn(viewModelScope, SharingStarted.Eagerly, doubleManga.value?.any) - private val history = historyRepository.observeOne(mangaId) + val history = historyRepository.observeOne(mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) - private val favourite = interactor.observeIsFavourite(mangaId) + val favouriteCategories = interactor.observeIsFavourite(mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) - private val newChapters = interactor.observeNewChapters(mangaId) + val newChaptersCount = interactor.observeNewChapters(mangaId) .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, 0) private val chaptersQuery = MutableStateFlow("") - private val selectedBranch = MutableStateFlow(null) + val selectedBranch = MutableStateFlow(null) - private val chaptersReversed = settings.observeAsFlow(AppSettings.KEY_REVERSE_CHAPTERS) { chaptersReverse } - .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) - - val manga = mangaData.filterNotNull().asLiveData(viewModelScope.coroutineContext) - val favouriteCategories = favourite.asLiveData(viewModelScope.coroutineContext) - val newChaptersCount = newChapters.asLiveData(viewModelScope.coroutineContext) - val isChaptersReversed = chaptersReversed.asLiveData(viewModelScope.coroutineContext) + val isChaptersReversed = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, + key = AppSettings.KEY_REVERSE_CHAPTERS, + valueProducer = { chaptersReverse }, + ) - val historyInfo: LiveData = combine( - mangaData, + val historyInfo: StateFlow = combine( + manga, selectedBranch, history, - interactor.observeIncognitoMode(mangaData), + interactor.observeIncognitoMode(manga), ) { m, b, h, im -> HistoryInfo(m, b, h, im) - }.asFlowLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, - defaultValue = HistoryInfo(null, null, null, false), + }.stateIn( + scope = viewModelScope + Dispatchers.Default, + started = SharingStarted.Eagerly, + initialValue = HistoryInfo(null, null, null, false), ) - val bookmarks = mangaData.flatMapLatest { + val bookmarks = manga.flatMapLatest { if (it != null) bookmarksRepository.observeBookmarks(it) else flowOf(emptyList()) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, emptyList()) val localSize = doubleManga .map { @@ -128,9 +126,9 @@ class DetailsViewModel @Inject constructor( } else { 0L } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, 0) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(), 0) - val description = mangaData + val description = manga .distinctUntilChangedBy { it?.description.orEmpty() } .transformLatest { val description = it?.description @@ -140,16 +138,16 @@ class DetailsViewModel @Inject constructor( emit(description.parseAsHtml().filterSpans()) emit(description.parseAsHtml(imageGetter = imageGetter).filterSpans()) } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, null) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), null) - val onMangaRemoved = SingleLiveEvent() + val onMangaRemoved = MutableEventFlow() val isScrobblingAvailable: Boolean get() = scrobblers.any { it.isAvailable } - val scrobblingInfo: LiveData> = interactor.observeScrobblingInfo(mangaId) - .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + val scrobblingInfo: StateFlow> = interactor.observeScrobblingInfo(mangaId) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) - val branches: LiveData> = combine( + val branches: StateFlow> = combine( doubleManga, selectedBranch, ) { m, b -> @@ -158,32 +156,29 @@ class DetailsViewModel @Inject constructor( chapters.groupBy { x -> x.branch } .map { x -> MangaBranch(x.key, x.value.size, x.key == b) } .sortedWith(BranchComparator()) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) - - val selectedBranchName = selectedBranch - .asFlowLiveData(viewModelScope.coroutineContext, null) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) - val isChaptersEmpty: LiveData = combine( + val isChaptersEmpty: StateFlow = combine( doubleManga, - isLoading.asFlow(), + isLoading, ) { manga, loading -> manga?.any != null && manga.chapters.isNullOrEmpty() && !loading - }.asFlowLiveData(viewModelScope.coroutineContext, false) + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false) val chapters = combine( combine( doubleManga, history, selectedBranch, - newChapters, + newChaptersCount, ) { manga, history, branch, news -> mapChapters(manga?.remote, manga?.local, history, news, branch) }, - chaptersReversed, + isChaptersReversed, chaptersQuery, ) { list, reversed, query -> (if (reversed) list.asReversed() else list).filterSearch(query) - }.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default) + }.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList()) val selectedBranchValue: String? get() = selectedBranch.value @@ -208,8 +203,8 @@ class DetailsViewModel @Inject constructor( return } launchLoadingJob(Dispatchers.Default) { - interactor.deleteLocalManga(m) - onMangaRemoved.emitCall(m) + deleteLocalMangaUseCase(m) + onMangaRemoved.call(m) } } @@ -276,12 +271,12 @@ class DetailsViewModel @Inject constructor( doubleManga.requireValue().requireAny(), chaptersIds, ) - onDownloadStarted.emitCall(Unit) + onDownloadStarted.call(Unit) } } private fun doLoad() = launchLoadingJob(Dispatchers.Default) { - val result = mangaLoader.load(intent) + val result = doubleMangaLoadUseCase(intent) val manga = result.requireAny() // find default branch val hist = historyRepository.getOne(manga) @@ -317,7 +312,7 @@ class DetailsViewModel @Inject constructor( } private fun getScrobbler(index: Int): Scrobbler? { - val info = scrobblingInfo.value?.getOrNull(index) + val info = scrobblingInfo.value.getOrNull(index) val scrobbler = if (info != null) { scrobblers.find { it.scrobblerService == info.scrobbler && it.isAvailable } } else { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt index 96950f5ad..045fb420d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt @@ -21,6 +21,8 @@ import org.koitharu.kotatsu.core.ui.BaseBottomSheet import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetScrobblingBinding @@ -59,7 +61,7 @@ class ScrobblingInfoBottomSheet : override fun onViewBindingCreated(binding: SheetScrobblingBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) viewModel.scrobblingInfo.observe(viewLifecycleOwner, ::onScrobblingInfoChanged) - viewModel.onError.observe(viewLifecycleOwner) { + viewModel.onError.observeEvent(viewLifecycleOwner) { Toast.makeText(binding.root.context, it.getDisplayMessage(binding.root.resources), Toast.LENGTH_SHORT) .show() } @@ -105,7 +107,7 @@ class ScrobblingInfoBottomSheet : when (v.id) { R.id.button_menu -> menu?.show() R.id.imageView_cover -> { - val coverUrl = viewModel.scrobblingInfo.value?.getOrNull(scrobblerIndex)?.coverUrl ?: return + val coverUrl = viewModel.scrobblingInfo.value.getOrNull(scrobblerIndex)?.coverUrl ?: return val options = scaleUpActivityOptionsOf(v) startActivity(ImageActivity.newIntent(v.context, coverUrl, null), options.toBundle()) } @@ -135,7 +137,7 @@ class ScrobblingInfoBottomSheet : override fun onMenuItemClick(item: MenuItem): Boolean { when (item.itemId) { R.id.action_browser -> { - val url = viewModel.scrobblingInfo.value?.getOrNull(scrobblerIndex)?.externalUrl ?: return false + val url = viewModel.scrobblingInfo.value.getOrNull(scrobblerIndex)?.externalUrl ?: return false val intent = Intent(Intent.ACTION_VIEW, url.toUri()) startActivity( Intent.createChooser(intent, getString(R.string.open_in_browser)), @@ -149,7 +151,7 @@ class ScrobblingInfoBottomSheet : R.id.action_edit -> { val manga = viewModel.manga.value ?: return false - val scrobblerService = viewModel.scrobblingInfo.value?.getOrNull(scrobblerIndex)?.scrobbler + val scrobblerService = viewModel.scrobblingInfo.value.getOrNull(scrobblerIndex)?.scrobbler ScrobblingSelectorBottomSheet.show(parentFragmentManager, manga, scrobblerService) dismiss() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt index fea793f6d..8adf4a953 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/domain/DownloadState.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.download.domain import androidx.work.Data -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import java.util.Date diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt index 6fb8ecb9d..5a6128b75 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt @@ -11,14 +11,16 @@ import androidx.annotation.Px import androidx.appcompat.view.ActionMode import androidx.core.graphics.Insets import androidx.core.view.updatePadding -import androidx.lifecycle.Observer import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.FlowCollector import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.PausingReceiver @@ -61,8 +63,8 @@ class DownloadsActivity : BaseActivity(), viewModel.items.observe(this) { downloadsAdapter.items = it } - viewModel.onActionDone.observe(this, ReversibleActionObserver(viewBinding.recyclerView)) - val menuObserver = Observer { _ -> invalidateOptionsMenu() } + viewModel.onActionDone.observeEvent(this, ReversibleActionObserver(viewBinding.recyclerView)) + val menuObserver = FlowCollector { _ -> invalidateOptionsMenu() } viewModel.hasActiveWorks.observe(this, menuObserver) viewModel.hasPausedWorks.observe(this, menuObserver) viewModel.hasCancellableWorks.observe(this, menuObserver) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt index fb6e455ff..24b3dc68f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsViewModel.kt @@ -20,8 +20,8 @@ import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.download.domain.DownloadState import org.koitharu.kotatsu.download.ui.worker.DownloadWorker @@ -47,23 +47,23 @@ class DownloadsViewModel @Inject constructor( .mapLatest { it.toDownloadsList() } .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) - val onActionDone = SingleLiveEvent() + val onActionDone = MutableEventFlow() val items = works.map { it?.toUiList() ?: listOf(LoadingState) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) val hasPausedWorks = works.map { it?.any { x -> x.canResume } == true - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), false) val hasActiveWorks = works.map { it?.any { x -> x.canPause } == true - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), false) val hasCancellableWorks = works.map { it?.any { x -> !x.workState.isFinished } == true - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), false) fun cancel(id: UUID) { launchJob(Dispatchers.Default) { @@ -79,14 +79,14 @@ class DownloadsViewModel @Inject constructor( workScheduler.cancel(work.id) } } - onActionDone.emitCall(ReversibleAction(R.string.downloads_cancelled, null)) + onActionDone.call(ReversibleAction(R.string.downloads_cancelled, null)) } } fun cancelAll() { launchJob(Dispatchers.Default) { workScheduler.cancelAll() - onActionDone.emitCall(ReversibleAction(R.string.downloads_cancelled, null)) + onActionDone.call(ReversibleAction(R.string.downloads_cancelled, null)) } } @@ -146,14 +146,14 @@ class DownloadsViewModel @Inject constructor( workScheduler.delete(work.id) } } - onActionDone.emitCall(ReversibleAction(R.string.downloads_removed, null)) + onActionDone.call(ReversibleAction(R.string.downloads_removed, null)) } } fun removeCompleted() { launchJob(Dispatchers.Default) { workScheduler.removeCompleted() - onActionDone.emitCall(ReversibleAction(R.string.downloads_removed, null)) + onActionDone.call(ReversibleAction(R.string.downloads_removed, null)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt index 10dbb2292..6c42b9275 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadStartedObserver.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.download.ui.worker import android.view.View -import androidx.lifecycle.Observer import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.flow.FlowCollector import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.util.ext.findActivity import org.koitharu.kotatsu.download.ui.list.DownloadsActivity @@ -10,9 +10,9 @@ import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner class DownloadStartedObserver( private val snackbarHost: View, -) : Observer { +) : FlowCollector { - override fun onChanged(value: Unit) { + override suspend fun emit(value: Unit) { val snackbar = Snackbar.make(snackbarHost, R.string.download_started, Snackbar.LENGTH_LONG) (snackbarHost.context.findActivity() as? BottomNavOwner)?.let { snackbar.anchorView = it.bottomNav diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt index 47cf46cf0..0d620188d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/worker/DownloadWorker.kt @@ -48,12 +48,12 @@ import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.core.util.progress.TimeLeftEstimator import org.koitharu.kotatsu.download.domain.DownloadState -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.local.data.input.LocalMangaInput import org.koitharu.kotatsu.local.data.output.LocalMangaOutput -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt index e3ea1c156..de68c4097 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/domain/ExploreRepository.kt @@ -4,7 +4,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.almostEquals import org.koitharu.kotatsu.core.util.ext.asArrayList -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.runCatchingCancellable diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt index d0159e851..69b6c9d5c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt @@ -25,6 +25,8 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.SpanSizeResolver import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentExploreBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter @@ -74,9 +76,9 @@ class ExploreFragment : viewModel.content.observe(viewLifecycleOwner) { exploreAdapter?.items = it } - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) - viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga) - viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onOpenManga.observeEvent(viewLifecycleOwner, ::onOpenManga) + viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) viewModel.isGrid.observe(viewLifecycleOwner, ::onGridModeChanged) viewModel.onShowSuggestionsTip.observe(viewLifecycleOwner) { showSuggestionsTip() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt index 6ee8eb2b8..0f163d92f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreViewModel.kt @@ -1,16 +1,17 @@ package org.koitharu.kotatsu.explore.ui -import androidx.lifecycle.LiveData -import androidx.lifecycle.asFlow import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings @@ -18,8 +19,8 @@ import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction import org.koitharu.kotatsu.core.ui.util.ReversibleHandle -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.explore.domain.ExploreRepository import org.koitharu.kotatsu.explore.ui.model.ExploreItem import org.koitharu.kotatsu.parsers.model.Manga @@ -34,29 +35,28 @@ class ExploreViewModel @Inject constructor( private val exploreRepository: ExploreRepository, ) : BaseViewModel() { - private val gridMode = settings.observeAsStateFlow( + val isGrid = settings.observeAsStateFlow( key = AppSettings.KEY_SOURCES_GRID, scope = viewModelScope + Dispatchers.IO, valueProducer = { isSourcesGridMode }, ) - val onOpenManga = SingleLiveEvent() - val onActionDone = SingleLiveEvent() - val onShowSuggestionsTip = SingleLiveEvent() - val isGrid = gridMode.asFlowLiveData(viewModelScope.coroutineContext) + val onOpenManga = MutableEventFlow() + val onActionDone = MutableEventFlow() + val onShowSuggestionsTip = MutableEventFlow() - val content: LiveData> = isLoading.asFlow().flatMapLatest { loading -> + val content: StateFlow> = isLoading.flatMapLatest { loading -> if (loading) { flowOf(listOf(ExploreItem.Loading)) } else { createContentFlow() } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(ExploreItem.Loading)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(ExploreItem.Loading)) init { launchJob(Dispatchers.Default) { if (!settings.isSuggestionsEnabled && settings.isTipEnabled(TIP_SUGGESTIONS)) { - onShowSuggestionsTip.emitCall(Unit) + onShowSuggestionsTip.call(Unit) } } } @@ -64,7 +64,7 @@ class ExploreViewModel @Inject constructor( fun openRandom() { launchLoadingJob(Dispatchers.Default) { val manga = exploreRepository.findRandomManga(tagsLimit = 8) - onOpenManga.emitCall(manga) + onOpenManga.call(manga) } } @@ -74,7 +74,7 @@ class ExploreViewModel @Inject constructor( val rollback = ReversibleHandle { settings.hiddenSources -= source.name } - onActionDone.emitCall(ReversibleAction(R.string.source_disabled, rollback)) + onActionDone.call(ReversibleAction(R.string.source_disabled, rollback)) } } @@ -95,7 +95,7 @@ class ExploreViewModel @Inject constructor( } .onStart { emit("") } .map { settings.getMangaSources(includeHidden = false) } - .combine(gridMode) { content, grid -> buildList(content, grid) } + .combine(isGrid) { content, grid -> buildList(content, grid) } private fun buildList(sources: List, isGrid: Boolean): List { val result = ArrayList(sources.size + 3) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt index 66901002d..2675851ae 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt @@ -24,6 +24,8 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.list.ListSelectionController +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding import org.koitharu.kotatsu.favourites.ui.FavouritesActivity @@ -71,7 +73,7 @@ class FavouriteCategoriesActivity : onBackPressedDispatcher.addCallback(exitReorderModeCallback) viewModel.detalizedCategories.observe(this, ::onCategoriesChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) + viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.isInReorderMode.observe(this, ::onReorderModeChanged) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt index e2057a28c..f7a397df0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt @@ -1,17 +1,17 @@ package org.koitharu.kotatsu.favourites.ui.categories -import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel @@ -27,23 +27,11 @@ class FavouritesCategoriesViewModel @Inject constructor( ) : BaseViewModel() { private var reorderJob: Job? = null - private val isReorder = MutableStateFlow(false) - - val isInReorderMode = isReorder.asLiveData(viewModelScope.coroutineContext) - - val allCategories = repository.observeCategories() - .mapItems { - CategoryListModel( - mangaCount = 0, - covers = listOf(), - category = it, - isReorderMode = false, - ) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + val isInReorderMode = MutableStateFlow(false) val detalizedCategories = combine( repository.observeCategoriesWithCovers(), - isReorder, + isInReorderMode, ) { list, reordering -> list.map { (category, covers) -> CategoryListModel( @@ -62,7 +50,7 @@ class FavouritesCategoriesViewModel @Inject constructor( ), ) } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) fun deleteCategory(id: Long) { launchJob { @@ -80,12 +68,12 @@ class FavouritesCategoriesViewModel @Inject constructor( settings.isAllFavouritesVisible = isVisible } - fun isInReorderMode(): Boolean = isReorder.value + fun isInReorderMode(): Boolean = isInReorderMode.value - fun isEmpty(): Boolean = detalizedCategories.value?.none { it is CategoryListModel } ?: true + fun isEmpty(): Boolean = detalizedCategories.value.none { it is CategoryListModel } fun setReorderMode(isReorderMode: Boolean) { - isReorder.value = isReorderMode + isInReorderMode.value = isReorderMode } fun reorderCategories(oldPos: Int, newPos: Int) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt index d7980dfcb..3b055ddff 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt @@ -22,6 +22,8 @@ import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getSerializableCompat +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity @@ -50,10 +52,10 @@ class FavouritesCategoryEditActivity : viewBinding.editName.addTextChangedListener(this) afterTextChanged(viewBinding.editName.text) - viewModel.onSaved.observe(this) { finishAfterTransition() } + viewModel.onSaved.observeEvent(this) { finishAfterTransition() } viewModel.category.observe(this, ::onCategoryChanged) viewModel.isLoading.observe(this, ::onLoadingStateChanged) - viewModel.onError.observe(this, ::onError) + viewModel.onError.observeEvent(this, ::onError) viewModel.isTrackerEnabled.observe(this) { viewBinding.switchTracker.isVisible = it } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt index 2677f1cd0..2b32a3d5c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt @@ -1,16 +1,19 @@ package org.koitharu.kotatsu.favourites.ui.categories.edit -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.EXTRA_ID import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.NO_ID @@ -26,22 +29,20 @@ class FavouritesCategoryEditViewModel @Inject constructor( private val categoryId = savedStateHandle[EXTRA_ID] ?: NO_ID - val onSaved = SingleLiveEvent() - val category = MutableLiveData() + val onSaved = MutableEventFlow() + val category = MutableStateFlow(null) - val isTrackerEnabled = liveData(viewModelScope.coroutineContext + Dispatchers.Default) { + val isTrackerEnabled = flow { emit(settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources) - } + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) init { launchLoadingJob(Dispatchers.Default) { - category.emitValue( - if (categoryId != NO_ID) { - repository.getCategory(categoryId) - } else { - null - }, - ) + category.value = if (categoryId != NO_ID) { + repository.getCategory(categoryId) + } else { + null + } } } @@ -58,7 +59,7 @@ class FavouritesCategoryEditViewModel @Inject constructor( } else { repository.updateCategory(categoryId, title, sortOrder, isTrackerEnabled, isVisibleOnShelf) } - onSaved.emitCall(Unit) + onSaved.call(Unit) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt index 2c9b5f4d5..983246319 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesBottomSheet.kt @@ -15,6 +15,8 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.ui.BaseBottomSheet import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetFavoriteCategoriesBinding import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity @@ -46,7 +48,7 @@ class FavouriteCategoriesBottomSheet : binding.headerBar.toolbar.setOnMenuItemClickListener(this) viewModel.content.observe(viewLifecycleOwner, this::onContentChanged) - viewModel.onError.observe(viewLifecycleOwner, ::onError) + viewModel.onError.observeEvent(viewLifecycleOwner, ::onError) } override fun onDestroyView() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt index 32a7f0f11..69180f1aa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt @@ -4,11 +4,13 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.model.ids import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet.Companion.KEY_MANGA_LIST import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem @@ -33,7 +35,7 @@ class MangaCategoriesViewModel @Inject constructor( isChecked = it.id in checked, ) } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) fun setChecked(categoryId: Long, isChecked: Boolean) { launchJob(Dispatchers.Default) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index 77c128fe5..9e22b6a62 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -12,6 +12,7 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index b8e310dcb..3c7ceb019 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -1,25 +1,28 @@ package org.koitharu.kotatsu.favourites.ui.list -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -43,12 +46,12 @@ class FavouritesListViewModel @Inject constructor( val categoryId: Long = savedStateHandle[ARG_CATEGORY_ID] ?: NO_ID - val sortOrder: LiveData = if (categoryId == NO_ID) { - MutableLiveData(null) + val sortOrder: StateFlow = if (categoryId == NO_ID) { + MutableStateFlow(null) } else { repository.observeCategory(categoryId) .map { it?.order } - .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, null) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) } override val content = combine( @@ -57,7 +60,7 @@ class FavouritesListViewModel @Inject constructor( } else { repository.observeAll(categoryId) }, - listModeFlow, + listMode, ) { list, mode -> when { list.isEmpty() -> listOf( @@ -77,7 +80,7 @@ class FavouritesListViewModel @Inject constructor( } }.catch { emit(listOf(it.toErrorState(canRetry = false))) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) override fun onRefresh() = Unit @@ -93,7 +96,7 @@ class FavouritesListViewModel @Inject constructor( } else { repository.removeFromCategory(categoryId, ids) } - onActionDone.emitCall(ReversibleAction(R.string.removed_from_favourites, handle)) + onActionDone.call(ReversibleAction(R.string.removed_from_favourites, handle)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt similarity index 96% rename from app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt index 3cc4a81b0..f8977fabf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.history.domain +package org.koitharu.kotatsu.history.data import androidx.room.withTransaction import dagger.Reusable @@ -17,8 +17,7 @@ import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.ReversibleHandle import org.koitharu.kotatsu.core.util.ext.mapItems -import org.koitharu.kotatsu.history.data.HistoryEntity -import org.koitharu.kotatsu.history.data.toMangaHistory +import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryUpdateUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryUpdateUseCase.kt new file mode 100644 index 000000000..a28d27fb8 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/HistoryUpdateUseCase.kt @@ -0,0 +1,38 @@ +package org.koitharu.kotatsu.history.domain + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.reader.ui.ReaderState +import org.koitharu.kotatsu.util.ext.printStackTraceDebug +import javax.inject.Inject + +class HistoryUpdateUseCase @Inject constructor( + private val historyRepository: HistoryRepository, +) { + + suspend operator fun invoke(manga: Manga, readerState: ReaderState, percent: Float) { + historyRepository.addOrUpdate( + manga = manga, + chapterId = readerState.chapterId, + page = readerState.page, + scroll = readerState.scroll, + percent = percent, + ) + } + + fun invokeAsync( + manga: Manga, + readerState: ReaderState, + percent: Float + ) = processLifecycleScope.launch(Dispatchers.Default) { + runCatchingCancellable { + invoke(manga, readerState, percent) + }.onFailure { + it.printStackTraceDebug() + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/MangaWithHistory.kt similarity index 77% rename from app/src/main/kotlin/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/MangaWithHistory.kt index 611dd1ded..5a7e26897 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/MangaWithHistory.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/MangaWithHistory.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.history.domain +package org.koitharu.kotatsu.history.domain.model import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.parsers.model.Manga @@ -6,4 +6,4 @@ import org.koitharu.kotatsu.parsers.model.Manga data class MangaWithHistory( val manga: Manga, val history: MangaHistory -) \ No newline at end of file +) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt index de17fc3ed..47157c4a7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index da09bea62..c46f349db 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -1,28 +1,28 @@ package org.koitharu.kotatsu.history.ui -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode -import org.koitharu.kotatsu.core.prefs.observeAsFlow +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.daysDiff -import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.MangaWithHistory -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -45,15 +45,16 @@ class HistoryListViewModel @Inject constructor( downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { - val isGroupingEnabled = MutableLiveData() - - private val historyGrouping = settings.observeAsFlow(AppSettings.KEY_HISTORY_GROUPING) { isHistoryGroupingEnabled } - .onEach { isGroupingEnabled.emitValue(it) } + val isGroupingEnabled = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, + key = AppSettings.KEY_HISTORY_GROUPING, + valueProducer = { isHistoryGroupingEnabled }, + ) override val content = combine( repository.observeAllWithHistory(), - historyGrouping, - listModeFlow, + isGroupingEnabled, + listMode, ) { list, grouped, mode -> when { list.isEmpty() -> listOf( @@ -73,7 +74,7 @@ class HistoryListViewModel @Inject constructor( loadingCounter.decrement() }.catch { emit(listOf(it.toErrorState(canRetry = false))) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) override fun onRefresh() = Unit @@ -91,7 +92,7 @@ class HistoryListViewModel @Inject constructor( } launchJob(Dispatchers.Default) { val handle = repository.delete(ids) - onActionDone.emitCall(ReversibleAction(R.string.removed_from_history, handle)) + onActionDone.call(ReversibleAction(R.string.removed_from_history, handle)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt index dc2bd9d8e..618b8d788 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressDrawable.kt @@ -13,7 +13,7 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.core.graphics.ColorUtils import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.util.ext.scale -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE class ReadingProgressDrawable( context: Context, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt index 49c05a7c5..744201215 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/util/ReadingProgressView.kt @@ -12,7 +12,7 @@ import androidx.annotation.AttrRes import androidx.annotation.StyleRes import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.util.ext.getAnimationDuration -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE class ReadingProgressView @JvmOverloads constructor( context: Context, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index c503087e3..146767467 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -37,6 +37,8 @@ import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.clearItemDecorations import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.measureHeight +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.resolveDp import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope @@ -123,9 +125,9 @@ abstract class MangaListFragment : viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged) viewModel.content.observe(viewLifecycleOwner, ::onListChanged) - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) - viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) - viewModel.onDownloadStarted.observe(viewLifecycleOwner, DownloadStartedObserver(binding.recyclerView)) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) + viewModel.onDownloadStarted.observeEvent(viewLifecycleOwner, DownloadStartedObserver(binding.recyclerView)) } override fun onDestroyView() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt index b123776dc..8c197fae9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListViewModel.kt @@ -1,39 +1,38 @@ package org.koitharu.kotatsu.list.ui -import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag abstract class MangaListViewModel( - private val settings: AppSettings, + settings: AppSettings, private val downloadScheduler: DownloadWorker.Scheduler, ) : BaseViewModel() { - abstract val content: LiveData> - protected val listModeFlow = settings.observeAsFlow(AppSettings.KEY_LIST_MODE) { listMode } - .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, settings.listMode) - val listMode = listModeFlow.asFlowLiveData(viewModelScope.coroutineContext) - val onActionDone = SingleLiveEvent() - val gridScale = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + abstract val content: StateFlow> + val listMode = settings.observeAsFlow(AppSettings.KEY_LIST_MODE) { listMode } + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, settings.listMode) + val onActionDone = MutableEventFlow() + val gridScale = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_GRID_SIZE, valueProducer = { gridSize / 100f }, ) - val onDownloadStarted = SingleLiveEvent() + val onDownloadStarted = MutableEventFlow() open fun onUpdateFilter(tags: Set) = Unit @@ -44,7 +43,7 @@ abstract class MangaListViewModel( fun download(items: Set) { launchJob(Dispatchers.Default) { downloadScheduler.schedule(items) - onDownloadStarted.emitCall(Unit) + onDownloadStarted.call(Unit) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt index 900738327..e47650a25 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt @@ -12,7 +12,7 @@ import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.databinding.ItemMangaGridBinding -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaGridModel diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt index 645ecefa4..95396fca3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt @@ -16,7 +16,7 @@ import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.source import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel import org.koitharu.kotatsu.parsers.model.MangaTag diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt index f1dc651f7..a00341a55 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterBottomSheet.kt @@ -11,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseBottomSheet import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.parentFragmentViewModels import org.koitharu.kotatsu.databinding.SheetFilterBinding import org.koitharu.kotatsu.remotelist.ui.RemoteListViewModel diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt index b8c04d96d..0ff57d7a3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/filter/FilterCoordinator.kt @@ -1,22 +1,25 @@ package org.koitharu.kotatsu.list.ui.filter import androidx.annotation.WorkerThread -import androidx.lifecycle.LiveData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.util.SuspendLazy import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.text.Collator @@ -31,13 +34,13 @@ class FilterCoordinator( private val currentState = MutableStateFlow(FilterState(repository.defaultSortOrder, emptySet())) private var searchQuery = MutableStateFlow("") - private val localTagsDeferred = coroutineScope.async(Dispatchers.Default, CoroutineStart.LAZY) { + private val localTags = SuspendLazy { dataRepository.findTags(repository.source) } private var availableTagsDeferred = loadTagsAsync() - val items: LiveData> = getItemsFlow() - .asFlowLiveData(coroutineScope.coroutineContext + Dispatchers.Default, listOf(FilterItem.Loading)) + val items: StateFlow> = getItemsFlow() + .stateIn(coroutineScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(FilterItem.Loading)) init { observeState() @@ -97,7 +100,7 @@ class FilterCoordinator( } private fun getTagsAsFlow() = flow { - val localTags = localTagsDeferred.await() + val localTags = localTags.get() emit(TagsWrapper(localTags, isLoading = true, isError = false)) val remoteTags = tryLoadTags() if (remoteTags == null) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt index 89cd7eee1..ea24b01fa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt @@ -7,7 +7,7 @@ import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.util.ext.ifZero -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.model.Manga diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalMangaRepository.kt similarity index 95% rename from app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalMangaRepository.kt index 6d3964978..7ac0dc282 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalMangaRepository.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.local.domain +package org.koitharu.kotatsu.local.data import android.net.Uri import androidx.core.net.toFile @@ -15,13 +15,10 @@ import org.koitharu.kotatsu.core.model.isLocal import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.util.CompositeMutex import org.koitharu.kotatsu.core.util.ext.deleteAwait -import org.koitharu.kotatsu.local.data.LocalManga -import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.data.LocalStorageManager -import org.koitharu.kotatsu.local.data.TempFileFilter import org.koitharu.kotatsu.local.data.input.LocalMangaInput import org.koitharu.kotatsu.local.data.output.LocalMangaOutput import org.koitharu.kotatsu.local.data.output.LocalMangaUtil +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt index e5c9bf9e1..9221a4f08 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/importer/SingleMangaImporter.kt @@ -16,10 +16,10 @@ import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.util.ext.resolveName import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.local.data.CbzFilter -import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.local.data.input.LocalMangaInput +import org.koitharu.kotatsu.local.domain.model.LocalManga import java.io.File import java.io.IOException import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt index e383da294..e62943d07 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt @@ -9,9 +9,9 @@ import org.koitharu.kotatsu.core.util.ext.longHashCode import org.koitharu.kotatsu.core.util.ext.toListSorted import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.ImageFileFilter -import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.local.data.output.LocalMangaOutput +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt index 0da957b8b..f203912e5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaInput.kt @@ -2,7 +2,7 @@ package org.koitharu.kotatsu.local.data.input import android.net.Uri import androidx.core.net.toFile -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt index e768e5b9b..f468c4647 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaZipInput.kt @@ -10,9 +10,9 @@ import kotlinx.coroutines.runInterruptible import org.koitharu.kotatsu.core.util.ext.longHashCode import org.koitharu.kotatsu.core.util.ext.readText import org.koitharu.kotatsu.core.util.ext.toListSorted -import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.local.data.output.LocalMangaOutput +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DeleteLocalMangaUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DeleteLocalMangaUseCase.kt new file mode 100644 index 000000000..ef613604f --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/DeleteLocalMangaUseCase.kt @@ -0,0 +1,42 @@ +package org.koitharu.kotatsu.local.domain + +import org.koitharu.kotatsu.core.model.isLocal +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.local.data.LocalMangaRepository +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.util.ext.printStackTraceDebug +import java.io.IOException +import javax.inject.Inject + +class DeleteLocalMangaUseCase @Inject constructor( + private val localMangaRepository: LocalMangaRepository, + private val historyRepository: HistoryRepository, +) { + + suspend operator fun invoke(manga: Manga) { + val victim = if (manga.isLocal) manga else localMangaRepository.findSavedManga(manga)?.manga + checkNotNull(victim) { "Cannot find saved manga for ${manga.title}" } + val original = if (manga.isLocal) localMangaRepository.getRemoteManga(manga) else manga + localMangaRepository.delete(victim) || throw IOException("Unable to delete file") + runCatchingCancellable { + historyRepository.deleteOrSwap(victim, original) + }.onFailure { + it.printStackTraceDebug() + } + } + + suspend operator fun invoke(ids: Set) { + val list = localMangaRepository.getList(0, null, null) + var removed = 0 + for (manga in list) { + if (manga.id in ids) { + invoke(manga) + removed++ + } + } + check(removed == ids.size) { + "Removed $removed files but ${ids.size} requested" + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalManga.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/model/LocalManga.kt similarity index 92% rename from app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalManga.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/local/domain/model/LocalManga.kt index bebb4c12c..247d395d4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/LocalManga.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/domain/model/LocalManga.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.local.data +package org.koitharu.kotatsu.local.domain.model import androidx.core.net.toFile import androidx.core.net.toUri @@ -38,9 +38,7 @@ class LocalManga( other as LocalManga if (manga != other.manga) return false - if (file != other.file) return false - - return true + return file == other.file } override fun hashCode(): Int { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt index d63ea1100..754c8ffbb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalChaptersRemoveService.kt @@ -15,9 +15,9 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.ui.CoroutineIntentService import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt index d451b3936..3f8fd2bb2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt @@ -15,6 +15,7 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.SortOrder @@ -26,7 +27,7 @@ class LocalListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) addMenuProvider(LocalListMenuProvider(this::onEmptyActionClick)) - viewModel.onMangaRemoved.observe(viewLifecycleOwner) { onItemRemoved() } + viewModel.onMangaRemoved.observeEvent(viewLifecycleOwner) { onItemRemoved() } } override fun onEmptyActionClick() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt index 0439423eb..80836cdd7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt @@ -1,7 +1,5 @@ package org.koitharu.kotatsu.local.ui -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asFlow import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException @@ -10,18 +8,20 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.update +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.widgets.ChipsView -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -29,15 +29,14 @@ import org.koitharu.kotatsu.list.ui.model.ListHeader2 import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import java.io.IOException import java.util.LinkedList import javax.inject.Inject @@ -49,11 +48,12 @@ class LocalListViewModel @Inject constructor( private val settings: AppSettings, private val tagHighlighter: MangaTagHighlighter, @LocalStorageChanges private val localStorageChanges: SharedFlow, + private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase, downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler), ListExtraProvider { - val onMangaRemoved = SingleLiveEvent() - val sortOrder = MutableLiveData(settings.localListOrder) + val onMangaRemoved = MutableEventFlow() + val sortOrder = MutableStateFlow(settings.localListOrder) private val listError = MutableStateFlow(null) private val mangaList = MutableStateFlow?>(null) private val selectedTags = MutableStateFlow>(emptySet()) @@ -61,8 +61,8 @@ class LocalListViewModel @Inject constructor( override val content = combine( mangaList, - listModeFlow, - sortOrder.asFlow(), + listMode, + sortOrder, selectedTags, listError, ) { list, mode, order, tags, error -> @@ -83,7 +83,7 @@ class LocalListViewModel @Inject constructor( list.toUi(this, mode, this@LocalListViewModel, tagHighlighter) } } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) init { onRefresh() @@ -120,18 +120,8 @@ class LocalListViewModel @Inject constructor( fun delete(ids: Set) { launchLoadingJob(Dispatchers.Default) { - val itemsToRemove = checkNotNull(mangaList.value).filter { it.id in ids } - for (manga in itemsToRemove) { - val original = repository.getRemoteManga(manga) - repository.delete(manga) || throw IOException("Unable to delete file") - runCatchingCancellable { - historyRepository.deleteOrSwap(manga, original) - } - mangaList.update { list -> - list?.filterNot { it.id == manga.id } - } - } - onMangaRemoved.emitCall(Unit) + deleteLocalMangaUseCase(ids) + onMangaRemoved.call(Unit) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt index fc2620b27..995ac48a7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalStorageCleanupWorker.kt @@ -11,7 +11,7 @@ import androidx.work.WorkManager import androidx.work.WorkerParameters import dagger.assisted.Assisted import dagger.assisted.AssistedInject -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.data.LocalMangaRepository import java.util.concurrent.TimeUnit @HiltWorker diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt index 9f34e0c61..024cb6994 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -45,6 +45,8 @@ import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView import org.koitharu.kotatsu.core.util.ext.drawableEnd import org.koitharu.kotatsu.core.util.ext.hideKeyboard +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.resolve import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.setNavigationBarTransparentCompat @@ -137,8 +139,8 @@ class MainActivity : onFirstStart() } - viewModel.onOpenReader.observe(this, this::onOpenReader) - viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.container, null)) + viewModel.onOpenReader.observeEvent(this, this::onOpenReader) + viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.container, null)) viewModel.isLoading.observe(this, this::onLoadingStateChanged) viewModel.isResumeEnabled.observe(this, this::onResumeEnabledChanged) viewModel.counters.observe(this, ::onCountersChanged) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt index f6482dce8..b983b7cbd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainViewModel.kt @@ -5,17 +5,20 @@ import androidx.core.util.set import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject @@ -24,21 +27,25 @@ import javax.inject.Inject class MainViewModel @Inject constructor( private val historyRepository: HistoryRepository, private val appUpdateRepository: AppUpdateRepository, - private val trackingRepository: TrackingRepository, - private val settings: AppSettings, + trackingRepository: TrackingRepository, + settings: AppSettings, ) : BaseViewModel() { - val onOpenReader = SingleLiveEvent() + val onOpenReader = MutableEventFlow() val isResumeEnabled = combine( historyRepository.observeHasItems(), settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled }, ) { hasItems, incognito -> hasItems && !incognito - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn( + scope = viewModelScope + Dispatchers.Default, + started = SharingStarted.WhileSubscribed(5000), + initialValue = false, + ) - val isFeedAvailable = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val isFeedAvailable = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_TRACKER_ENABLED, valueProducer = { isTrackerEnabled }, ) @@ -51,7 +58,11 @@ class MainViewModel @Inject constructor( a[R.id.nav_tools] = if (appUpdate != null) 1 else 0 a[R.id.nav_feed] = tracks a - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, SparseIntArray(0)) + }.stateIn( + scope = viewModelScope + Dispatchers.Default, + started = SharingStarted.WhileSubscribed(5000), + initialValue = SparseIntArray(0), + ) init { launchJob { @@ -62,7 +73,7 @@ class MainViewModel @Inject constructor( fun openLastReader() { launchLoadingJob(Dispatchers.Default) { val manga = historyRepository.getLastOrNull() ?: throw EmptyHistoryException() - onOpenReader.emitCall(manga) + onOpenReader.call(manga) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt index a4a693cf5..ff6bf07bf 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt @@ -22,6 +22,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivityProtectBinding @AndroidEntryPoint @@ -42,9 +44,9 @@ class ProtectActivity : viewBinding.buttonNext.setOnClickListener(this) viewBinding.buttonCancel.setOnClickListener(this) - viewModel.onError.observe(this, this::onError) + viewModel.onError.observeEvent(this, this::onError) viewModel.isLoading.observe(this, this::onLoadingStateChanged) - viewModel.onUnlockSuccess.observe(this) { + viewModel.onUnlockSuccess.observeEvent(this) { val intent = intent.getParcelableExtraCompat(EXTRA_INTENT) startActivity(intent) finishAfterTransition() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt index e530a2a7d..7f0d8f5b5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt @@ -6,7 +6,8 @@ import kotlinx.coroutines.delay import org.koitharu.kotatsu.core.exceptions.WrongPasswordException import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.parsers.util.md5 import javax.inject.Inject @@ -20,7 +21,7 @@ class ProtectViewModel @Inject constructor( private var job: Job? = null - val onUnlockSuccess = SingleLiveEvent() + val onUnlockSuccess = MutableEventFlow() val isBiometricEnabled get() = settings.isBiometricProtectionEnabled diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt index 6cff4c94f..1c75d5702 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/ChaptersLoader.kt @@ -4,8 +4,8 @@ import android.util.LongSparseArray import dagger.hilt.android.scopes.ViewModelScoped import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.details.domain.model.DoubleManga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.reader.ui.pager.ReaderPage import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/DetectReaderModeUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/DetectReaderModeUseCase.kt new file mode 100644 index 000000000..fe4ad571f --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/DetectReaderModeUseCase.kt @@ -0,0 +1,97 @@ +package org.koitharu.kotatsu.reader.domain + +import android.graphics.BitmapFactory +import android.net.Uri +import android.util.Size +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runInterruptible +import okhttp3.OkHttpClient +import org.koitharu.kotatsu.core.model.findChapter +import org.koitharu.kotatsu.core.network.MangaHttpClient +import org.koitharu.kotatsu.core.parser.MangaDataRepository +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.ReaderMode +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.parsers.util.await +import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.reader.ui.ReaderState +import org.koitharu.kotatsu.util.ext.printStackTraceDebug +import java.io.InputStream +import java.util.zip.ZipFile +import javax.inject.Inject +import kotlin.math.roundToInt + +class DetectReaderModeUseCase @Inject constructor( + private val dataRepository: MangaDataRepository, + private val settings: AppSettings, + private val mangaRepositoryFactory: MangaRepository.Factory, + @MangaHttpClient private val okHttpClient: OkHttpClient, +) { + + suspend operator fun invoke(manga: Manga, state: ReaderState?): ReaderMode { + dataRepository.getReaderMode(manga.id)?.let { return it } + val defaultMode = settings.defaultReaderMode + if (!settings.isReaderModeDetectionEnabled || defaultMode == ReaderMode.WEBTOON) { + return defaultMode + } + val chapter = state?.let { manga.findChapter(it.chapterId) } + ?: manga.chapters?.firstOrNull() + ?: error("There are no chapters in this manga") + val repo = mangaRepositoryFactory.create(manga.source) + val pages = repo.getPages(chapter) + return runCatchingCancellable { + val isWebtoon = guessMangaIsWebtoon(repo, pages) + if (isWebtoon) ReaderMode.WEBTOON else defaultMode + }.onSuccess { + dataRepository.saveReaderMode(manga, it) + }.onFailure { + it.printStackTraceDebug() + }.getOrDefault(defaultMode) + } + + /** + * Automatic determine type of manga by page size + * @return ReaderMode.WEBTOON if page is wide + */ + private suspend fun guessMangaIsWebtoon(repository: MangaRepository, pages: List): Boolean { + val pageIndex = (pages.size * 0.3).roundToInt() + val page = requireNotNull(pages.getOrNull(pageIndex)) { "No pages" } + val url = repository.getPageUrl(page) + val uri = Uri.parse(url) + val size = if (uri.scheme == "cbz") { + runInterruptible(Dispatchers.IO) { + val zip = ZipFile(uri.schemeSpecificPart) + val entry = zip.getEntry(uri.fragment) + zip.getInputStream(entry).use { + getBitmapSize(it) + } + } + } else { + val request = PageLoader.createPageRequest(page, url) + okHttpClient.newCall(request).await().use { + runInterruptible(Dispatchers.IO) { + getBitmapSize(it.body?.byteStream()) + } + } + } + return size.width * MIN_WEBTOON_RATIO < size.height + } + + companion object { + + private const val MIN_WEBTOON_RATIO = 1.8 + + private fun getBitmapSize(input: InputStream?): Size { + val options = BitmapFactory.Options().apply { + inJustDecodeBounds = true + } + BitmapFactory.decodeStream(input, null, options)?.recycle() + val imageHeight: Int = options.outHeight + val imageWidth: Int = options.outWidth + check(imageHeight > 0 && imageWidth > 0) + return Size(imageWidth, imageHeight) + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt index d8382a543..b312c9b12 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.reader.ui import android.content.Context +import android.graphics.BitmapFactory import android.net.Uri import android.webkit.MimeTypeMap import androidx.activity.result.ActivityResultLauncher @@ -15,7 +16,6 @@ import okio.IOException import okio.buffer import okio.sink import okio.source -import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.util.ext.writeAllCancellable import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.toFileNameSafe @@ -74,7 +74,7 @@ class PageSaveHelper @Inject constructor( var extension = name.substringAfterLast('.', "") name = name.substringBeforeLast('.') if (extension.length !in 2..4) { - val mimeType = MangaDataRepository.getImageMimeType(file) + val mimeType = getImageMimeType(file) extension = if (mimeType != null) { MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) ?: EXTENSION_FALLBACK } else { @@ -83,4 +83,12 @@ class PageSaveHelper @Inject constructor( } return name.toFileNameSafe().take(MAX_FILENAME_LENGTH) + "." + extension } + + private suspend fun getImageMimeType(file: File): String? = runInterruptible(Dispatchers.IO) { + val options = BitmapFactory.Options().apply { + inJustDecodeBounds = true + } + BitmapFactory.decodeFile(file.path, options)?.recycle() + options.outMimeType + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index 6dfb02e93..f3f655ede 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -42,9 +42,11 @@ import org.koitharu.kotatsu.core.util.IdlingDetector import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ext.hasGlobalPoint import org.koitharu.kotatsu.core.util.ext.isRtl -import org.koitharu.kotatsu.core.util.ext.observeWithPrevious +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.postDelayed import org.koitharu.kotatsu.core.util.ext.setValueRounded +import org.koitharu.kotatsu.core.util.ext.zipWithPrevious import org.koitharu.kotatsu.databinding.ActivityReaderBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter @@ -108,7 +110,7 @@ class ReaderActivity : insetsDelegate.interceptingWindowInsetsListener = this idlingDetector.bindToLifecycle(this) - viewModel.onError.observe( + viewModel.onError.observeEvent( this, DialogErrorObserver( host = viewBinding.container, @@ -117,23 +119,23 @@ class ReaderActivity : onResolved = { isResolved -> if (isResolved) { viewModel.reload() - } else if (viewModel.content.value?.pages.isNullOrEmpty()) { + } else if (viewModel.content.value.pages.isEmpty()) { finishAfterTransition() } }, ), ) viewModel.readerMode.observe(this, this::onInitReader) - viewModel.onPageSaved.observe(this, this::onPageSaved) - viewModel.uiState.observeWithPrevious(this, this::onUiStateChanged) + viewModel.onPageSaved.observeEvent(this, this::onPageSaved) + viewModel.uiState.zipWithPrevious().observe(this, this::onUiStateChanged) viewModel.isLoading.observe(this, this::onLoadingStateChanged) viewModel.content.observe(this) { - onLoadingStateChanged(viewModel.isLoading.value == true) + onLoadingStateChanged(viewModel.isLoading.value) } viewModel.isScreenshotsBlockEnabled.observe(this, this::setWindowSecure) viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged) viewModel.isBookmarkAdded.observe(this, this::onBookmarkStateChanged) - viewModel.onShowToast.observe(this) { msgId -> + viewModel.onShowToast.observeEvent(this) { msgId -> Snackbar.make(viewBinding.container, msgId, Snackbar.LENGTH_SHORT) .setAnchorView(viewBinding.appbarBottom) .show() @@ -150,7 +152,10 @@ class ReaderActivity : viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState()) } - private fun onInitReader(mode: ReaderMode) { + private fun onInitReader(mode: ReaderMode?) { + if (mode == null) { + return + } if (readerManager.currentMode != mode) { readerManager.replace(mode) } @@ -190,7 +195,7 @@ class ReaderActivity : } R.id.action_bookmark -> { - if (viewModel.isBookmarkAdded.value == true) { + if (viewModel.isBookmarkAdded.value) { viewModel.removeBookmark() } else { viewModel.addBookmark() @@ -209,7 +214,7 @@ class ReaderActivity : } private fun onLoadingStateChanged(isLoading: Boolean) { - val hasPages = !viewModel.content.value?.pages.isNullOrEmpty() + val hasPages = viewModel.content.value.pages.isNotEmpty() viewBinding.layoutLoading.isVisible = isLoading && !hasPages if (isLoading && hasPages) { viewBinding.toastView.show(R.string.loading_) @@ -260,7 +265,7 @@ class ReaderActivity : override fun onPageSelected(page: ReaderPage) { lifecycleScope.launch(Dispatchers.Default) { - val pages = viewModel.content.value?.pages ?: return@launch + val pages = viewModel.content.value.pages val index = pages.indexOfFirst { it.chapterId == page.chapterId && it.id == page.id } if (index != -1) { withContext(Dispatchers.Main) { @@ -311,7 +316,7 @@ class ReaderActivity : TransitionManager.beginDelayedTransition(viewBinding.root, transition) viewBinding.appbarTop.isVisible = isUiVisible viewBinding.appbarBottom?.isVisible = isUiVisible - viewBinding.infoBar.isGone = isUiVisible || (viewModel.isInfoBarEnabled.value == false) + viewBinding.infoBar.isGone = isUiVisible || (!viewModel.isInfoBarEnabled.value) if (isUiVisible) { showSystemUI() } else { @@ -367,7 +372,8 @@ class ReaderActivity : menuItem.setIcon(if (isAdded) R.drawable.ic_bookmark_added else R.drawable.ic_bookmark) } - private fun onUiStateChanged(uiState: ReaderUiState?, previous: ReaderUiState?) { + private fun onUiStateChanged(pair: Pair) { + val (uiState: ReaderUiState?, previous: ReaderUiState?) = pair title = uiState?.chapterName ?: uiState?.mangaName ?: getString(R.string.loading_) viewBinding.infoBar.update(uiState) if (uiState == null) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index 029bf76b3..f32dbbbb6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -5,8 +5,6 @@ import androidx.activity.result.ActivityResultLauncher import androidx.annotation.AnyThread import androidx.annotation.MainThread import androidx.annotation.WorkerThread -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -28,35 +26,32 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository -import org.koitharu.kotatsu.core.model.DoubleManga import org.koitharu.kotatsu.core.os.ShortcutsUpdater import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaIntent -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ScreenshotsPolicy import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.core.util.ext.emitValue -import org.koitharu.kotatsu.core.util.ext.processLifecycleScope +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.requireValue -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE -import org.koitharu.kotatsu.local.domain.DoubleMangaLoader +import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase +import org.koitharu.kotatsu.details.domain.model.DoubleManga +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.history.domain.HistoryUpdateUseCase import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.reader.domain.ChaptersLoader +import org.koitharu.kotatsu.reader.domain.DetectReaderModeUseCase import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.ui.config.ReaderSettings import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState @@ -70,7 +65,6 @@ private const val PREFETCH_LIMIT = 10 @HiltViewModel class ReaderViewModel @Inject constructor( savedStateHandle: SavedStateHandle, - private val mangaRepositoryFactory: MangaRepository.Factory, private val dataRepository: MangaDataRepository, private val historyRepository: HistoryRepository, private val bookmarksRepository: BookmarksRepository, @@ -79,7 +73,9 @@ class ReaderViewModel @Inject constructor( private val pageLoader: PageLoader, private val chaptersLoader: ChaptersLoader, private val shortcutsUpdater: ShortcutsUpdater, - private val mangaLoader: DoubleMangaLoader, + private val doubleMangaLoadUseCase: DoubleMangaLoadUseCase, + private val historyUpdateUseCase: HistoryUpdateUseCase, + private val detectReaderModeUseCase: DetectReaderModeUseCase, ) : BaseViewModel() { private val intent = MangaIntent(savedStateHandle) @@ -95,29 +91,29 @@ class ReaderViewModel @Inject constructor( private val mangaFlow: Flow get() = mangaData.map { it?.any } - val readerMode = MutableLiveData() - val onPageSaved = SingleLiveEvent() - val onShowToast = SingleLiveEvent() - val uiState = MutableLiveData(null) + val readerMode = MutableStateFlow(null) + val onPageSaved = MutableEventFlow() + val onShowToast = MutableEventFlow() + val uiState = MutableStateFlow(null) - val content = MutableLiveData(ReaderContent(emptyList(), null)) + val content = MutableStateFlow(ReaderContent(emptyList(), null)) val manga: DoubleManga? get() = mangaData.value - val readerAnimation = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val readerAnimation = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_READER_ANIMATION, valueProducer = { readerAnimation }, ) - val isInfoBarEnabled = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val isInfoBarEnabled = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_READER_BAR, valueProducer = { isReaderBarEnabled }, ) - val isWebtoonZoomEnabled = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val isWebtoonZoomEnabled = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_WEBTOON_ZOOM, valueProducer = { isWebtoonZoomEnable }, ) @@ -136,9 +132,9 @@ class ReaderViewModel @Inject constructor( ) { manga, policy -> policy == ScreenshotsPolicy.BLOCK_ALL || (policy == ScreenshotsPolicy.BLOCK_NSFW && manga != null && manga.isNsfw) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, false) - val isBookmarkAdded: LiveData = currentState.flatMapLatest { state -> + val isBookmarkAdded = currentState.flatMapLatest { state -> val manga = mangaData.value?.any if (state == null || manga == null) { flowOf(false) @@ -146,7 +142,7 @@ class ReaderViewModel @Inject constructor( bookmarksRepository.observeBookmark(manga, state.chapterId, state.page) .map { it != null } } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, false) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false) init { loadImpl() @@ -173,10 +169,8 @@ class ReaderViewModel @Inject constructor( mode = newMode, ) readerMode.value = newMode - content.value?.run { - content.value = copy( - state = getCurrentState(), - ) + content.update { + it.copy(state = getCurrentState()) } } } @@ -189,9 +183,9 @@ class ReaderViewModel @Inject constructor( return } val readerState = state ?: currentState.value ?: return - historyRepository.saveStateAsync( + historyUpdateUseCase.invokeAsync( manga = mangaData.value?.any ?: return, - state = readerState, + readerState = readerState, percent = computePercent(readerState.chapterId, readerState.page), ) } @@ -212,12 +206,12 @@ class ReaderViewModel @Inject constructor( prevJob?.cancelAndJoin() try { val dest = pageSaveHelper.savePage(pageLoader, page, saveLauncher) - onPageSaved.emitCall(dest) + onPageSaved.call(dest) } catch (e: CancellationException) { throw e } catch (e: Exception) { e.printStackTraceDebug() - onPageSaved.emitCall(null) + onPageSaved.call(null) } } } @@ -233,7 +227,7 @@ class ReaderViewModel @Inject constructor( fun getCurrentPage(): MangaPage? { val state = currentState.value ?: return null - return content.value?.pages?.find { + return content.value.pages.find { it.chapterId == state.chapterId && it.index == state.page }?.toMangaPage() } @@ -242,9 +236,9 @@ class ReaderViewModel @Inject constructor( val prevJob = loadingJob loadingJob = launchLoadingJob(Dispatchers.Default) { prevJob?.cancelAndJoin() - content.postValue(ReaderContent(emptyList(), null)) + content.value = ReaderContent(emptyList(), null) chaptersLoader.loadSingleChapter(id) - content.postValue(ReaderContent(chaptersLoader.snapshot(), ReaderState(id, page, 0))) + content.value = ReaderContent(chaptersLoader.snapshot(), ReaderState(id, page, 0)) } } @@ -254,7 +248,7 @@ class ReaderViewModel @Inject constructor( stateChangeJob = launchJob(Dispatchers.Default) { prevJob?.cancelAndJoin() loadingJob?.join() - val pages = content.value?.pages ?: return@launchJob + val pages = content.value.pages pages.getOrNull(position)?.let { page -> currentState.update { cs -> cs?.copy(chapterId = page.chapterId, page = page.index) @@ -296,7 +290,7 @@ class ReaderViewModel @Inject constructor( percent = computePercent(state.chapterId, state.page), ) bookmarksRepository.addBookmark(bookmark) - onShowToast.emitCall(R.string.bookmark_added) + onShowToast.call(R.string.bookmark_added) } } @@ -318,32 +312,31 @@ class ReaderViewModel @Inject constructor( var manga = DoubleManga(dataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", "")) mangaData.value = manga - manga = mangaLoader.load(intent) + manga = doubleMangaLoadUseCase(intent) chaptersLoader.init(manga) // determine mode val singleManga = manga.requireAny() - val mode = detectReaderMode(singleManga) // obtain state if (currentState.value == null) { currentState.value = historyRepository.getOne(singleManga)?.let { ReaderState(it) } ?: ReaderState(singleManga, preselectedBranch) } - + val mode = detectReaderModeUseCase.invoke(singleManga, currentState.value) val branch = chaptersLoader.peekChapter(currentState.value?.chapterId ?: 0L)?.branch mangaData.value = manga.filterChapters(branch) - readerMode.emitValue(mode) + readerMode.value = mode chaptersLoader.loadSingleChapter(requireNotNull(currentState.value).chapterId) // save state if (!isIncognito) { currentState.value?.let { val percent = computePercent(it.chapterId, it.page) - historyRepository.addOrUpdate(singleManga, it.chapterId, it.page, it.scroll, percent) + historyUpdateUseCase.invoke(singleManga, it, percent) } } notifyStateChanged() - content.emitValue(ReaderContent(chaptersLoader.snapshot(), currentState.value)) + content.value = ReaderContent(chaptersLoader.snapshot(), currentState.value) } } @@ -353,7 +346,7 @@ class ReaderViewModel @Inject constructor( loadingJob = launchLoadingJob(Dispatchers.Default) { prevJob?.join() chaptersLoader.loadPrevNextChapter(mangaData.requireValue(), currentId, isNext) - content.emitValue(ReaderContent(chaptersLoader.snapshot(), null)) + content.value = ReaderContent(chaptersLoader.snapshot(), null) } } @@ -367,27 +360,6 @@ class ReaderViewModel @Inject constructor( } } - private suspend fun detectReaderMode(manga: Manga): ReaderMode { - dataRepository.getReaderMode(manga.id)?.let { return it } - val defaultMode = settings.defaultReaderMode - if (!settings.isReaderModeDetectionEnabled || defaultMode == ReaderMode.WEBTOON) { - return defaultMode - } - val chapter = currentState.value?.chapterId?.let { chaptersLoader.peekChapter(it) } - ?: manga.chapters?.randomOrNull() - ?: error("There are no chapters in this manga") - val repo = mangaRepositoryFactory.create(manga.source) - val pages = repo.getPages(chapter) - return runCatchingCancellable { - val isWebtoon = dataRepository.determineMangaIsWebtoon(repo, pages) - if (isWebtoon) ReaderMode.WEBTOON else defaultMode - }.onSuccess { - dataRepository.saveReaderMode(manga, it) - }.onFailure { - it.printStackTraceDebug() - }.getOrDefault(defaultMode) - } - @WorkerThread private fun notifyStateChanged() { val state = getCurrentState() @@ -402,7 +374,7 @@ class ReaderViewModel @Inject constructor( isSliderEnabled = settings.isReaderSliderEnabled, percent = if (state != null) computePercent(state.chapterId, state.page) else PROGRESS_NONE, ) - uiState.postValue(newState) + uiState.value = newState } private fun computePercent(chapterId: Long, pageIndex: Int): Float { @@ -419,23 +391,3 @@ class ReaderViewModel @Inject constructor( return ppc * chapterIndex + ppc * pagePercent } } - -/** - * This function is not a member of the ReaderViewModel - * because it should work independently of the ViewModel's lifecycle. - */ -private fun HistoryRepository.saveStateAsync(manga: Manga, state: ReaderState, percent: Float): Job { - return processLifecycleScope.launch(Dispatchers.Default) { - runCatchingCancellable { - addOrUpdate( - manga = manga, - chapterId = state.chapterId, - page = state.page, - scroll = state.scroll, - percent = percent, - ) - }.onFailure { - it.printStackTraceDebug() - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt index 02a6b00ea..d77cdc62c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigActivity.kt @@ -24,6 +24,8 @@ import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.ext.decodeRegion import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.indicator +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding import org.koitharu.kotatsu.parsers.model.Manga @@ -64,7 +66,7 @@ class ColorFilterConfigActivity : viewModel.colorFilter.observe(this, this::onColorFilterChanged) viewModel.isLoading.observe(this, this::onLoadingChanged) viewModel.preview.observe(this, this::onPreviewChanged) - viewModel.onDismiss.observe(this) { + viewModel.onDismiss.observeEvent(this) { finishAfterTransition() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt index a7d017c15..97527946c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigBackPressedDispatcher.kt @@ -5,6 +5,7 @@ import android.content.DialogInterface import androidx.activity.OnBackPressedCallback import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.ext.call class ColorFilterConfigBackPressedDispatcher( private val context: Context, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt index 22ef8497b..d4568ed2d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/colorfilter/ColorFilterConfigViewModel.kt @@ -1,16 +1,16 @@ package org.koitharu.kotatsu.reader.ui.colorfilter -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaPages import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.domain.ReaderColorFilter import org.koitharu.kotatsu.reader.ui.colorfilter.ColorFilterConfigActivity.Companion.EXTRA_MANGA @@ -26,9 +26,9 @@ class ColorFilterConfigViewModel @Inject constructor( private val manga = checkNotNull(savedStateHandle.get(EXTRA_MANGA)?.manga) private var initialColorFilter: ReaderColorFilter? = null - val colorFilter = MutableLiveData(null) - val onDismiss = SingleLiveEvent() - val preview = MutableLiveData(null) + val colorFilter = MutableStateFlow(null) + val onDismiss = MutableEventFlow() + val preview = MutableStateFlow(null) val isChanged: Boolean get() = colorFilter.value != initialColorFilter @@ -44,13 +44,11 @@ class ColorFilterConfigViewModel @Inject constructor( launchLoadingJob(Dispatchers.Default) { val repository = mangaRepositoryFactory.create(page.source) val url = repository.getPageUrl(page) - preview.emitValue( - MangaPage( - id = page.id, - url = url, - preview = page.preview, - source = page.source, - ), + preview.value = MangaPage( + id = page.id, + url = url, + preview = page.preview, + source = page.source, ) } } @@ -72,7 +70,7 @@ class ColorFilterConfigViewModel @Inject constructor( fun save() { launchLoadingJob(Dispatchers.Default) { mangaDataRepository.saveColorFilter(manga, colorFilter.value) - onDismiss.emitCall(Unit) + onDismiss.call(Unit) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt index 714819f51..4fa2db3f8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt @@ -18,12 +18,14 @@ import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ReaderMode -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseBottomSheet import org.koitharu.kotatsu.core.util.ScreenOrientationHelper +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetReaderConfigBinding @@ -75,8 +77,8 @@ class ReaderConfigBottomSheet : binding.sliderTimer.addOnChangeListener(this) binding.switchScrollTimer.setOnCheckedChangeListener(this) - settings.observeAsLiveData( - context = lifecycleScope.coroutineContext + Dispatchers.Default, + settings.observeAsStateFlow( + scope = lifecycleScope + Dispatchers.Default, key = AppSettings.KEY_READER_AUTOSCROLL_SPEED, valueProducer = { readerAutoscrollSpeed }, ).observe(viewLifecycleOwner) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt index 7570a9f5c..e2a9a82e4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt @@ -6,6 +6,7 @@ import androidx.fragment.app.activityViewModels import androidx.viewbinding.ViewBinding import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.util.ext.getParcelableCompat +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderViewModel diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt index 016a7436f..ce228d578 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.util.ext.doOnPageChanged import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.recyclerView import org.koitharu.kotatsu.core.util.ext.resetTransformations import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt index 19815597b..c08199d24 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.launch import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.util.ext.doOnPageChanged import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.recyclerView import org.koitharu.kotatsu.core.util.ext.resetTransformations import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt index b8f2eac37..e98d90c94 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt @@ -11,6 +11,7 @@ import org.koitharu.kotatsu.core.os.NetworkState import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding import org.koitharu.kotatsu.reader.domain.PageLoader diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index b4fe13b2f..39255497c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -20,6 +20,8 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.ScrollListenerInvalidationObserver import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.core.ui.widgets.BottomSheetHeaderBar +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetPagesBinding @@ -93,7 +95,7 @@ class PagesThumbnailsSheet : viewModel.branch.observe(viewLifecycleOwner) { onExpansionStateChanged(binding.headerBar, binding.headerBar.isExpanded) } - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) } override fun onDestroyView() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt index 934245a5c..30e7ccb75 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -1,18 +1,17 @@ package org.koitharu.kotatsu.reader.ui.thumbnails -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.details.domain.DoubleMangaLoadUseCase import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter -import org.koitharu.kotatsu.local.domain.DoubleMangaLoader import org.koitharu.kotatsu.parsers.util.SuspendLazy import org.koitharu.kotatsu.reader.domain.ChaptersLoader import javax.inject.Inject @@ -22,7 +21,7 @@ class PagesThumbnailsViewModel @Inject constructor( savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, private val chaptersLoader: ChaptersLoader, - private val mangaLoader: DoubleMangaLoader, + private val doubleMangaLoadUseCase: DoubleMangaLoadUseCase, ) : BaseViewModel() { private val currentPageIndex: Int = savedStateHandle[PagesThumbnailsSheet.ARG_CURRENT_PAGE] ?: -1 @@ -31,9 +30,9 @@ class PagesThumbnailsViewModel @Inject constructor( private val repository = mangaRepositoryFactory.create(manga.source) private val mangaDetails = SuspendLazy { - mangaLoader.load(manga).let { + doubleMangaLoadUseCase(manga).let { val b = manga.chapters?.find { ch -> ch.id == initialChapterId }?.branch - branch.emitValue(b) + branch.value = b it.filterChapters(b) } } @@ -41,8 +40,8 @@ class PagesThumbnailsViewModel @Inject constructor( private var loadingPrevJob: Job? = null private var loadingNextJob: Job? = null - val thumbnails = MutableLiveData>() - val branch = MutableLiveData() + val thumbnails = MutableStateFlow>(emptyList()) + val branch = MutableStateFlow(null) val title = manga.title init { @@ -100,6 +99,6 @@ class PagesThumbnailsViewModel @Inject constructor( add(LoadingFooter(1)) } } - thumbnails.emitValue(pages) + thumbnails.value = pages } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index a7a1fb73d..ee0890f4f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.remotelist.ui -import androidx.lifecycle.LiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -9,11 +8,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaRepository @@ -21,7 +24,7 @@ import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.widgets.ChipsView -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel @@ -65,12 +68,12 @@ class RemoteListViewModel @Inject constructor( private val listError = MutableStateFlow(null) private var loadingJob: Job? = null - val filterItems: LiveData> + val filterItems: StateFlow> get() = filter.items override val content = combine( mangaList, - listModeFlow, + listMode, createHeaderFlow(), listError, hasNextPage, @@ -90,7 +93,7 @@ class RemoteListViewModel @Inject constructor( } } } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) init { filter.observeState() @@ -163,7 +166,7 @@ class RemoteListViewModel @Inject constructor( e.printStackTraceDebug() listError.value = e if (!mangaList.value.isNullOrEmpty()) { - errorEvent.emitCall(e) + errorEvent.call(e) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt index 4cc7c0963..f1a4fce2b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt @@ -19,6 +19,8 @@ import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration import org.koitharu.kotatsu.core.util.ext.disposeImageRequest import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.newImageRequest +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerService @@ -64,7 +66,7 @@ class ScrobblerConfigActivity : BaseActivity(), viewModel.content.observe(this, listAdapter::setItems) viewModel.user.observe(this, this::onUserChanged) viewModel.isLoading.observe(this, this::onLoadingStateChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) + viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.onLoggedOut.observe(this) { finishAfterTransition() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt index 1096123eb..029d7ce1e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigViewModel.kt @@ -1,23 +1,24 @@ package org.koitharu.kotatsu.scrobbling.common.ui.config import android.net.Uri -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -40,34 +41,34 @@ class ScrobblerConfigViewModel @Inject constructor( val titleResId = scrobbler.scrobblerService.titleResId - val user = MutableLiveData(null) - val onLoggedOut = SingleLiveEvent() + val user = MutableStateFlow(null) + val onLoggedOut = MutableEventFlow() val content = scrobbler.observeAllScrobblingInfo() .onStart { loadingCounter.increment() } .onFirst { loadingCounter.decrement() } - .catch { errorEvent.postCall(it) } + .catch { errorEvent.call(it) } .map { buildContentList(it) } - .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) init { scrobbler.user - .onEach { user.emitValue(it) } + .onEach { user.value = it } .launchIn(viewModelScope + Dispatchers.Default) } fun onAuthCodeReceived(authCode: String) { launchLoadingJob(Dispatchers.Default) { val newUser = scrobbler.authorize(authCode) - user.emitValue(newUser) + user.value = newUser } } fun logout() { launchLoadingJob(Dispatchers.Default) { scrobbler.logout() - user.emitValue(null) - onLoggedOut.emitCall(Unit) + user.value = null + onLoggedOut.call(Unit) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt index 37502d42a..65e79be5e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorBottomSheet.kt @@ -22,6 +22,8 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetScrobblingSelectorBinding import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener @@ -72,8 +74,8 @@ class ScrobblingSelectorBottomSheet : decoration.checkedItemId = it binding.recyclerView.invalidateItemDecorations() } - viewModel.onError.observe(viewLifecycleOwner, ::onError) - viewModel.onClose.observe(viewLifecycleOwner) { + viewModel.onError.observeEvent(viewLifecycleOwner, ::onError) + viewModel.onClose.observeEvent(viewLifecycleOwner) { dismiss() } viewModel.selectedScrobblerIndex.observe(viewLifecycleOwner) { index -> diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt index c27419e5d..f322f53c4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/selector/ScrobblingSelectorViewModel.kt @@ -1,7 +1,5 @@ package org.koitharu.kotatsu.scrobbling.common.ui.selector -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.RecyclerView.NO_ID @@ -9,14 +7,17 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.core.util.ext.requireValue import org.koitharu.kotatsu.list.ui.model.ListModel @@ -39,7 +40,7 @@ class ScrobblingSelectorViewModel @Inject constructor( val availableScrobblers = scrobblers.filter { it.isAvailable } - val selectedScrobblerIndex = MutableLiveData(0) + val selectedScrobblerIndex = MutableStateFlow(0) private val scrobblerMangaList = MutableStateFlow>(emptyList()) private val hasNextPage = MutableStateFlow(true) @@ -51,7 +52,7 @@ class ScrobblingSelectorViewModel @Inject constructor( private val currentScrobbler: Scrobbler get() = availableScrobblers[selectedScrobblerIndex.requireValue()] - val content: LiveData> = combine( + val content: StateFlow> = combine( scrobblerMangaList, listError, hasNextPage, @@ -71,11 +72,11 @@ class ScrobblingSelectorViewModel @Inject constructor( }, ) } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) - val selectedItemId = MutableLiveData(NO_ID) - val searchQuery = MutableLiveData(manga.title) - val onClose = SingleLiveEvent() + val selectedItemId = MutableStateFlow(NO_ID) + val searchQuery = MutableStateFlow(manga.title) + val onClose = MutableEventFlow() val isEmpty: Boolean get() = scrobblerMangaList.value.isEmpty() @@ -130,13 +131,13 @@ class ScrobblingSelectorViewModel @Inject constructor( if (doneJob?.isActive == true) { return } - val targetId = selectedItemId.value ?: NO_ID + val targetId = selectedItemId.value if (targetId == NO_ID) { onClose.call(Unit) } doneJob = launchJob(Dispatchers.Default) { currentScrobbler.linkManga(manga.id, targetId) - onClose.emitCall(Unit) + onClose.call(Unit) } } @@ -155,7 +156,7 @@ class ScrobblingSelectorViewModel @Inject constructor( try { val info = currentScrobbler.getScrobblingInfoOrNull(manga.id) if (info != null) { - selectedItemId.emitValue(info.targetId) + selectedItemId.value = info.targetId } } finally { loadList(append = false) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt index f36639dec..cb89e0860 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchActivity.kt @@ -13,6 +13,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.showKeyboard import org.koitharu.kotatsu.databinding.ActivitySearchBinding import org.koitharu.kotatsu.parsers.model.MangaSource diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index 7c442d0b1..ff7abf11c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -7,12 +7,14 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel @@ -44,7 +46,7 @@ class SearchViewModel @Inject constructor( override val content = combine( mangaList, - listModeFlow, + listMode, listError, hasNextPage, ) { list, mode, error, hasNext -> @@ -70,7 +72,7 @@ class SearchViewModel @Inject constructor( result } } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) init { loadList(append = false) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt index 0e0c59362..c8c75b2dd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt @@ -21,6 +21,8 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.databinding.ActivitySearchMultiBinding import org.koitharu.kotatsu.details.ui.DetailsActivity @@ -59,10 +61,8 @@ class MultiSearchActivity : setContentView(ActivitySearchMultiBinding.inflate(layoutInflater)) window.statusBarColor = ContextCompat.getColor(this, R.color.dim_statusbar) - val itemCLickListener = object : OnListItemClickListener { - override fun onItemClick(item: MultiSearchListModel, view: View) { - startActivity(SearchActivity.newIntent(view.context, item.source, viewModel.query.value)) - } + val itemCLickListener = OnListItemClickListener { item, view -> + startActivity(SearchActivity.newIntent(view.context, item.source, viewModel.query.value)) } val sizeResolver = ItemSizeResolver(resources, settings) val selectionDecoration = MangaSelectionDecoration(this) @@ -90,8 +90,8 @@ class MultiSearchActivity : viewModel.query.observe(this) { title = it } viewModel.list.observe(this) { adapter.items = it } - viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) - viewModel.onDownloadStarted.observe(this, DownloadStartedObserver(viewBinding.recyclerView)) + viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) + viewModel.onDownloadStarted.observeEvent(this, DownloadStartedObserver(viewBinding.recyclerView)) } override fun onWindowInsetsChanged(insets: Insets) { @@ -130,7 +130,7 @@ class MultiSearchActivity : } override fun onRetryClick(error: Throwable) { - viewModel.doSearch(viewModel.query.value.orEmpty()) + viewModel.doSearch(viewModel.query.value) } override fun onUpdateFilter(tags: Set) = Unit diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index 1a420e11f..51a273537 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -1,7 +1,5 @@ package org.koitharu.kotatsu.search.ui.multi -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -12,17 +10,20 @@ import kotlinx.coroutines.async import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.CompositeException import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData -import org.koitharu.kotatsu.core.util.ext.emitValue +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -50,10 +51,10 @@ class MultiSearchViewModel @Inject constructor( private val listData = MutableStateFlow>(emptyList()) private val loadingData = MutableStateFlow(false) private var listError = MutableStateFlow(null) - val onDownloadStarted = SingleLiveEvent() + val onDownloadStarted = MutableEventFlow() - val query = MutableLiveData(savedStateHandle.get(MultiSearchActivity.EXTRA_QUERY).orEmpty()) - val list: LiveData> = combine( + val query = MutableStateFlow(savedStateHandle.get(MultiSearchActivity.EXTRA_QUERY).orEmpty()) + val list: StateFlow> = combine( listData, loadingData, listError, @@ -75,10 +76,10 @@ class MultiSearchViewModel @Inject constructor( loading -> list + LoadingFooter() else -> list } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) init { - doSearch(query.value.orEmpty()) + doSearch(query.value) } fun getItems(ids: Set): Set { @@ -101,7 +102,7 @@ class MultiSearchViewModel @Inject constructor( listError.value = null listData.value = emptyList() loadingData.value = true - query.emitValue(q) + query.value = q searchImpl(q) } catch (e: CancellationException) { throw e @@ -116,7 +117,7 @@ class MultiSearchViewModel @Inject constructor( fun download(items: Set) { launchJob(Dispatchers.Default) { downloadScheduler.schedule(items) - onDownloadStarted.emitCall(Unit) + onDownloadStarted.call(Unit) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt index bc77594e9..804e00f19 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionFragment.kt @@ -12,6 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter import javax.inject.Inject diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt index 9862e195f..a01a2d31f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/suggestion/SearchSuggestionViewModel.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.search.ui.suggestion -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -17,10 +16,9 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.widgets.ChipsView -import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.search.domain.MangaSearchRepository @@ -42,13 +40,13 @@ class SearchSuggestionViewModel @Inject constructor( private val query = MutableStateFlow("") private var suggestionJob: Job? = null - val isIncognitoModeEnabled = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val isIncognitoModeEnabled = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_INCOGNITO_MODE, valueProducer = { isIncognitoModeEnabled }, ) - val suggestion = MutableLiveData>() + val suggestion = MutableStateFlow>(emptyList()) init { setupSuggestion() @@ -98,7 +96,7 @@ class SearchSuggestionViewModel @Inject constructor( buildSearchSuggestion(searchQuery, hiddenSources) }.distinctUntilChanged() .onEach { - suggestion.emitValue(it) + suggestion.value = it }.launchIn(viewModelScope + Dispatchers.Default) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt index 94051d98b..cda8c9fdd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsFragment.kt @@ -18,6 +18,8 @@ import org.koitharu.kotatsu.core.logs.FileLogger import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.util.ShareHelper +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import javax.inject.Inject @AndroidEntryPoint @@ -45,7 +47,7 @@ class AboutSettingsFragment : BasePreferenceFragment(R.string.about) { viewModel.isLoading.observe(viewLifecycleOwner) { findPreference(AppSettings.KEY_APP_UPDATE)?.isEnabled = !it } - viewModel.onUpdateAvailable.observe(viewLifecycleOwner, ::onUpdateAvailable) + viewModel.onUpdateAvailable.observeEvent(viewLifecycleOwner, ::onUpdateAvailable) } override fun onPreferenceTreeClick(preference: Preference): Boolean { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt index 3ee1ea9e3..638ce1e8e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/about/AboutSettingsViewModel.kt @@ -4,7 +4,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.github.AppVersion import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import javax.inject.Inject @HiltViewModel @@ -13,7 +14,7 @@ class AboutSettingsViewModel @Inject constructor( ) : BaseViewModel() { val isUpdateSupported = appUpdateRepository.isUpdateSupported() - val onUpdateAvailable = SingleLiveEvent() + val onUpdateAvailable = MutableEventFlow() fun checkForUpdates() { launchLoadingJob { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt index 19362ebb2..1a93c12d9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt @@ -13,6 +13,8 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.DialogProgressBinding import java.io.File import java.io.FileOutputStream @@ -46,8 +48,8 @@ class BackupDialogFragment : AlertDialogFragment() { binding.textViewSubtitle.setText(R.string.processing_) viewModel.progress.observe(viewLifecycleOwner, this::onProgressChanged) - viewModel.onBackupDone.observe(viewLifecycleOwner, this::onBackupDone) - viewModel.onError.observe(viewLifecycleOwner, this::onError) + viewModel.onBackupDone.observeEvent(viewLifecycleOwner, this::onBackupDone) + viewModel.onError.observeEvent(viewLifecycleOwner, this::onError) } override fun onBuildDialog(builder: MaterialAlertDialogBuilder): MaterialAlertDialogBuilder { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt index 80d9705e3..8c60b385f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupViewModel.kt @@ -1,13 +1,14 @@ package org.koitharu.kotatsu.settings.backup import android.content.Context -import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipOutput import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import java.io.File import javax.inject.Inject @@ -17,8 +18,8 @@ class BackupViewModel @Inject constructor( @ApplicationContext context: Context, ) : BaseViewModel() { - val progress = MutableLiveData(-1f) - val onBackupDone = SingleLiveEvent() + val progress = MutableStateFlow(-1f) + val onBackupDone = MutableEventFlow() init { launchLoadingJob { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt index c1c7c7817..f2d0b200e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt @@ -12,6 +12,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.backup.CompositeResult import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.DialogProgressBinding import kotlin.math.roundToInt @@ -32,8 +34,8 @@ class RestoreDialogFragment : AlertDialogFragment() { binding.textViewSubtitle.setText(R.string.preparing_) viewModel.progress.observe(viewLifecycleOwner, this::onProgressChanged) - viewModel.onRestoreDone.observe(viewLifecycleOwner, this::onRestoreDone) - viewModel.onError.observe(viewLifecycleOwner, this::onError) + viewModel.onRestoreDone.observeEvent(viewLifecycleOwner, this::onRestoreDone) + viewModel.onError.observeEvent(viewLifecycleOwner, this::onError) } override fun onBuildDialog(builder: MaterialAlertDialogBuilder): MaterialAlertDialogBuilder { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt index cea8a7dfa..01b55c951 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreViewModel.kt @@ -1,18 +1,19 @@ package org.koitharu.kotatsu.settings.backup import android.content.Context -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runInterruptible import org.koitharu.kotatsu.core.backup.BackupEntry import org.koitharu.kotatsu.core.backup.BackupRepository import org.koitharu.kotatsu.core.backup.BackupZipInput import org.koitharu.kotatsu.core.backup.CompositeResult import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.toUriOrNull import java.io.File import java.io.FileNotFoundException @@ -25,8 +26,8 @@ class RestoreViewModel @Inject constructor( @ApplicationContext context: Context, ) : BaseViewModel() { - val progress = MutableLiveData(-1f) - val onRestoreDone = SingleLiveEvent() + val progress = MutableStateFlow(-1f) + val onRestoreDone = MutableEventFlow() init { launchLoadingJob { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt index ac16391c6..bec4ad77f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesDialogFragment.kt @@ -11,6 +11,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.DialogOnboardBinding import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt index 3f631be7b..1a2a935a9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/newsources/NewSourcesViewModel.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.settings.newsources import androidx.core.os.LocaleListCompat -import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.core.model.getLocaleTitle import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel @@ -15,13 +15,9 @@ class NewSourcesViewModel @Inject constructor( private val settings: AppSettings, ) : BaseViewModel() { - val sources = MutableLiveData>() + val sources = MutableStateFlow>(buildList()) private val initialList = settings.newSources - init { - buildList() - } - fun onItemEnabledChanged(item: SourceConfigItem.SourceItem, isEnabled: Boolean) { if (isEnabled) { settings.hiddenSources -= item.source.name @@ -34,10 +30,10 @@ class NewSourcesViewModel @Inject constructor( settings.markKnownSources(initialList) } - private fun buildList() { + private fun buildList(): List { val locales = LocaleListCompat.getDefault().mapToSet { it.language } val pendingHidden = HashSet() - sources.value = initialList.map { + return initialList.map { val locale = it.locale val isEnabledByLocale = locale == null || locale in locales if (!isEnabledByLocale) { @@ -49,9 +45,10 @@ class NewSourcesViewModel @Inject constructor( isEnabled = isEnabledByLocale, isDraggable = false, ) - } - if (pendingHidden.isNotEmpty()) { - settings.hiddenSources += pendingHidden + }.also { + if (pendingHidden.isNotEmpty()) { + settings.hiddenSources += pendingHidden + } } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt index 295a08a90..14ac39e54 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardDialogFragment.kt @@ -10,6 +10,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.AlertDialogFragment +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.showAllowStateLoss import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.DialogOnboardBinding diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt index 4380d0163..4707da3cc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/onboard/OnboardViewModel.kt @@ -1,8 +1,8 @@ package org.koitharu.kotatsu.settings.onboard import androidx.core.os.LocaleListCompat -import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel @@ -26,7 +26,7 @@ class OnboardViewModel @Inject constructor( private val selectedLocales = locales.keys.toMutableSet() - val list = MutableLiveData?>() + val list = MutableStateFlow?>(null) init { if (settings.isSourcesSelected) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt index 955158643..88a1f64e4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt @@ -18,6 +18,7 @@ import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding private const val MIN_PASSWORD_LENGTH = 4 diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt index 387c34848..73b5597b3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt @@ -2,12 +2,16 @@ package org.koitharu.kotatsu.settings.protect import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.parsers.util.md5 import javax.inject.Inject @@ -20,10 +24,10 @@ class ProtectSetupViewModel @Inject constructor( val isSecondStep = firstPassword.map { it != null - }.asFlowLiveData(viewModelScope.coroutineContext, false) - val onPasswordSet = SingleLiveEvent() - val onPasswordMismatch = SingleLiveEvent() - val onClearText = SingleLiveEvent() + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, false) + val onPasswordSet = MutableEventFlow() + val onPasswordMismatch = MutableEventFlow() + val onClearText = MutableEventFlow() val isBiometricEnabled get() = settings.isBiometricProtectionEnabled diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt index d34733efa..12b20babc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt @@ -21,6 +21,8 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.getItem +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.settings.SettingsActivity @@ -64,7 +66,7 @@ class SourcesListFragment : viewModel.items.observe(viewLifecycleOwner) { sourcesAdapter.items = it } - viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) + viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) addMenuProvider(SourcesMenuProvider()) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt index 9eaf346c2..5ba8cd767 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListViewModel.kt @@ -1,10 +1,10 @@ package org.koitharu.kotatsu.settings.sources import androidx.core.os.LocaleListCompat -import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -14,11 +14,12 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction import org.koitharu.kotatsu.core.ui.util.ReversibleHandle -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.map -import org.koitharu.kotatsu.core.util.ext.move import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.move import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem import java.util.Locale @@ -35,8 +36,8 @@ class SourcesListViewModel @Inject constructor( private val settings: AppSettings, ) : BaseViewModel() { - val items = MutableLiveData>(emptyList()) - val onActionDone = SingleLiveEvent() + val items = MutableStateFlow>(emptyList()) + val onActionDone = MutableEventFlow() private val mutex = Mutex() private val expandedGroups = HashSet() @@ -49,7 +50,7 @@ class SourcesListViewModel @Inject constructor( } fun reorderSources(oldPos: Int, newPos: Int): Boolean { - val snapshot = items.value?.toMutableList() ?: return false + val snapshot = items.value.toMutableList() if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isEnabled != true) return false if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isEnabled != true) return false launchAtomicJob(Dispatchers.Default) { @@ -63,7 +64,7 @@ class SourcesListViewModel @Inject constructor( } fun canReorder(oldPos: Int, newPos: Int): Boolean { - val snapshot = items.value?.toMutableList() ?: return false + val snapshot = items.value.toMutableList() if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isEnabled != true) return false return (snapshot[newPos] as? SourceConfigItem.SourceItem)?.isEnabled == true } @@ -81,7 +82,7 @@ class SourcesListViewModel @Inject constructor( val rollback = ReversibleHandle { setEnabled(source, true) } - onActionDone.emitCall(ReversibleAction(R.string.source_disabled, rollback)) + onActionDone.call(ReversibleAction(R.string.source_disabled, rollback)) } buildList() } @@ -126,21 +127,19 @@ class SourcesListViewModel @Inject constructor( val hiddenSources = settings.hiddenSources val query = searchQuery if (!query.isNullOrEmpty()) { - items.postValue( - sources.mapNotNull { - if (!it.title.contains(query, ignoreCase = true)) { - return@mapNotNull null - } - SourceConfigItem.SourceItem( - source = it, - summary = it.getLocaleTitle(), - isEnabled = it.name !in hiddenSources, - isDraggable = false, - ) - }.ifEmpty { - listOf(SourceConfigItem.EmptySearchResult) - }, - ) + items.value = sources.mapNotNull { + if (!it.title.contains(query, ignoreCase = true)) { + return@mapNotNull null + } + SourceConfigItem.SourceItem( + source = it, + summary = it.getLocaleTitle(), + isEnabled = it.name !in hiddenSources, + isDraggable = false, + ) + }.ifEmpty { + listOf(SourceConfigItem.EmptySearchResult) + } return@runInterruptible } val map = sources.groupByTo(TreeMap(LocaleKeyComparator())) { @@ -188,7 +187,7 @@ class SourcesListViewModel @Inject constructor( } } } - items.postValue(result) + items.value = result } private fun getLocaleTitle(localeKey: String?): String? { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt index 51ea765ef..f0ecacc4d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsFragment.kt @@ -15,6 +15,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.github.AppVersion import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.FragmentToolsBinding import org.koitharu.kotatsu.download.ui.list.DownloadsActivity diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt index b977b7996..9d0289bb0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tools/ToolsViewModel.kt @@ -1,14 +1,16 @@ package org.koitharu.kotatsu.settings.tools -import androidx.lifecycle.LiveData -import androidx.lifecycle.asLiveData -import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.github.AppUpdateRepository import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.observeAsLiveData +import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.LocalStorageManager @@ -18,21 +20,18 @@ import javax.inject.Inject @HiltViewModel class ToolsViewModel @Inject constructor( private val storageManager: LocalStorageManager, - private val appUpdateRepository: AppUpdateRepository, private val settings: AppSettings, + appUpdateRepository: AppUpdateRepository, ) : BaseViewModel() { val appUpdate = appUpdateRepository.observeAvailableUpdate() - .asLiveData(viewModelScope.coroutineContext) - val storageUsage: LiveData = liveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, - ) { + val storageUsage: StateFlow = flow { emit(collectStorageUsage()) - } + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null) - val isIncognitoModeEnabled = settings.observeAsLiveData( - context = viewModelScope.coroutineContext + Dispatchers.Default, + val isIncognitoModeEnabled = settings.observeAsStateFlow( + scope = viewModelScope + Dispatchers.Default, key = AppSettings.KEY_INCOGNITO_MODE, valueProducer = { isIncognitoModeEnabled }, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt index d60d185ad..51cca1a26 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsFragment.kt @@ -23,6 +23,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.settings.tracker.categories.TrackerCategoriesConfigSheet import org.koitharu.kotatsu.settings.utils.MultiSummaryProvider import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt index b6d0f8106..cd6713272 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/TrackerSettingsViewModel.kt @@ -1,15 +1,14 @@ package org.koitharu.kotatsu.settings.tracker -import androidx.lifecycle.MutableLiveData import androidx.room.InvalidationTracker import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import okio.Closeable import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.TABLE_FAVOURITE_CATEGORIES import org.koitharu.kotatsu.core.db.removeObserverAsync import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.ext.emitValue import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject @@ -19,7 +18,7 @@ class TrackerSettingsViewModel @Inject constructor( private val database: MangaDatabase, ) : BaseViewModel() { - val categoriesCount = MutableLiveData(null) + val categoriesCount = MutableStateFlow(null) init { updateCategoriesCount() @@ -32,7 +31,7 @@ class TrackerSettingsViewModel @Inject constructor( private fun updateCategoriesCount() { launchJob(Dispatchers.Default) { - categoriesCount.emitValue(repository.getCategoriesCount()) + categoriesCount.value = repository.getCategoriesCount() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt index 028a22020..942ef03ee 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigSheet.kt @@ -12,6 +12,7 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.ui.BaseBottomSheet import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.SheetBaseBinding @AndroidEntryPoint diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt index 8ec72c44c..51daf79b1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/tracker/categories/TrackerCategoriesConfigViewModel.kt @@ -4,9 +4,11 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import javax.inject.Inject @@ -16,7 +18,7 @@ class TrackerCategoriesConfigViewModel @Inject constructor( ) : BaseViewModel() { val content = favouritesRepository.observeCategories() - .asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) private var updateJob: Job? = null diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt similarity index 74% rename from app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt index a534c90cb..5fa916e1c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt @@ -1,9 +1,5 @@ package org.koitharu.kotatsu.shelf.domain -import dagger.Reusable -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.combine @@ -18,19 +14,18 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity import org.koitharu.kotatsu.favourites.data.toFavouriteCategory import org.koitharu.kotatsu.favourites.data.toMangaList -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.local.data.LocalManga +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.local.data.LocalMangaRepository import org.koitharu.kotatsu.local.data.LocalStorageChanges -import org.koitharu.kotatsu.local.domain.LocalMangaRepository +import org.koitharu.kotatsu.local.domain.model.LocalManga import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.parsers.util.runCatchingCancellable +import org.koitharu.kotatsu.shelf.domain.model.ShelfContent import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject -@Reusable -class ShelfRepository @Inject constructor( +class ShelfContentObserveUseCase @Inject constructor( private val localMangaRepository: LocalMangaRepository, private val historyRepository: HistoryRepository, private val trackingRepository: TrackingRepository, @@ -39,7 +34,7 @@ class ShelfRepository @Inject constructor( @LocalStorageChanges private val localStorageChanges: SharedFlow, ) { - fun observeShelfContent(): Flow = combine( + operator fun invoke(): Flow = combine( historyRepository.observeAllWithHistory(), observeLocalManga(SortOrder.UPDATED), observeFavourites(), @@ -69,23 +64,6 @@ class ShelfRepository @Inject constructor( } } - suspend fun deleteLocalManga(ids: Set) { - val list = localMangaRepository.getList(0, null, null) - .filter { x -> x.id in ids } - coroutineScope { - list.map { manga -> - async { - val original = localMangaRepository.getRemoteManga(manga) - if (localMangaRepository.delete(manga)) { - runCatchingCancellable { - historyRepository.deleteOrSwap(manga, original) - } - } - } - }.awaitAll() - } - } - private fun observeCategoriesContent( categories: List, ) = combine>, Map>>( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt similarity index 89% rename from app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt index 1319cf991..3e98c8cd3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContent.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt @@ -1,7 +1,7 @@ -package org.koitharu.kotatsu.shelf.domain +package org.koitharu.kotatsu.shelf.domain.model import org.koitharu.kotatsu.core.model.FavouriteCategory -import org.koitharu.kotatsu.history.domain.MangaWithHistory +import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.parsers.model.Manga class ShelfContent( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfSection.kt similarity index 62% rename from app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfSection.kt index d798c09e5..ecdd14b7d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfSection.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfSection.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.shelf.domain +package org.koitharu.kotatsu.shelf.domain.model enum class ShelfSection { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt index cb499a611..50e2073af 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfFragment.kt @@ -21,6 +21,8 @@ import org.koitharu.kotatsu.core.ui.list.SectionedSelectionController import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.util.ext.addMenuProvider +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentShelfBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver @@ -84,9 +86,9 @@ class ShelfFragment : addMenuProvider(ShelfMenuProvider(binding.root.context, childFragmentManager, viewModel)) viewModel.content.observe(viewLifecycleOwner, ::onListChanged) - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) - viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) - viewModel.onDownloadStarted.observe(viewLifecycleOwner, DownloadStartedObserver(binding.recyclerView)) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) + viewModel.onDownloadStarted.observeEvent(viewLifecycleOwner, DownloadStartedObserver(binding.recyclerView)) } override fun onSaveInstanceState(outState: Bundle) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt index e48113db3..557801d47 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt @@ -1,12 +1,15 @@ package org.koitharu.kotatsu.shelf.ui import androidx.collection.ArraySet -import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.os.NetworkState @@ -15,13 +18,13 @@ import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.MangaWithHistory -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.model.EmptyHint import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -30,11 +33,12 @@ import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toGridModel import org.koitharu.kotatsu.list.ui.model.toUi +import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.shelf.domain.ShelfContent -import org.koitharu.kotatsu.shelf.domain.ShelfRepository -import org.koitharu.kotatsu.shelf.domain.ShelfSection +import org.koitharu.kotatsu.shelf.domain.ShelfContentObserveUseCase +import org.koitharu.kotatsu.shelf.domain.model.ShelfContent +import org.koitharu.kotatsu.shelf.domain.model.ShelfSection import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel import org.koitharu.kotatsu.sync.domain.SyncController import org.koitharu.kotatsu.tracker.domain.TrackingRepository @@ -42,30 +46,31 @@ import javax.inject.Inject @HiltViewModel class ShelfViewModel @Inject constructor( - private val repository: ShelfRepository, private val historyRepository: HistoryRepository, private val favouritesRepository: FavouritesRepository, private val trackingRepository: TrackingRepository, private val settings: AppSettings, private val downloadScheduler: DownloadWorker.Scheduler, + private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase, + shelfContentObserveUseCase: ShelfContentObserveUseCase, syncController: SyncController, networkState: NetworkState, ) : BaseViewModel(), ListExtraProvider { - val onActionDone = SingleLiveEvent() - val onDownloadStarted = SingleLiveEvent() + val onActionDone = MutableEventFlow() + val onDownloadStarted = MutableEventFlow() - val content: LiveData> = combine( + val content: StateFlow> = combine( settings.observeAsFlow(AppSettings.KEY_SHELF_SECTIONS) { shelfSections }, settings.observeAsFlow(AppSettings.KEY_TRACKER_ENABLED) { isTrackerEnabled }, settings.observeAsFlow(AppSettings.KEY_SUGGESTIONS) { isSuggestionsEnabled }, networkState, - repository.observeShelfContent(), + shelfContentObserveUseCase(), ) { sections, isTrackerEnabled, isSuggestionsEnabled, isConnected, content -> mapList(content, isTrackerEnabled, isSuggestionsEnabled, sections, isConnected) }.catch { e -> emit(listOf(e.toErrorState(canRetry = false))) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) init { launchJob(Dispatchers.Default) { @@ -95,7 +100,7 @@ class ShelfViewModel @Inject constructor( } launchJob(Dispatchers.Default) { val handle = favouritesRepository.removeFromCategory(category.id, ids) - onActionDone.emitCall(ReversibleAction(R.string.removed_from_favourites, handle)) + onActionDone.call(ReversibleAction(R.string.removed_from_favourites, handle)) } } @@ -105,14 +110,14 @@ class ShelfViewModel @Inject constructor( } launchJob(Dispatchers.Default) { val handle = historyRepository.delete(ids) - onActionDone.emitCall(ReversibleAction(R.string.removed_from_history, handle)) + onActionDone.call(ReversibleAction(R.string.removed_from_history, handle)) } } fun deleteLocal(ids: Set) { launchLoadingJob(Dispatchers.Default) { - repository.deleteLocalManga(ids) - onActionDone.emitCall(ReversibleAction(R.string.removal_completed, null)) + deleteLocalMangaUseCase(ids) + onActionDone.call(ReversibleAction(R.string.removal_completed, null)) } } @@ -125,12 +130,12 @@ class ShelfViewModel @Inject constructor( historyRepository.deleteAfter(minDate) R.string.removed_from_history } - onActionDone.emitCall(ReversibleAction(stringRes, null)) + onActionDone.call(ReversibleAction(stringRes, null)) } } fun getManga(ids: Set): Set { - val snapshot = content.value ?: return emptySet() + val snapshot = content.value val result = ArraySet(ids.size) for (section in snapshot) { if (section !is ShelfSectionModel) { @@ -151,7 +156,7 @@ class ShelfViewModel @Inject constructor( fun download(items: Set) { launchJob(Dispatchers.Default) { downloadScheduler.schedule(items) - onDownloadStarted.emitCall(Unit) + onDownloadStarted.call(Unit) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt index 6697d0367..e8c8f346f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsActivity.kt @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.ActivityShelfSettingsBinding import com.google.android.material.R as materialR @@ -40,8 +41,6 @@ class ShelfSettingsActivity : it.attachToRecyclerView(this) } } - - viewModel.content.observe(this) { settingsAdapter.items = it } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt index 2897e3eb6..736aa125f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsAdapterDelegates.kt @@ -10,7 +10,7 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.databinding.ItemCategoryCheckableMultipleBinding import org.koitharu.kotatsu.databinding.ItemShelfSectionDraggableBinding -import org.koitharu.kotatsu.shelf.domain.ShelfSection +import org.koitharu.kotatsu.shelf.domain.model.ShelfSection @SuppressLint("ClickableViewAccessibility") fun shelfSectionAD( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt index e75f329de..c45d6bee3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsItemModel.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.shelf.ui.config import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.shelf.domain.ShelfSection +import org.koitharu.kotatsu.shelf.domain.model.ShelfSection sealed interface ShelfSettingsItemModel : ListModel { @@ -19,9 +19,7 @@ sealed interface ShelfSettingsItemModel : ListModel { other as Section if (section != other.section) return false - if (isChecked != other.isChecked) return false - - return true + return isChecked == other.isChecked } override fun hashCode(): Int { @@ -45,9 +43,7 @@ sealed interface ShelfSettingsItemModel : ListModel { if (id != other.id) return false if (title != other.title) return false - if (isChecked != other.isChecked) return false - - return true + return isChecked == other.isChecked } override fun hashCode(): Int { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt index 6d9ac2bde..4df55a1d1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/config/ShelfSettingsViewModel.kt @@ -4,15 +4,17 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.parsers.util.move -import org.koitharu.kotatsu.shelf.domain.ShelfSection +import org.koitharu.kotatsu.shelf.domain.model.ShelfSection import javax.inject.Inject @HiltViewModel @@ -27,7 +29,7 @@ class ShelfSettingsViewModel @Inject constructor( favouritesRepository.observeCategories(), ) { sections, isTrackerEnabled, categories -> buildList(sections, isTrackerEnabled, categories) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) private var updateJob: Job? = null @@ -57,7 +59,7 @@ class ShelfSettingsViewModel @Inject constructor( } fun reorderSections(oldPos: Int, newPos: Int): Boolean { - val snapshot = content.value?.toMutableList() ?: return false + val snapshot = content.value.toMutableList() snapshot.move(oldPos, newPos) settings.shelfSections = snapshot.sections() return true diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt index acf3fe5d1..5eff7818f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt @@ -3,13 +3,15 @@ package org.koitharu.kotatsu.suggestions.ui import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.ui.MangaListViewModel @@ -30,7 +32,7 @@ class SuggestionsViewModel @Inject constructor( override val content = combine( repository.observeAll(), - listModeFlow, + listMode, ) { list, mode -> when { list.isEmpty() -> listOf( @@ -50,10 +52,7 @@ class SuggestionsViewModel @Inject constructor( loadingCounter.decrement() }.catch { emit(listOf(it.toErrorState(canRetry = false))) - }.asFlowLiveData( - viewModelScope.coroutineContext + Dispatchers.Default, - listOf(LoadingState), - ) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) override fun onRefresh() = Unit diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index e96b56930..e5770a597 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -46,7 +46,7 @@ import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull import org.koitharu.kotatsu.core.util.ext.trySetForeground import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.favourites.domain.FavouritesRepository -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaTag diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt index 1ef83da4a..f26b3dd2d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt @@ -22,6 +22,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivitySyncAuthBinding import org.koitharu.kotatsu.sync.data.SyncSettings import org.koitharu.kotatsu.sync.domain.SyncAuthResult @@ -52,8 +54,8 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi onBackPressedDispatcher.addCallback(pageBackCallback) - viewModel.onTokenObtained.observe(this, ::onTokenReceived) - viewModel.onError.observe(this, ::onError) + viewModel.onTokenObtained.observeEvent(this, ::onTokenReceived) + viewModel.onError.observeEvent(this, ::onError) viewModel.isLoading.observe(this, ::onLoadingStateChanged) viewModel.onAccountAlreadyExists.observe(this) { onAccountAlreadyExists() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt index 6aea529a5..fd02134fa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthViewModel.kt @@ -2,13 +2,14 @@ package org.koitharu.kotatsu.sync.ui import android.accounts.AccountManager import android.content.Context -import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.SingleLiveEvent +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty import org.koitharu.kotatsu.sync.data.SyncAuthApi import org.koitharu.kotatsu.sync.domain.SyncAuthResult @@ -20,9 +21,9 @@ class SyncAuthViewModel @Inject constructor( private val api: SyncAuthApi, ) : BaseViewModel() { - val onAccountAlreadyExists = SingleLiveEvent() - val onTokenObtained = SingleLiveEvent() - val host = MutableLiveData("") + val onAccountAlreadyExists = MutableEventFlow() + val onTokenObtained = MutableEventFlow() + val host = MutableStateFlow("") private val defaultHost = context.getString(R.string.sync_host_default) @@ -31,7 +32,7 @@ class SyncAuthViewModel @Inject constructor( val am = AccountManager.get(context) val accounts = am.getAccountsByType(context.getString(R.string.account_type_sync)) if (accounts.isNotEmpty()) { - onAccountAlreadyExists.emitCall(Unit) + onAccountAlreadyExists.call(Unit) } } } @@ -40,8 +41,8 @@ class SyncAuthViewModel @Inject constructor( val hostValue = host.value.ifNullOrEmpty { defaultHost } launchLoadingJob(Dispatchers.Default) { val token = api.authenticate(hostValue, email, password) - val result = SyncAuthResult(host.value.orEmpty(), email, password, token) - onTokenObtained.emitCall(result) + val result = SyncAuthResult(host.value, email, password, token) + onTokenObtained.call(result) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt index 31df0a6be..fcc8f996a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/Tracker.kt @@ -1,16 +1,16 @@ package org.koitharu.kotatsu.tracker.domain import androidx.annotation.VisibleForTesting -import javax.inject.Inject import org.koitharu.kotatsu.core.model.getPreferredBranch import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.tracker.domain.model.MangaTracking import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels import org.koitharu.kotatsu.tracker.work.TrackingItem +import javax.inject.Inject class Tracker @Inject constructor( private val settings: AppSettings, @@ -114,9 +114,11 @@ class Tracker @Inject constructor( newChapters.isEmpty() -> { MangaUpdates(manga, emptyList(), isValid = chapters.lastOrNull()?.id == track.lastChapterId) } + newChapters.size == chapters.size -> { MangaUpdates(manga, emptyList(), isValid = false) } + else -> { MangaUpdates(manga, newChapters, isValid = true) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt index b06b063be..2e9cfd162 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt @@ -18,6 +18,8 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener import org.koitharu.kotatsu.core.ui.list.decor.TypedSpacingItemDecoration import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.getThemeColor +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentFeedBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.list.ui.adapter.MangaListListener @@ -76,11 +78,11 @@ class FeedFragment : ) viewModel.content.observe(viewLifecycleOwner, this::onListChanged) - viewModel.onError.observe(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) + viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) viewModel.onFeedCleared.observe(viewLifecycleOwner) { onFeedCleared() } - TrackWorker.getIsRunningLiveData(binding.root.context.applicationContext) + TrackWorker.observeIsRunning(binding.root.context.applicationContext) .observe(viewLifecycleOwner, this::onIsTrackerRunningChanged) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt index 5c80f4a09..ce1c89b3a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedViewModel.kt @@ -4,12 +4,15 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.model.DateTimeAgo -import org.koitharu.kotatsu.core.util.SingleLiveEvent -import org.koitharu.kotatsu.core.util.asFlowLiveData +import org.koitharu.kotatsu.core.util.ext.MutableEventFlow +import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -32,7 +35,7 @@ class FeedViewModel @Inject constructor( private val limit = MutableStateFlow(PAGE_SIZE) private val isReady = AtomicBoolean(false) - val onFeedCleared = SingleLiveEvent() + val onFeedCleared = MutableEventFlow() val content = repository.observeTrackingLog(limit) .map { list -> if (list.isEmpty()) { @@ -48,7 +51,7 @@ class FeedViewModel @Inject constructor( isReady.set(true) list.mapList() } - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) fun clearFeed(clearCounters: Boolean) { launchLoadingJob(Dispatchers.Default) { @@ -56,7 +59,7 @@ class FeedViewModel @Inject constructor( if (clearCounters) { repository.clearCounters() } - onFeedCleared.emitCall(Unit) + onFeedCleared.call(Unit) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt index bb46a503f..a3dffc059 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt @@ -3,18 +3,20 @@ package org.koitharu.kotatsu.tracker.ui.updates import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker -import org.koitharu.kotatsu.history.domain.HistoryRepository -import org.koitharu.kotatsu.history.domain.PROGRESS_NONE +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -38,7 +40,7 @@ class UpdatesViewModel @Inject constructor( override val content = combine( repository.observeUpdatedManga(), - listModeFlow, + listMode, ) { mangaMap, mode -> when { mangaMap.isEmpty() -> listOf( @@ -58,7 +60,7 @@ class UpdatesViewModel @Inject constructor( loadingCounter.decrement() }.catch { emit(listOf(it.toErrorState(canRetry = false))) - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState)) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) override fun onRefresh() = Unit diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt index 06e8d25c7..934a19ac0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt @@ -11,8 +11,7 @@ import androidx.core.app.NotificationCompat.VISIBILITY_SECRET import androidx.core.app.PendingIntentCompat import androidx.core.content.ContextCompat import androidx.hilt.work.HiltWorker -import androidx.lifecycle.LiveData -import androidx.lifecycle.map +import androidx.lifecycle.asFlow import androidx.work.BackoffPolicy import androidx.work.Constraints import androidx.work.CoroutineWorker @@ -35,6 +34,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R @@ -263,11 +264,13 @@ class TrackWorker @AssistedInject constructor( WorkManager.getInstance(context).enqueue(request) } - fun getIsRunningLiveData(context: Context): LiveData { + fun observeIsRunning(context: Context): Flow { val query = WorkQuery.Builder.fromTags(listOf(TAG, TAG_ONESHOT)).build() - return WorkManager.getInstance(context).getWorkInfosLiveData(query).map { works -> - works.any { x -> x.state == WorkInfo.State.RUNNING } - } + return WorkManager.getInstance(context).getWorkInfosLiveData(query) + .asFlow() + .map { works -> + works.any { x -> x.state == WorkInfo.State.RUNNING } + } } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt index fc263b5d7..83266be1e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentListFactory.kt @@ -14,7 +14,7 @@ import kotlinx.coroutines.runBlocking import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.replaceWith diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt index 250892e28..a5052477a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/widget/recent/RecentWidgetService.kt @@ -4,7 +4,7 @@ import android.content.Intent import android.widget.RemoteViewsService import coil.ImageLoader import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.history.domain.HistoryRepository +import org.koitharu.kotatsu.history.data.HistoryRepository import javax.inject.Inject @AndroidEntryPoint diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt index 15e453361..e51c3c912 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigActivity.kt @@ -17,6 +17,8 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter import org.koitharu.kotatsu.widget.shelf.model.CategoryItem @@ -57,7 +59,7 @@ class ShelfConfigActivity : viewModel.checkedId = config.categoryId viewModel.content.observe(this, this::onContentChanged) - viewModel.onError.observe(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) + viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) } override fun onClick(v: View) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt index 1208cb5dd..3a1b4deca 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/widget/shelf/ShelfConfigViewModel.kt @@ -1,13 +1,15 @@ package org.koitharu.kotatsu.widget.shelf -import androidx.lifecycle.LiveData import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import org.koitharu.kotatsu.core.ui.BaseViewModel -import org.koitharu.kotatsu.core.util.asFlowLiveData import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.widget.shelf.model.CategoryItem import javax.inject.Inject @@ -19,7 +21,7 @@ class ShelfConfigViewModel @Inject constructor( private val selectedCategoryId = MutableStateFlow(0L) - val content: LiveData> = combine( + val content: StateFlow> = combine( favouritesRepository.observeCategories(), selectedCategoryId, ) { categories, selectedId -> @@ -29,7 +31,11 @@ class ShelfConfigViewModel @Inject constructor( CategoryItem(it.id, it.title, selectedId == it.id) } list - }.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, emptyList()) + }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, emptyList()) - var checkedId: Long by selectedCategoryId::value + var checkedId: Long + get() = selectedCategoryId.value + set(value) { + selectedCategoryId.value = value + } } From 2442e7cbe14fe3d6975d84454a3fe2de46614843 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 29 May 2023 13:06:50 +0300 Subject: [PATCH 13/90] Fix warnings --- app/build.gradle | 10 ++--- .../core/parser/RemoteMangaRepository.kt | 2 +- .../core/parser/favicon/FaviconFetcher.kt | 6 +-- .../kotatsu/core/ui/BaseFullscreenActivity.kt | 38 ++++--------------- .../org/koitharu/kotatsu/core/util/Event.kt | 2 +- .../koitharu/kotatsu/core/util/ext/Android.kt | 2 + .../kotatsu/core/util/ext/FlowObserver.kt | 4 -- .../kotatsu/explore/ui/ExploreFragment.kt | 2 +- .../kotatsu/explore/ui/model/ExploreItem.kt | 13 ++----- .../local/data/input/LocalMangaDirInput.kt | 1 - .../koitharu/kotatsu/main/ui/MainActivity.kt | 2 +- .../kotatsu/main/ui/MainNavigationDelegate.kt | 3 +- .../ui/config/ScrobblerConfigActivity.kt | 2 +- .../settings/protect/ProtectSetupActivity.kt | 7 ++-- .../kotatsu/sync/ui/SyncAuthActivity.kt | 2 +- .../kotatsu/tracker/ui/feed/FeedFragment.kt | 2 +- build.gradle | 2 +- 17 files changed, 34 insertions(+), 66 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9ee4d3fd9..5e3d86120 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,7 +106,7 @@ dependencies { implementation 'androidx.work:work-runtime-ktx:2.8.1' //noinspection GradleDependency - implementation('com.google.guava:guava:31.1-android') { + implementation('com.google.guava:guava:32.0.0-android') { exclude group: 'com.google.guava', module: 'failureaccess' exclude group: 'org.checkerframework', module: 'checker-qual' exclude group: 'com.google.j2objc', module: 'j2objc-annotations' @@ -116,8 +116,8 @@ dependencies { implementation 'androidx.room:room-ktx:2.5.1' kapt 'androidx.room:room-compiler:2.5.1' - implementation 'com.squareup.okhttp3:okhttp:4.10.0' - implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3' + implementation 'com.squareup.okhttp3:okhttp:4.11.0' + implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.11.0' implementation 'com.squareup.okio:okio:3.3.0' implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl:4.3.2' @@ -128,8 +128,8 @@ dependencies { implementation 'androidx.hilt:hilt-work:1.0.0' kapt 'androidx.hilt:hilt-compiler:1.0.0' - implementation 'io.coil-kt:coil-base:2.3.0' - implementation 'io.coil-kt:coil-svg:2.3.0' + implementation 'io.coil-kt:coil-base:2.4.0' + implementation 'io.coil-kt:coil-svg:2.4.0' implementation 'com.github.KotatsuApp:subsampling-scale-image-view:1b19231b2f' implementation 'com.github.solkin:disk-lru-cache:1.4' implementation 'io.noties.markwon:core:4.6.2' diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt index 0f3d6d482..65758fd99 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt @@ -101,7 +101,7 @@ class RemoteMangaRepository( } fun getAvailableMirrors(): List { - return parser.configKeyDomain.presetValues?.toList().orEmpty() + return parser.configKeyDomain.presetValues.toList() } private fun getConfig() = parser.config as SourceSettings diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt index be0d0dcfc..6af4218ae 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt @@ -86,7 +86,7 @@ class FaviconFetcher( if (!options.diskCachePolicy.readEnabled) { return null } - val snapshot = diskCache.value?.get(diskCacheKey) ?: return null + val snapshot = diskCache.value?.openSnapshot(diskCacheKey) ?: return null return SourceResult( source = snapshot.toImageSource(), mimeType = null, @@ -98,12 +98,12 @@ class FaviconFetcher( if (!options.diskCachePolicy.writeEnabled || body.contentLength() == 0L) { return null } - val editor = diskCache.value?.edit(diskCacheKey) ?: return null + val editor = diskCache.value?.openEditor(diskCacheKey) ?: return null try { fileSystem.write(editor.data) { body.source().readAll(this) } - return editor.commitAndGet() + return editor.commitAndOpenSnapshot() } catch (e: Throwable) { try { editor.abort() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt index 96a240e55..27f2b5fb2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt @@ -3,57 +3,35 @@ package org.koitharu.kotatsu.core.ui import android.graphics.Color import android.os.Build import android.os.Bundle -import android.view.View import android.view.WindowManager +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.viewbinding.ViewBinding -@Suppress("DEPRECATION") -private const val SYSTEM_UI_FLAGS_SHOWN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - -@Suppress("DEPRECATION") -private const val SYSTEM_UI_FLAGS_HIDDEN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or - View.SYSTEM_UI_FLAG_FULLSCREEN or - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - abstract class BaseFullscreenActivity : - BaseActivity(), - View.OnSystemUiVisibilityChangeListener { + BaseActivity() { + + private lateinit var insetsControllerCompat: WindowInsetsControllerCompat override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) with(window) { + insetsControllerCompat = WindowInsetsControllerCompat(this, decorView) statusBarColor = Color.TRANSPARENT navigationBarColor = Color.TRANSPARENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } - decorView.setOnSystemUiVisibilityChangeListener(this@BaseFullscreenActivity) } showSystemUI() } - @Suppress("DEPRECATION", "DeprecatedCallableAddReplaceWith") - @Deprecated("Deprecated in Java") - final override fun onSystemUiVisibilityChange(visibility: Int) { - onSystemUiVisibilityChanged(visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) - } - - // TODO WindowInsetsControllerCompat works incorrect - @Suppress("DEPRECATION") protected fun hideSystemUI() { - window.decorView.systemUiVisibility = SYSTEM_UI_FLAGS_HIDDEN + insetsControllerCompat.hide(WindowInsetsCompat.Type.systemBars()) } - @Suppress("DEPRECATION") protected fun showSystemUI() { - window.decorView.systemUiVisibility = SYSTEM_UI_FLAGS_SHOWN + insetsControllerCompat.show(WindowInsetsCompat.Type.systemBars()) } - - protected open fun onSystemUiVisibilityChanged(isVisible: Boolean) = Unit } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt index e14d2703c..1fd768af1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/Event.kt @@ -8,7 +8,7 @@ class Event( private var isConsumed = false suspend fun consume(collector: FlowCollector) { - if (isConsumed) { + if (!isConsumed) { collector.emit(data) isConsumed = true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt index 02c0f3ba0..9f5941449 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt @@ -23,6 +23,8 @@ import android.widget.Toast import androidx.activity.result.ActivityResultLauncher import androidx.annotation.IntegerRes import androidx.core.app.ActivityOptionsCompat +import androidx.core.content.IntentCompat +import androidx.core.content.PackageManagerCompat import androidx.core.os.LocaleListCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt index bfd2db25f..e13f221e1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/FlowObserver.kt @@ -9,13 +9,9 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.util.Event fun Flow.observe(owner: LifecycleOwner, collector: FlowCollector) { - if (BuildConfig.DEBUG) { - require((this as? StateFlow)?.value !is Event<*>) - } val start = if (this is StateFlow) CoroutineStart.UNDISPATCHED else CoroutineStart.DEFAULT owner.lifecycleScope.launch(start = start) { owner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt index 69b6c9d5c..bf58733d5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt @@ -80,7 +80,7 @@ class ExploreFragment : viewModel.onOpenManga.observeEvent(viewLifecycleOwner, ::onOpenManga) viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) viewModel.isGrid.observe(viewLifecycleOwner, ::onGridModeChanged) - viewModel.onShowSuggestionsTip.observe(viewLifecycleOwner) { + viewModel.onShowSuggestionsTip.observeEvent(viewLifecycleOwner) { showSuggestionsTip() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt index e9d4603f3..9449ee21a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/model/ExploreItem.kt @@ -18,9 +18,7 @@ sealed interface ExploreItem : ListModel { other as Buttons - if (isSuggestionsEnabled != other.isSuggestionsEnabled) return false - - return true + return isSuggestionsEnabled == other.isSuggestionsEnabled } override fun hashCode(): Int { @@ -40,9 +38,7 @@ sealed interface ExploreItem : ListModel { other as Header if (titleResId != other.titleResId) return false - if (isButtonVisible != other.isButtonVisible) return false - - return true + return isButtonVisible == other.isButtonVisible } override fun hashCode(): Int { @@ -64,9 +60,7 @@ sealed interface ExploreItem : ListModel { other as Source if (source != other.source) return false - if (isGrid != other.isGrid) return false - - return true + return isGrid == other.isGrid } override fun hashCode(): Int { @@ -76,7 +70,6 @@ sealed interface ExploreItem : ListModel { } } - @Deprecated("") class EmptyHint( @DrawableRes icon: Int, @StringRes textPrimary: Int, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt index e62943d07..c2cac2c60 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/input/LocalMangaDirInput.kt @@ -130,7 +130,6 @@ class LocalMangaDirInput(root: File) : LocalMangaInput(root) { } val cbz = root.listFilesRecursive(CbzFilter()).firstOrNull() ?: return null return ZipFile(cbz).use { zip -> - val filter = ImageFileFilter() zip.entries().asSequence() .firstOrNull { x -> !x.isDirectory && filter.accept(x) } ?.let { entry -> zipUri(cbz, entry.name) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt index 024cb6994..731aa12de 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -129,7 +129,7 @@ class MainActivity : navigationDelegate = MainNavigationDelegate(checkNotNull(bottomNav ?: viewBinding.navRail), supportFragmentManager) navigationDelegate.addOnFragmentChangedListener(this) - navigationDelegate.onCreate(savedInstanceState) + navigationDelegate.onCreate() onBackPressedDispatcher.addCallback(ExitCallback(this, viewBinding.container)) onBackPressedDispatcher.addCallback(navigationDelegate) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt index fe23e3cc2..adfec639a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainNavigationDelegate.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.main.ui -import android.os.Bundle import android.view.MenuItem import androidx.activity.OnBackPressedCallback import androidx.annotation.IdRes @@ -57,7 +56,7 @@ class MainNavigationDelegate( navBar.selectedItemId = R.id.nav_shelf } - fun onCreate(savedInstanceState: Bundle?) { + fun onCreate() { primaryFragment?.let { onFragmentChanged(it, fromUser = false) val itemId = getItemId(it) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt index f1a4fce2b..ac1784635 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/ScrobblerConfigActivity.kt @@ -67,7 +67,7 @@ class ScrobblerConfigActivity : BaseActivity(), viewModel.user.observe(this, this::onUserChanged) viewModel.isLoading.observe(this, this::onLoadingStateChanged) viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) - viewModel.onLoggedOut.observe(this) { + viewModel.onLoggedOut.observeEvent(this) { finishAfterTransition() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt index 88a1f64e4..cc086c8cd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt @@ -19,6 +19,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding private const val MIN_PASSWORD_LENGTH = 4 @@ -46,13 +47,13 @@ class ProtectSetupActivity : viewBinding.switchBiometric.setOnCheckedChangeListener(this) viewModel.isSecondStep.observe(this, this::onStepChanged) - viewModel.onPasswordSet.observe(this) { + viewModel.onPasswordSet.observeEvent(this) { finishAfterTransition() } - viewModel.onPasswordMismatch.observe(this) { + viewModel.onPasswordMismatch.observeEvent(this) { viewBinding.editPassword.error = getString(R.string.passwords_mismatch) } - viewModel.onClearText.observe(this) { + viewModel.onClearText.observeEvent(this) { viewBinding.editPassword.text?.clear() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt index f26b3dd2d..a7cd65491 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncAuthActivity.kt @@ -57,7 +57,7 @@ class SyncAuthActivity : BaseActivity(), View.OnClickLi viewModel.onTokenObtained.observeEvent(this, ::onTokenReceived) viewModel.onError.observeEvent(this, ::onError) viewModel.isLoading.observe(this, ::onLoadingStateChanged) - viewModel.onAccountAlreadyExists.observe(this) { + viewModel.onAccountAlreadyExists.observeEvent(this) { onAccountAlreadyExists() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt index 2e9cfd162..588e22677 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt @@ -79,7 +79,7 @@ class FeedFragment : viewModel.content.observe(viewLifecycleOwner, this::onListChanged) viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) - viewModel.onFeedCleared.observe(viewLifecycleOwner) { + viewModel.onFeedCleared.observeEvent(viewLifecycleOwner) { onFeedCleared() } TrackWorker.observeIsRunning(binding.root.context.applicationContext) diff --git a/build.gradle b/build.gradle index c420893c0..bd956dc1e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.0.1' + classpath 'com.android.tools.build:gradle:8.0.2' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.21' classpath 'com.google.dagger:hilt-android-gradle-plugin:2.46.1' } From 3d05541f61d64527de3158e46709c3a1b008ab9b Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 30 May 2023 08:49:21 +0300 Subject: [PATCH 14/90] Update reader activity ui --- .../kotatsu/core/ui/BaseFullscreenActivity.kt | 1 + .../list/fastscroll/FastScrollRecyclerView.kt | 9 ++- .../kotatsu/reader/ui/ReaderActivity.kt | 22 ++++--- .../kotatsu/reader/ui/ReaderViewModel.kt | 1 + .../ui/config/ReaderConfigBottomSheet.kt | 3 +- .../kotatsu/reader/ui/pager/ReaderUiState.kt | 10 ++++ .../ui/thumbnails/PagesThumbnailsSheet.kt | 1 + .../adapter/PageThumbnailAdapter.kt | 15 ++++- .../tracker/ui/feed/adapter/FeedAdapter.kt | 15 ++++- .../res/layout-w600dp/activity_reader.xml | 44 +++++++------- .../res/layout-w600dp/fragment_details.xml | 1 + app/src/main/res/layout/activity_browser.xml | 3 +- app/src/main/res/layout/activity_reader.xml | 58 +++++++++---------- app/src/main/res/layout/fragment_details.xml | 1 + app/src/main/res/layout/item_download.xml | 1 - app/src/main/res/layout/sheet_pages.xml | 26 +++++---- app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 8 +++ app/src/main/res/values/themes.xml | 2 + 19 files changed, 142 insertions(+), 80 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt index 27f2b5fb2..9a7ccbd2e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BaseFullscreenActivity.kt @@ -24,6 +24,7 @@ abstract class BaseFullscreenActivity : WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } } + insetsControllerCompat.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE showSystemUI() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt index 2b62a6d49..1a1590019 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/fastscroll/FastScrollRecyclerView.kt @@ -4,6 +4,7 @@ import android.content.Context import android.util.AttributeSet import android.view.ViewGroup import androidx.annotation.AttrRes +import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.R @@ -15,6 +16,12 @@ class FastScrollRecyclerView @JvmOverloads constructor( val fastScroller = FastScroller(context, attrs) + var isFastScrollerEnabled: Boolean = true + set(value) { + field = value + fastScroller.isVisible = value && isVisible + } + init { fastScroller.id = R.id.fast_scroller fastScroller.layoutParams = ViewGroup.LayoutParams( @@ -30,7 +37,7 @@ class FastScrollRecyclerView @JvmOverloads constructor( override fun setVisibility(visibility: Int) { super.setVisibility(visibility) - fastScroller.visibility = visibility + fastScroller.visibility = if (isFastScrollerEnabled) visibility else GONE } override fun onAttachedToWindow() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index f3f655ede..0b8ce9908 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -14,6 +14,7 @@ import android.view.Menu import android.view.MenuItem import android.view.MotionEvent import android.view.View +import android.view.ViewGroup.MarginLayoutParams import android.view.WindowManager import androidx.activity.viewModels import androidx.core.graphics.Insets @@ -21,6 +22,7 @@ import androidx.core.view.OnApplyWindowInsetsListener import androidx.core.view.WindowInsetsCompat import androidx.core.view.isGone import androidx.core.view.isVisible +import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.lifecycle.lifecycleScope import com.google.android.material.snackbar.Snackbar @@ -333,11 +335,11 @@ class ReaderActivity : right = systemBars.right, left = systemBars.left, ) - viewBinding.appbarBottom?.updatePadding( - bottom = systemBars.bottom, - right = systemBars.right, - left = systemBars.left, - ) + viewBinding.appbarBottom?.updateLayoutParams { + bottomMargin = systemBars.bottom + topMargin + rightMargin = systemBars.right + topMargin + leftMargin = systemBars.left + topMargin + } return WindowInsetsCompat.Builder(insets) .setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE) .build() @@ -373,19 +375,15 @@ class ReaderActivity : } private fun onUiStateChanged(pair: Pair) { - val (uiState: ReaderUiState?, previous: ReaderUiState?) = pair - title = uiState?.chapterName ?: uiState?.mangaName ?: getString(R.string.loading_) + val (previous: ReaderUiState?, uiState: ReaderUiState?) = pair + title = uiState?.resolveTitle(this) ?: getString(R.string.loading_) viewBinding.infoBar.update(uiState) if (uiState == null) { supportActionBar?.subtitle = null viewBinding.slider.isVisible = false return } - supportActionBar?.subtitle = if (uiState.chapterNumber in 1..uiState.chaptersTotal) { - getString(R.string.chapter_d_of_d, uiState.chapterNumber, uiState.chaptersTotal) - } else { - null - } + supportActionBar?.subtitle = uiState.chapterName if (previous?.chapterName != null && uiState.chapterName != previous.chapterName) { if (!uiState.chapterName.isNullOrEmpty()) { viewBinding.toastView.showTemporary(uiState.chapterName, TOAST_DURATION) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index f32dbbbb6..0ccbac877 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -366,6 +366,7 @@ class ReaderViewModel @Inject constructor( val chapter = state?.chapterId?.let { chaptersLoader.peekChapter(it) } val newState = ReaderUiState( mangaName = manga?.any?.title, + branch = chapter?.branch, chapterName = chapter?.name, chapterNumber = chapter?.number ?: 0, chaptersTotal = manga?.any?.getChapters(chapter?.branch)?.size ?: 0, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt index 4fa2db3f8..3994526dd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigBottomSheet.kt @@ -41,7 +41,8 @@ class ReaderConfigBottomSheet : ActivityResultCallback, View.OnClickListener, MaterialButtonToggleGroup.OnButtonCheckedListener, - Slider.OnChangeListener, CompoundButton.OnCheckedChangeListener { + Slider.OnChangeListener, + CompoundButton.OnCheckedChangeListener { private val viewModel by activityViewModels() private val savePageRequest = registerForActivityResult(PageSaveContract(), this) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt index e97192ecf..650c4439a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/ReaderUiState.kt @@ -1,7 +1,11 @@ package org.koitharu.kotatsu.reader.ui.pager +import android.content.Context +import org.koitharu.kotatsu.R + data class ReaderUiState( val mangaName: String?, + val branch: String?, val chapterName: String?, val chapterNumber: Int, val chaptersTotal: Int, @@ -14,4 +18,10 @@ data class ReaderUiState( fun isSliderAvailable(): Boolean { return isSliderEnabled && totalPages > 1 && currentPage < totalPages } + + fun resolveTitle(context: Context): String? = when { + mangaName == null -> null + branch == null -> mangaName + else -> context.getString(R.string.manga_branch_title_template, mangaName, branch) + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index 39255497c..72293932c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -124,6 +124,7 @@ class PagesThumbnailsSheet : } else { headerBar.subtitle = null } + viewBinding?.recyclerView?.isFastScrollerEnabled = isExpanded } private inner class ScrollListener : BoundsScrollListener(3, 3) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt index e1169638a..1b197fdb6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAdapter.kt @@ -1,10 +1,12 @@ package org.koitharu.kotatsu.reader.ui.thumbnails.adapter +import android.content.Context import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.list.ui.adapter.listHeaderAD import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD import org.koitharu.kotatsu.list.ui.model.ListHeader @@ -16,7 +18,7 @@ class PageThumbnailAdapter( coil: ImageLoader, lifecycleOwner: LifecycleOwner, clickListener: OnListItemClickListener, -) : AsyncListDifferDelegationAdapter(DiffCallback()) { +) : AsyncListDifferDelegationAdapter(DiffCallback()), FastScroller.SectionIndexer { init { delegatesManager.addDelegate(ITEM_TYPE_THUMBNAIL, pageThumbnailAD(coil, lifecycleOwner, clickListener)) @@ -24,6 +26,17 @@ class PageThumbnailAdapter( .addDelegate(ITEM_LOADING, loadingFooterAD()) } + override fun getSectionText(context: Context, position: Int): CharSequence? { + val list = items + for (i in (0..position).reversed()) { + val item = list.getOrNull(i) ?: continue + if (item is ListHeader) { + return item.getText(context) + } + } + return null + } + private class DiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel): Boolean { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt index 64963e946..063e17d8c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/adapter/FeedAdapter.kt @@ -1,9 +1,11 @@ package org.koitharu.kotatsu.tracker.ui.feed.adapter +import android.content.Context import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.DiffUtil import coil.ImageLoader import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter +import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.core.ui.model.DateTimeAgo import org.koitharu.kotatsu.list.ui.adapter.MangaListListener import org.koitharu.kotatsu.list.ui.adapter.emptyStateListAD @@ -21,7 +23,7 @@ class FeedAdapter( coil: ImageLoader, lifecycleOwner: LifecycleOwner, listener: MangaListListener, -) : AsyncListDifferDelegationAdapter(DiffCallback()) { +) : AsyncListDifferDelegationAdapter(DiffCallback()), FastScroller.SectionIndexer { init { delegatesManager @@ -34,6 +36,17 @@ class FeedAdapter( .addDelegate(ITEM_TYPE_DATE_HEADER, relatedDateItemAD()) } + override fun getSectionText(context: Context, position: Int): CharSequence? { + val list = items + for (i in (0..position).reversed()) { + val item = list.getOrNull(i) ?: continue + if (item is DateTimeAgo) { + return item.format(context.resources) + } + } + return null + } + private class DiffCallback : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel) = when { diff --git a/app/src/main/res/layout-w600dp/activity_reader.xml b/app/src/main/res/layout-w600dp/activity_reader.xml index 051bfefe5..50b3da7ee 100644 --- a/app/src/main/res/layout-w600dp/activity_reader.xml +++ b/app/src/main/res/layout-w600dp/activity_reader.xml @@ -1,5 +1,5 @@ - - - + android:elevation="@dimen/m3_card_elevated_elevation" + app:elevation="@dimen/m3_card_elevated_elevation" + app:liftOnScroll="false"> + android:layout_weight="1" /> + app:menu="@menu/opt_reader_bottom"> + + - + diff --git a/app/src/main/res/layout-w600dp/fragment_details.xml b/app/src/main/res/layout-w600dp/fragment_details.xml index 81e1c7403..bad58eb53 100644 --- a/app/src/main/res/layout-w600dp/fragment_details.xml +++ b/app/src/main/res/layout-w600dp/fragment_details.xml @@ -206,6 +206,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:showAnimationBehavior="inward" + app:trackCornerRadius="0dp" tools:visibility="visible" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index 06ad562fe..8c97641da 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -1,5 +1,5 @@ - - - + android:elevation="@dimen/m3_card_elevated_elevation" + app:elevation="@dimen/m3_card_elevated_elevation" + app:liftOnScroll="false"> - + android:layout_margin="8dp" + app:layout_insetEdge="bottom"> + app:menu="@menu/opt_reader_bottom"> - + + + + android:indeterminate="true" + app:trackCornerRadius="@dimen/mtrl_progress_indicator_full_rounded_corner_radius" /> - + diff --git a/app/src/main/res/layout/fragment_details.xml b/app/src/main/res/layout/fragment_details.xml index 4af56cca4..ff371e036 100644 --- a/app/src/main/res/layout/fragment_details.xml +++ b/app/src/main/res/layout/fragment_details.xml @@ -218,6 +218,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:showAnimationBehavior="inward" + app:trackCornerRadius="0dp" tools:visibility="visible" /> - + android:layout_height="match_parent"> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aee909a83..2c3977217 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -424,4 +424,5 @@ Port Proxy Invalid value + %1$s (%2$s) diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 098dd4768..452574345 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -76,6 +76,14 @@ 18sp + + + + + + From da4aedca979c54f0b42548b72f705984c4ab7fb1 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sat, 3 Jun 2023 16:54:04 +0300 Subject: [PATCH 27/90] Fix proxy authentication --- .../core/network/ProxyAuthenticator.kt | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/ProxyAuthenticator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/ProxyAuthenticator.kt index bc1fb8d53..fb4ffad7e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/ProxyAuthenticator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/ProxyAuthenticator.kt @@ -6,12 +6,24 @@ import okhttp3.Request import okhttp3.Response import okhttp3.Route import org.koitharu.kotatsu.core.prefs.AppSettings +import java.net.PasswordAuthentication +import java.net.Proxy class ProxyAuthenticator( private val settings: AppSettings, -) : Authenticator { +) : Authenticator, java.net.Authenticator() { + + init { + setDefault(this) + } override fun authenticate(route: Route?, response: Response): Request? { + if (!isProxyEnabled()) { + return null + } + if (response.request.header(CommonHeaders.PROXY_AUTHORIZATION) != null) { + return null + } val login = settings.proxyLogin ?: return null val password = settings.proxyPassword ?: return null val credential = Credentials.basic(login, password) @@ -19,4 +31,15 @@ class ProxyAuthenticator( .header(CommonHeaders.PROXY_AUTHORIZATION, credential) .build() } + + override fun getPasswordAuthentication(): PasswordAuthentication? { + if (!isProxyEnabled()) { + return null + } + val login = settings.proxyLogin ?: return null + val password = settings.proxyPassword ?: return null + return PasswordAuthentication(login, password.toCharArray()) + } + + private fun isProxyEnabled() = settings.proxyType != Proxy.Type.DIRECT } From b48c6d7d3888175ad22fb0b575055a13c2aacc94 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 15:42:15 +0300 Subject: [PATCH 28/90] Fix pages bottom sheet scroll --- .../core/ui/list/BoundsScrollListener.kt | 13 +++++- .../ScrollListenerInvalidationObserver.kt | 30 ------------- .../kotatsu/core/util/CompositeRunnable.kt | 12 ++++++ .../koitharu/kotatsu/core/util/ext/Other.kt | 14 ++++++ .../ui/thumbnails/PagesThumbnailsSheet.kt | 43 +++++++++++++++---- .../ui/thumbnails/PagesThumbnailsViewModel.kt | 14 +++++- app/src/main/res/layout/sheet_pages.xml | 2 +- 7 files changed, 84 insertions(+), 44 deletions(-) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeRunnable.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt index f9d41fec8..9aa7cdf93 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/BoundsScrollListener.kt @@ -3,8 +3,10 @@ package org.koitharu.kotatsu.core.ui.list import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -abstract class BoundsScrollListener(private val offsetTop: Int, private val offsetBottom: Int) : - RecyclerView.OnScrollListener() { +abstract class BoundsScrollListener( + @JvmField protected val offsetTop: Int, + @JvmField protected val offsetBottom: Int +) : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) @@ -24,9 +26,16 @@ abstract class BoundsScrollListener(private val offsetTop: Int, private val offs if (firstVisibleItemPosition <= offsetTop) { onScrolledToStart(recyclerView) } + onPostScrolled(recyclerView, firstVisibleItemPosition, visibleItemCount) } abstract fun onScrolledToStart(recyclerView: RecyclerView) abstract fun onScrolledToEnd(recyclerView: RecyclerView) + + protected open fun onPostScrolled( + recyclerView: RecyclerView, + firstVisibleItemPosition: Int, + visibleItemCount: Int + ) = Unit } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt deleted file mode 100644 index 5acc5862c..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ScrollListenerInvalidationObserver.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.koitharu.kotatsu.core.ui.list - -import androidx.recyclerview.widget.RecyclerView - -class ScrollListenerInvalidationObserver( - private val recyclerView: RecyclerView, - private val scrollListener: RecyclerView.OnScrollListener, -) : RecyclerView.AdapterDataObserver() { - - override fun onChanged() { - super.onChanged() - invalidateScroll() - } - - override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { - super.onItemRangeInserted(positionStart, itemCount) - invalidateScroll() - } - - override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { - super.onItemRangeRemoved(positionStart, itemCount) - invalidateScroll() - } - - private fun invalidateScroll() { - recyclerView.post { - scrollListener.onScrolled(recyclerView, 0, 0) - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeRunnable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeRunnable.kt new file mode 100644 index 000000000..fe56ffc3c --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/CompositeRunnable.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.core.util + +class CompositeRunnable( + private val children: List, +) : Runnable, Collection by children { + + override fun run() { + for (child in children) { + child.run() + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt index baf078b7f..046bd94ca 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Other.kt @@ -1,5 +1,7 @@ package org.koitharu.kotatsu.core.util.ext +import org.koitharu.kotatsu.core.util.CompositeRunnable + @Suppress("UNCHECKED_CAST") fun Class.castOrNull(obj: Any?): T? { if (obj == null || !isInstance(obj)) { @@ -7,3 +9,15 @@ fun Class.castOrNull(obj: Any?): T? { } return obj as T } + +/* CompositeRunnable */ + +operator fun Runnable.plus(other: Runnable): Runnable { + val list = ArrayList(this.size + other.size) + if (this is CompositeRunnable) list.addAll(this) else list.add(this) + if (other is CompositeRunnable) list.addAll(other) else list.add(other) + return CompositeRunnable(list) +} + +private val Runnable.size: Int + get() = if (this is CompositeRunnable) size else 1 diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index 4f49f9bad..a5aa7ac9c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -16,23 +16,25 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.list.BoundsScrollListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.core.ui.list.ScrollListenerInvalidationObserver import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet +import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observeEvent +import org.koitharu.kotatsu.core.util.ext.plus import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetPagesBinding import org.koitharu.kotatsu.list.ui.MangaListSpanResolver +import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter -import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.TargetScrollObserver import javax.inject.Inject +import kotlin.math.roundToInt @AndroidEntryPoint class PagesThumbnailsSheet : @@ -79,14 +81,8 @@ class PagesThumbnailsSheet : spanResolver?.setGridSize(settings.gridSize / 100f, this) addOnScrollListener(ScrollListener().also { scrollListener = it }) (layoutManager as GridLayoutManager).spanSizeLookup = spanSizeLookup - thumbnailsAdapter?.registerAdapterDataObserver( - ScrollListenerInvalidationObserver(this, checkNotNull(scrollListener)), - ) - thumbnailsAdapter?.registerAdapterDataObserver(TargetScrollObserver(this)) - } - viewModel.thumbnails.observe(viewLifecycleOwner) { - thumbnailsAdapter?.setItems(it, listCommitCallback) } + viewModel.thumbnails.observe(viewLifecycleOwner, ::onThumbnailsChanged) viewModel.branch.observe(viewLifecycleOwner, ::updateTitle) viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this)) } @@ -124,6 +120,28 @@ class PagesThumbnailsSheet : } } + private fun onThumbnailsChanged(list: List) { + val adapter = thumbnailsAdapter ?: return + if (adapter.itemCount == 0) { + var position = list.indexOfFirst { it is PageThumbnail && it.isCurrent } + if (position > 0) { + val spanCount = spanResolver?.spanCount ?: 0 + val offset = if (position > spanCount + 1) { + (resources.getDimensionPixelSize(R.dimen.manga_list_details_item_height) * 0.6).roundToInt() + } else { + position = 0 + 0 + } + val scrollCallback = RecyclerViewScrollCallback(requireViewBinding().recyclerView, position, offset) + adapter.setItems(list, listCommitCallback + scrollCallback) + } else { + adapter.setItems(list, listCommitCallback) + } + } else { + adapter.setItems(list, listCommitCallback) + } + } + private inner class ScrollListener : BoundsScrollListener(3, 3) { override fun onScrolledToStart(recyclerView: RecyclerView) { @@ -133,6 +151,13 @@ class PagesThumbnailsSheet : override fun onScrolledToEnd(recyclerView: RecyclerView) { viewModel.loadNextChapter() } + + override fun onPostScrolled(recyclerView: RecyclerView, firstVisibleItemPosition: Int, visibleItemCount: Int) { + super.onPostScrolled(recyclerView, firstVisibleItemPosition, visibleItemCount) + if (firstVisibleItemPosition > offsetTop) { + viewModel.allowLoadAbove() + } + } } private inner class SpanSizeLookup : GridLayoutManager.SpanSizeLookup() { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt index 8116560fa..ef0463ba0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -39,6 +39,7 @@ class PagesThumbnailsViewModel @Inject constructor( private var loadingJob: Job? = null private var loadingPrevJob: Job? = null private var loadingNextJob: Job? = null + private var isLoadAboveAllowed = false val thumbnails = MutableStateFlow>(emptyList()) val branch = MutableStateFlow(null) @@ -51,8 +52,17 @@ class PagesThumbnailsViewModel @Inject constructor( } } + fun allowLoadAbove() { + if (!isLoadAboveAllowed) { + loadingJob = launchJob(Dispatchers.Default) { + isLoadAboveAllowed = true + updateList() + } + } + } + fun loadPrevChapter() { - if (loadingJob?.isActive == true || loadingPrevJob?.isActive == true) { + if (!isLoadAboveAllowed || loadingJob?.isActive == true || loadingPrevJob?.isActive == true) { return } loadingPrevJob = loadPrevNextChapter(isNext = false) @@ -74,7 +84,7 @@ class PagesThumbnailsViewModel @Inject constructor( private suspend fun updateList() { val snapshot = chaptersLoader.snapshot() val mangaChapters = mangaDetails.tryGet().getOrNull()?.chapters.orEmpty() - val hasPrevChapter = snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id + val hasPrevChapter = isLoadAboveAllowed && snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id val hasNextChapter = snapshot.lastOrNull()?.chapterId != mangaChapters.lastOrNull()?.id val pages = buildList(snapshot.size + chaptersLoader.size + 2) { if (hasPrevChapter) { diff --git a/app/src/main/res/layout/sheet_pages.xml b/app/src/main/res/layout/sheet_pages.xml index 986ea651b..140e944af 100644 --- a/app/src/main/res/layout/sheet_pages.xml +++ b/app/src/main/res/layout/sheet_pages.xml @@ -19,7 +19,7 @@ Date: Sun, 4 Jun 2023 16:02:38 +0300 Subject: [PATCH 29/90] Set style for drag handle globally --- app/src/main/res/layout/activity_details.xml | 1 - app/src/main/res/layout/layout_sheet_header_adaptive.xml | 1 - app/src/main/res/values/themes.xml | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index c73fd7075..7e6f0e8d1 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -55,7 +55,6 @@ android:orientation="vertical"> diff --git a/app/src/main/res/layout/layout_sheet_header_adaptive.xml b/app/src/main/res/layout/layout_sheet_header_adaptive.xml index 616360f18..0f5bead1c 100644 --- a/app/src/main/res/layout/layout_sheet_header_adaptive.xml +++ b/app/src/main/res/layout/layout_sheet_header_adaptive.xml @@ -9,7 +9,6 @@ tools:parentTag="android.widget.LinearLayout"> @style/Widget.Material3.CollapsingToolbar.Medium @style/Widget.Kotatsu.CircularProgressIndicator @style/Widget.Kotatsu.LinearProgressIndicator + @style/Widget.Kotatsu.BottomSheet.DragHandle @style/TextAppearance.Kotatsu.Menu From 46b797fc67bf16af0928a7e2f6f01b8ef62537a0 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 15:56:57 +0300 Subject: [PATCH 30/90] Fix chapters bottom sheet header size --- .../koitharu/kotatsu/details/ui/DetailsActivity.kt | 3 +++ app/src/main/res/layout/activity_details.xml | 13 +++++++++---- .../res/layout/layout_sheet_header_adaptive.xml | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 0acb146c1..038348767 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -243,6 +243,9 @@ class DetailsActivity : viewBinding.cardChapters?.updateLayoutParams { bottomMargin = insets.bottom + marginEnd } + viewBinding.dragHandle?.updateLayoutParams { + bottomMargin = insets.bottom + } } private fun onHistoryChanged(info: HistoryInfo) { diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index 7e6f0e8d1..579adf35d 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -48,7 +48,7 @@ app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.BottomSheet" tools:visibility="visible"> - + android:layout_height="?actionBarSize" + android:layout_gravity="top" + android:paddingTop="0dp" + android:paddingBottom="32dp" + tools:layout_marginBottom="14dp" /> @@ -92,7 +97,7 @@ - + From b5705b45dfa26ad6c2bcaeb09ed174ebd3628253 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 15:59:44 +0300 Subject: [PATCH 31/90] Add port number validation --- .../kotatsu/settings/ProxySettingsFragment.kt | 4 +++- .../kotatsu/settings/SourceSettingsExt.kt | 2 ++ .../{ => utils/validation}/DomainValidator.kt | 2 +- .../{ => utils/validation}/HeaderValidator.kt | 2 +- .../utils/validation/PortNumberValidator.kt | 24 +++++++++++++++++++ .../kotatsu/sync/ui/SyncHostDialogFragment.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 7 files changed, 33 insertions(+), 4 deletions(-) rename app/src/main/kotlin/org/koitharu/kotatsu/settings/{ => utils/validation}/DomainValidator.kt (93%) rename app/src/main/kotlin/org/koitharu/kotatsu/settings/{ => utils/validation}/HeaderValidator.kt (92%) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/PortNumberValidator.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt index ab6097f5f..4125d46e2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ProxySettingsFragment.kt @@ -13,6 +13,8 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.settings.utils.EditTextBindListener import org.koitharu.kotatsu.settings.utils.PasswordSummaryProvider +import org.koitharu.kotatsu.settings.utils.validation.DomainValidator +import org.koitharu.kotatsu.settings.utils.validation.PortNumberValidator import java.net.Proxy @AndroidEntryPoint @@ -32,7 +34,7 @@ class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy), EditTextBindListener( inputType = EditorInfo.TYPE_CLASS_NUMBER, hint = null, - validator = null, + validator = PortNumberValidator(), ), ) findPreference(AppSettings.KEY_PROXY_PASSWORD)?.let { pref -> diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt index 6a83af617..d0123bee7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SourceSettingsExt.kt @@ -11,6 +11,8 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.settings.utils.AutoCompleteTextViewPreference import org.koitharu.kotatsu.settings.utils.EditTextBindListener import org.koitharu.kotatsu.settings.utils.EditTextDefaultSummaryProvider +import org.koitharu.kotatsu.settings.utils.validation.DomainValidator +import org.koitharu.kotatsu.settings.utils.validation.HeaderValidator fun PreferenceFragmentCompat.addPreferencesFromRepository(repository: RemoteMangaRepository) { val configKeys = repository.getConfigKeys() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/DomainValidator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/DomainValidator.kt similarity index 93% rename from app/src/main/kotlin/org/koitharu/kotatsu/settings/DomainValidator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/DomainValidator.kt index 0ac467edc..201fabeec 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/DomainValidator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/DomainValidator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.settings +package org.koitharu.kotatsu.settings.utils.validation import okhttp3.HttpUrl import org.koitharu.kotatsu.R diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/HeaderValidator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/HeaderValidator.kt similarity index 92% rename from app/src/main/kotlin/org/koitharu/kotatsu/settings/HeaderValidator.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/HeaderValidator.kt index b25be70d6..36891f980 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/HeaderValidator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/HeaderValidator.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.settings +package org.koitharu.kotatsu.settings.utils.validation import okhttp3.Headers import org.koitharu.kotatsu.R diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/PortNumberValidator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/PortNumberValidator.kt new file mode 100644 index 000000000..3bee9f9a5 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/utils/validation/PortNumberValidator.kt @@ -0,0 +1,24 @@ +package org.koitharu.kotatsu.settings.utils.validation + +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.util.EditTextValidator + +class PortNumberValidator : EditTextValidator() { + + override fun validate(text: String): ValidationResult { + val trimmed = text.trim() + if (trimmed.isEmpty()) { + return ValidationResult.Success + } + return if (!checkCharacters(trimmed)) { + ValidationResult.Failed(context.getString(R.string.invalid_port_number)) + } else { + ValidationResult.Success + } + } + + private fun checkCharacters(value: String): Boolean { + val intValue = value.toIntOrNull() ?: return false + return intValue in 1..65535 + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt index 735adb19a..2de3183f4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/sync/ui/SyncHostDialogFragment.kt @@ -14,7 +14,7 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.databinding.PreferenceDialogAutocompletetextviewBinding -import org.koitharu.kotatsu.settings.DomainValidator +import org.koitharu.kotatsu.settings.utils.validation.DomainValidator import org.koitharu.kotatsu.sync.data.SyncSettings import javax.inject.Inject diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb9f3d1f4..5dad409f3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -432,4 +432,5 @@ Username Password Authorization (optional) + Invalid port number From 12d8d3e2d117354e810a0ac3872afb541954e74a Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 16:04:36 +0300 Subject: [PATCH 32/90] Set AppProxySelector as default --- .../org/koitharu/kotatsu/core/network/AppProxySelector.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt index 5beb6e42a..7d67a40fd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/network/AppProxySelector.kt @@ -13,6 +13,10 @@ class AppProxySelector( private val settings: AppSettings, ) : ProxySelector() { + init { + setDefault(this) + } + private var cachedProxy: Proxy? = null override fun select(uri: URI?): List { From 02d5dfb37599ebd15fa34f5ad71056c70b319f40 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 16:50:09 +0300 Subject: [PATCH 33/90] Check if page file valid before page display --- .../koitharu/kotatsu/core/util/ext/File.kt | 2 ++ .../kotatsu/core/util/ext/Throwable.kt | 3 +++ .../koitharu/kotatsu/local/data/PagesCache.kt | 20 ++++++++++++++++++- .../kotatsu/reader/domain/PageLoader.kt | 13 +++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt index ac98e2b48..79877887b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/File.kt @@ -26,6 +26,8 @@ fun File.takeIfReadable() = takeIf { it.exists() && it.canRead() } fun File.takeIfWriteable() = takeIf { it.exists() && it.canWrite() } +fun File.isNotEmpty() = length() != 0L + fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().use { it.readText() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt index 3623d56d1..29defe131 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Throwable.kt @@ -87,3 +87,6 @@ fun Throwable.isWebViewUnavailable(): Boolean { return (this is AndroidRuntimeException && message?.contains("WebView") == true) || cause?.isWebViewUnavailable() == true } + +@Suppress("FunctionName") +fun NoSpaceLeftException() = IOException(MSG_NO_SPACE_LEFT) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt index 336fe6511..a39f01262 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/data/PagesCache.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.local.data import android.content.Context +import android.os.StatFs import com.tomclaw.cache.DiskLruCache import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers @@ -33,7 +34,8 @@ class PagesCache @Inject constructor(@ApplicationContext context: Context) { } private val lruCache = SuspendLazy { val dir = cacheDir.get() - val size = FileSize.MEGABYTES.convert(200, FileSize.BYTES) + val availableSize = getAvailableSizeMb() + val size = SIZE_DEFAULT.coerceIn(SIZE_MIN, availableSize) runCatchingCancellable { DiskLruCache.create(dir, size) }.recoverCatching { error -> @@ -63,4 +65,20 @@ class PagesCache @Inject constructor(@ApplicationContext context: Context) { file.delete() } } + + private suspend fun getAvailableSizeMb(): Long = runCatchingCancellable { + val statFs = StatFs(cacheDir.get().absolutePath) + FileSize.BYTES.convert(statFs.availableBytes, FileSize.MEGABYTES) + }.onFailure { + it.printStackTraceDebug() + }.getOrDefault(SIZE_DEFAULT) + + private companion object { + + val SIZE_MIN + get() = FileSize.MEGABYTES.convert(20, FileSize.BYTES) + + val SIZE_DEFAULT + get() = FileSize.MEGABYTES.convert(200, FileSize.BYTES) + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt index d37d80a30..eeac2ce29 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/PageLoader.kt @@ -12,6 +12,7 @@ import dagger.hilt.android.lifecycle.RetainedLifecycle import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.scopes.ActivityRetainedScoped import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.flow.MutableStateFlow @@ -32,6 +33,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.FileSize import org.koitharu.kotatsu.core.util.RetainedLifecycleCoroutineScope import org.koitharu.kotatsu.core.util.ext.ensureSuccess +import org.koitharu.kotatsu.core.util.ext.isNotEmpty import org.koitharu.kotatsu.core.util.ext.ramAvailable import org.koitharu.kotatsu.core.util.ext.withProgress import org.koitharu.kotatsu.core.util.progress.ProgressDeferred @@ -103,7 +105,7 @@ class PageLoader @Inject constructor( } fun loadPageAsync(page: MangaPage, force: Boolean): ProgressDeferred { - var task = tasks[page.id] + var task = tasks[page.id]?.takeIf { it.isValid() } if (force) { task?.cancel() } else if (task?.isCancelled == false) { @@ -216,6 +218,15 @@ class PageLoader @Inject constructor( return context.ramAvailable <= FileSize.MEGABYTES.convert(PREFETCH_MIN_RAM_MB, FileSize.BYTES) } + private fun Deferred.isValid(): Boolean { + return if (isCompleted) { + val file = getCompleted() + file.exists() && file.isNotEmpty() + } else { + true + } + } + private class InternalErrorHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler { From 1847759ec3ebb8fbf94d6eb7fe91414348ff1690 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 4 Jun 2023 17:37:54 +0300 Subject: [PATCH 34/90] Refactor list extra provider --- .../org/koitharu/kotatsu/core/AppModule.kt | 5 -- .../core/parser/MangaTagHighlighter.kt | 37 ----------- .../kotatsu/details/ui/DetailsFragment.kt | 6 +- .../ui/list/FavouritesListViewModel.kt | 30 ++------- .../kotatsu/history/data/HistoryDao.kt | 10 ++- .../kotatsu/history/data/HistoryRepository.kt | 6 ++ .../history/ui/HistoryListViewModel.kt | 20 ++---- .../kotatsu/list/domain/ListExtraProvider.kt | 60 ++++++++++++++++-- .../list/domain/ListExtraProviderImpl.kt | 32 ---------- .../list/ui/model/ListModelConversionExt.kt | 63 ++++++------------- .../kotatsu/local/ui/LocalListViewModel.kt | 3 - .../remotelist/ui/RemoteListViewModel.kt | 4 +- .../kotatsu/search/ui/SearchViewModel.kt | 6 +- .../search/ui/multi/MultiSearchViewModel.kt | 4 +- .../domain/ShelfContentObserveUseCase.kt | 11 ++-- .../shelf/domain/model/ShelfContent.kt | 5 +- .../kotatsu/shelf/ui/ShelfViewModel.kt | 49 ++++----------- .../suggestions/ui/SuggestionsViewModel.kt | 6 +- .../kotatsu/tracker/data/TracksDao.kt | 5 +- .../tracker/domain/TrackingRepository.kt | 5 +- .../tracker/ui/updates/UpdatesViewModel.kt | 33 ++-------- 21 files changed, 143 insertions(+), 257 deletions(-) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProviderImpl.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt index 1aad04a76..25332e92e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/AppModule.kt @@ -40,8 +40,6 @@ import org.koitharu.kotatsu.core.util.IncognitoModeIndicator import org.koitharu.kotatsu.core.util.ext.activityManager import org.koitharu.kotatsu.core.util.ext.connectivityManager import org.koitharu.kotatsu.core.util.ext.isLowRamDevice -import org.koitharu.kotatsu.list.domain.ListExtraProvider -import org.koitharu.kotatsu.list.domain.ListExtraProviderImpl import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.CbzFetcher import org.koitharu.kotatsu.local.data.LocalStorageChanges @@ -65,9 +63,6 @@ interface AppModule { @Binds fun bindImageGetter(coilImageGetter: CoilImageGetter): Html.ImageGetter - @Binds - fun bindListExtraProvider(impl: ListExtraProviderImpl): ListExtraProvider - companion object { @Provides diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt deleted file mode 100644 index 7168445bd..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaTagHighlighter.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.koitharu.kotatsu.core.parser - -import android.content.Context -import androidx.annotation.ColorRes -import dagger.Reusable -import dagger.hilt.android.qualifiers.ApplicationContext -import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.parsers.model.MangaTag -import javax.inject.Inject - -@Reusable -class MangaTagHighlighter @Inject constructor( - @ApplicationContext context: Context, -) { - - private val dict by lazy { - context.resources.openRawResource(R.raw.tags_redlist).use { - val set = HashSet() - it.bufferedReader().forEachLine { x -> - val line = x.trim() - if (line.isNotEmpty()) { - set.add(line) - } - } - set - } - } - - @ColorRes - fun getTint(tag: MangaTag): Int { - return if (tag.title.lowercase() in dict) { - R.color.warning - } else { - 0 - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 7c581df2b..5cf4dc756 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -23,7 +23,6 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.bookmarks.domain.Bookmark import org.koitharu.kotatsu.bookmarks.ui.adapter.BookmarksAdapter import org.koitharu.kotatsu.core.model.countChaptersByBranch -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener @@ -45,6 +44,7 @@ import org.koitharu.kotatsu.details.ui.scrobbling.ScrobblingItemDecoration import org.koitharu.kotatsu.details.ui.scrobbling.ScrollingInfoAdapter import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.image.ui.ImageActivity +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource @@ -67,7 +67,7 @@ class DetailsFragment : lateinit var coil: ImageLoader @Inject - lateinit var tagHighlighter: MangaTagHighlighter + lateinit var tagHighlighter: ListExtraProvider private val viewModel by activityViewModels() @@ -283,7 +283,7 @@ class DetailsFragment : manga.tags.map { tag -> ChipsView.ChipModel( title = tag.title, - tint = tagHighlighter.getTint(tag), + tint = tagHighlighter.getTagTint(tag), icon = 0, data = tag, isCheckable = false, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index 3c7ceb019..dea73f94f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.ReversibleAction import org.koitharu.kotatsu.core.util.ext.call @@ -21,8 +20,6 @@ import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID -import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -30,19 +27,16 @@ import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject @HiltViewModel class FavouritesListViewModel @Inject constructor( savedStateHandle: SavedStateHandle, private val repository: FavouritesRepository, - private val trackingRepository: TrackingRepository, - private val historyRepository: HistoryRepository, - private val settings: AppSettings, - private val tagHighlighter: MangaTagHighlighter, + private val listExtraProvider: ListExtraProvider, + settings: AppSettings, downloadScheduler: DownloadWorker.Scheduler, -) : MangaListViewModel(settings, downloadScheduler), ListExtraProvider { +) : MangaListViewModel(settings, downloadScheduler) { val categoryId: Long = savedStateHandle[ARG_CATEGORY_ID] ?: NO_ID @@ -76,7 +70,7 @@ class FavouritesListViewModel @Inject constructor( ), ) - else -> list.toUi(mode, this, tagHighlighter) + else -> list.toUi(mode, listExtraProvider) } }.catch { emit(listOf(it.toErrorState(canRetry = false))) @@ -108,20 +102,4 @@ class FavouritesListViewModel @Inject constructor( repository.setCategoryOrder(categoryId, order) } } - - override suspend fun getCounter(mangaId: Long): Int { - return if (settings.isTrackerEnabled) { - trackingRepository.getNewChaptersCount(mangaId) - } else { - 0 - } - } - - override suspend fun getProgress(mangaId: Long): Float { - return if (settings.isReadingIndicatorsEnabled) { - historyRepository.getProgress(mangaId) - } else { - PROGRESS_NONE - } - } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt index be2c5f7e9..0e033ddd5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt @@ -1,6 +1,10 @@ package org.koitharu.kotatsu.history.data -import androidx.room.* +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Transaction import kotlinx.coroutines.flow.Flow import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.TagEntity @@ -20,6 +24,10 @@ abstract class HistoryDao { @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC") abstract fun observeAll(): Flow> + @Transaction + @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC LIMIT :limit") + abstract fun observeAll(limit: Int): Flow> + @Query("SELECT * FROM manga WHERE manga_id IN (SELECT manga_id FROM history WHERE deleted_at = 0)") abstract suspend fun findAllManga(): List diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt index f8977fabf..3cd576e87 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt @@ -51,6 +51,12 @@ class HistoryRepository @Inject constructor( } } + fun observeAll(limit: Int): Flow> { + return db.historyDao.observeAll(limit).mapItems { + it.manga.toManga(it.tags.toMangaTags()) + } + } + fun observeAllWithHistory(): Flow> { return db.historyDao.observeAll().mapItems { MangaWithHistory( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index c46f349db..673fbc87d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -10,7 +10,6 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.observeAsStateFlow @@ -21,8 +20,8 @@ import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.history.domain.model.MangaWithHistory +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -31,7 +30,6 @@ import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toGridModel import org.koitharu.kotatsu.list.ui.model.toListDetailedModel import org.koitharu.kotatsu.list.ui.model.toListModel -import org.koitharu.kotatsu.tracker.domain.TrackingRepository import java.util.Date import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -40,8 +38,7 @@ import javax.inject.Inject class HistoryListViewModel @Inject constructor( private val repository: HistoryRepository, private val settings: AppSettings, - private val trackingRepository: TrackingRepository, - private val tagHighlighter: MangaTagHighlighter, + private val extraProvider: ListExtraProvider, downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { @@ -106,7 +103,6 @@ class HistoryListViewModel @Inject constructor( mode: ListMode, ): List { val result = ArrayList(if (grouped) (list.size * 1.4).toInt() else list.size + 1) - val showPercent = settings.isReadingIndicatorsEnabled var prevDate: DateTimeAgo? = null for ((manga, history) in list) { if (grouped) { @@ -116,16 +112,10 @@ class HistoryListViewModel @Inject constructor( } prevDate = date } - val counter = if (settings.isTrackerEnabled) { - trackingRepository.getNewChaptersCount(manga.id) - } else { - 0 - } - val percent = if (showPercent) history.percent else PROGRESS_NONE result += when (mode) { - ListMode.LIST -> manga.toListModel(counter, percent) - ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent, tagHighlighter) - ListMode.GRID -> manga.toGridModel(counter, percent) + ListMode.LIST -> manga.toListModel(extraProvider) + ListMode.DETAILED_LIST -> manga.toListDetailedModel(extraProvider) + ListMode.GRID -> manga.toGridModel(extraProvider) } } return result diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt index 7c547e0ae..60cc18885 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProvider.kt @@ -1,8 +1,60 @@ package org.koitharu.kotatsu.list.domain -interface ListExtraProvider { +import android.content.Context +import androidx.annotation.ColorRes +import dagger.Reusable +import dagger.hilt.android.qualifiers.ApplicationContext +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.history.data.HistoryRepository +import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.tracker.domain.TrackingRepository +import javax.inject.Inject - suspend fun getCounter(mangaId: Long): Int +@Reusable +class ListExtraProvider @Inject constructor( + @ApplicationContext context: Context, + private val settings: AppSettings, + private val trackingRepository: TrackingRepository, + private val historyRepository: HistoryRepository, +) { - suspend fun getProgress(mangaId: Long): Float -} \ No newline at end of file + private val dict by lazy { + context.resources.openRawResource(R.raw.tags_redlist).use { + val set = HashSet() + it.bufferedReader().forEachLine { x -> + val line = x.trim() + if (line.isNotEmpty()) { + set.add(line) + } + } + set + } + } + + suspend fun getCounter(mangaId: Long): Int { + return if (settings.isTrackerEnabled) { + trackingRepository.getNewChaptersCount(mangaId) + } else { + 0 + } + } + + suspend fun getProgress(mangaId: Long): Float { + return if (settings.isReadingIndicatorsEnabled) { + historyRepository.getProgress(mangaId) + } else { + PROGRESS_NONE + } + } + + @ColorRes + fun getTagTint(tag: MangaTag): Int { + return if (tag.title.lowercase() in dict) { + R.color.warning + } else { + 0 + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProviderImpl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProviderImpl.kt deleted file mode 100644 index c972feb7e..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListExtraProviderImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.koitharu.kotatsu.list.domain - -import dagger.Reusable -import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.data.PROGRESS_NONE -import org.koitharu.kotatsu.tracker.domain.TrackingRepository -import javax.inject.Inject - -@Reusable -class ListExtraProviderImpl @Inject constructor( - private val settings: AppSettings, - private val trackingRepository: TrackingRepository, - private val historyRepository: HistoryRepository, -) : ListExtraProvider { - - override suspend fun getCounter(mangaId: Long): Int { - return if (settings.isTrackerEnabled) { - trackingRepository.getNewChaptersCount(mangaId) - } else { - 0 - } - } - - override suspend fun getProgress(mangaId: Long): Float { - return if (settings.isReadingIndicatorsEnabled) { - historyRepository.getProgress(mangaId) - } else { - PROGRESS_NONE - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt index 172fe3aeb..aa6014626 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.list.ui.model import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.util.ext.ifZero @@ -14,34 +13,31 @@ import org.koitharu.kotatsu.parsers.model.Manga import java.net.SocketTimeoutException import java.net.UnknownHostException -fun Manga.toListModel( - counter: Int, - progress: Float, +suspend fun Manga.toListModel( + extraProvider: ListExtraProvider? ) = MangaListModel( id = id, title = title, subtitle = tags.joinToString(", ") { it.title }, coverUrl = coverUrl, manga = this, - counter = counter, - progress = progress, + counter = extraProvider?.getCounter(id) ?: 0, + progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE, ) -fun Manga.toListDetailedModel( - counter: Int, - progress: Float, - tagHighlighter: MangaTagHighlighter?, +suspend fun Manga.toListDetailedModel( + extraProvider: ListExtraProvider?, ) = MangaListDetailedModel( id = id, title = title, subtitle = altTitle, coverUrl = coverUrl, manga = this, - counter = counter, - progress = progress, + counter = extraProvider?.getCounter(id) ?: 0, + progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE, tags = tags.map { ChipsView.ChipModel( - tint = tagHighlighter?.getTint(it) ?: 0, + tint = extraProvider?.getTagTint(it) ?: 0, title = it.title, icon = 0, isCheckable = false, @@ -51,53 +47,30 @@ fun Manga.toListDetailedModel( }, ) -fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel( +suspend fun Manga.toGridModel( + extraProvider: ListExtraProvider?, +) = MangaGridModel( id = id, title = title, coverUrl = coverUrl, manga = this, - counter = counter, - progress = progress, + counter = extraProvider?.getCounter(id) ?: 0, + progress = extraProvider?.getProgress(id) ?: PROGRESS_NONE, ) suspend fun List.toUi( mode: ListMode, extraProvider: ListExtraProvider, - tagHighlighter: MangaTagHighlighter?, -): List = toUi(ArrayList(size), mode, extraProvider, tagHighlighter) - -fun List.toUi( - mode: ListMode, - tagHighlighter: MangaTagHighlighter?, -): List = toUi(ArrayList(size), mode, tagHighlighter) - -fun > List.toUi( - destination: C, - mode: ListMode, - tagHighlighter: MangaTagHighlighter?, -): C = when (mode) { - ListMode.LIST -> mapTo(destination) { it.toListModel(0, PROGRESS_NONE) } - ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(0, PROGRESS_NONE, tagHighlighter) } - ListMode.GRID -> mapTo(destination) { it.toGridModel(0, PROGRESS_NONE) } -} +): List = toUi(ArrayList(size), mode, extraProvider) suspend fun > List.toUi( destination: C, mode: ListMode, extraProvider: ListExtraProvider, - tagHighlighter: MangaTagHighlighter?, ): C = when (mode) { - ListMode.LIST -> mapTo(destination) { - it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) - } - - ListMode.DETAILED_LIST -> mapTo(destination) { - it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id), tagHighlighter) - } - - ListMode.GRID -> mapTo(destination) { - it.toGridModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) - } + ListMode.LIST -> mapTo(destination) { it.toListModel(extraProvider) } + ListMode.DETAILED_LIST -> mapTo(destination) { it.toListDetailedModel(extraProvider) } + ListMode.GRID -> mapTo(destination) { it.toGridModel(extraProvider) } } fun Throwable.toErrorState(canRetry: Boolean = true) = ErrorState( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt index 65f7a393e..99723036a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListViewModel.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharedFlow import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call @@ -25,7 +24,6 @@ class LocalListViewModel @Inject constructor( savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, filter: FilterCoordinator, - tagHighlighter: MangaTagHighlighter, settings: AppSettings, downloadScheduler: DownloadWorker.Scheduler, listExtraProvider: ListExtraProvider, @@ -35,7 +33,6 @@ class LocalListViewModel @Inject constructor( savedStateHandle, mangaRepositoryFactory, filter, - tagHighlighter, settings, listExtraProvider, downloadScheduler, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt index 130a34233..816c464f7 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListViewModel.kt @@ -18,7 +18,6 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.require @@ -47,7 +46,6 @@ open class RemoteListViewModel @Inject constructor( savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, private val filter: FilterCoordinator, - private val tagHighlighter: MangaTagHighlighter, settings: AppSettings, listExtraProvider: ListExtraProvider, downloadScheduler: DownloadWorker.Scheduler, @@ -72,7 +70,7 @@ open class RemoteListViewModel @Inject constructor( list == null -> add(LoadingState) list.isEmpty() -> add(createEmptyState(header.value.hasSelectedTags)) else -> { - list.toUi(this, mode, listExtraProvider, tagHighlighter) + list.toUi(this, mode, listExtraProvider) when { error != null -> add(error.toErrorFooter()) hasNext -> add(LoadingFooter()) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt index ff7abf11c..a1ad1f52a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/SearchViewModel.kt @@ -13,10 +13,10 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.parser.MangaRepository -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.require import org.koitharu.kotatsu.download.ui.worker.DownloadWorker +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel @@ -33,7 +33,7 @@ class SearchViewModel @Inject constructor( savedStateHandle: SavedStateHandle, repositoryFactory: MangaRepository.Factory, settings: AppSettings, - private val tagHighlighter: MangaTagHighlighter, + private val extraProvider: ListExtraProvider, downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { @@ -64,7 +64,7 @@ class SearchViewModel @Inject constructor( else -> { val result = ArrayList(list.size + 1) - list.toUi(result, mode, tagHighlighter) + list.toUi(result, mode, extraProvider) when { error != null -> result += error.toErrorFooter() hasNext -> result += LoadingFooter() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index 51a273537..f117f6d09 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -25,6 +25,7 @@ import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter @@ -42,6 +43,7 @@ private const val MIN_HAS_MORE_ITEMS = 8 @HiltViewModel class MultiSearchViewModel @Inject constructor( savedStateHandle: SavedStateHandle, + private val extraProvider: ListExtraProvider, private val settings: AppSettings, private val mangaRepositoryFactory: MangaRepository.Factory, private val downloadScheduler: DownloadWorker.Scheduler, @@ -128,7 +130,7 @@ class MultiSearchViewModel @Inject constructor( async(dispatcher) { runCatchingCancellable { val list = mangaRepositoryFactory.create(source).getList(offset = 0, query = q) - .toUi(ListMode.GRID, null) + .toUi(ListMode.GRID, extraProvider) if (list.isNotEmpty()) { MultiSearchListModel(source, list.size > MIN_HAS_MORE_ITEMS, list) } else { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt index 5fa916e1c..b2104c199 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/ShelfContentObserveUseCase.kt @@ -25,6 +25,7 @@ import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject +@Suppress("SameParameterValue") class ShelfContentObserveUseCase @Inject constructor( private val localMangaRepository: LocalMangaRepository, private val historyRepository: HistoryRepository, @@ -35,20 +36,20 @@ class ShelfContentObserveUseCase @Inject constructor( ) { operator fun invoke(): Flow = combine( - historyRepository.observeAllWithHistory(), - observeLocalManga(SortOrder.UPDATED), + historyRepository.observeAll(20), + observeLocalManga(SortOrder.UPDATED, 20), observeFavourites(), trackingRepository.observeUpdatedManga(), - suggestionRepository.observeAll(16), + suggestionRepository.observeAll(20), ) { history, local, favorites, updated, suggestions -> ShelfContent(history, favorites, updated, local, suggestions) } - private fun observeLocalManga(sortOrder: SortOrder): Flow> { + private fun observeLocalManga(sortOrder: SortOrder, limit: Int): Flow> { return localStorageChanges .onStart { emit(null) } .mapLatest { - localMangaRepository.getList(0, null, sortOrder) + localMangaRepository.getList(0, null, sortOrder).take(limit) }.distinctUntilChanged() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt index 3e98c8cd3..39c88010f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/domain/model/ShelfContent.kt @@ -1,13 +1,12 @@ package org.koitharu.kotatsu.shelf.domain.model import org.koitharu.kotatsu.core.model.FavouriteCategory -import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.parsers.model.Manga class ShelfContent( - val history: List, + val history: List, val favourites: Map>, - val updated: Map, + val updated: List, val local: List, val suggestions: List, ) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt index 557801d47..16ea86002 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/shelf/ui/ShelfViewModel.kt @@ -23,8 +23,6 @@ import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.data.PROGRESS_NONE -import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.model.EmptyHint import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -41,21 +39,20 @@ import org.koitharu.kotatsu.shelf.domain.model.ShelfContent import org.koitharu.kotatsu.shelf.domain.model.ShelfSection import org.koitharu.kotatsu.shelf.ui.model.ShelfSectionModel import org.koitharu.kotatsu.sync.domain.SyncController -import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject @HiltViewModel class ShelfViewModel @Inject constructor( private val historyRepository: HistoryRepository, private val favouritesRepository: FavouritesRepository, - private val trackingRepository: TrackingRepository, private val settings: AppSettings, private val downloadScheduler: DownloadWorker.Scheduler, private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase, + private val listExtraProvider: ListExtraProvider, shelfContentObserveUseCase: ShelfContentObserveUseCase, syncController: SyncController, networkState: NetworkState, -) : BaseViewModel(), ListExtraProvider { +) : BaseViewModel() { val onActionDone = MutableEventFlow() val onDownloadStarted = MutableEventFlow() @@ -78,22 +75,6 @@ class ShelfViewModel @Inject constructor( } } - override suspend fun getCounter(mangaId: Long): Int { - return if (settings.isTrackerEnabled) { - trackingRepository.getNewChaptersCount(mangaId) - } else { - 0 - } - } - - override suspend fun getProgress(mangaId: Long): Float { - return if (settings.isReadingIndicatorsEnabled) { - historyRepository.getProgress(mangaId) - } else { - PROGRESS_NONE - } - } - fun removeFromFavourites(category: FavouriteCategory, ids: Set) { if (ids.isEmpty()) { return @@ -194,7 +175,7 @@ class ShelfViewModel @Inject constructor( when (section) { ShelfSection.HISTORY -> mapHistory( result, - content.history.filter { it.manga.source == MangaSource.LOCAL }, + content.history.filter { it.source == MangaSource.LOCAL }, ) ShelfSection.LOCAL -> mapLocal(result, content.local) @@ -222,17 +203,14 @@ class ShelfViewModel @Inject constructor( private suspend fun mapHistory( destination: MutableList, - list: List, + list: List, ) { if (list.isEmpty()) { return } - val showPercent = settings.isReadingIndicatorsEnabled destination += ShelfSectionModel.History( - items = list.map { (manga, history) -> - val counter = getCounter(manga.id) - val percent = if (showPercent) history.percent else PROGRESS_NONE - manga.toGridModel(counter, percent) + items = list.map { manga -> + manga.toGridModel(listExtraProvider) }, showAllButtonText = R.string.show_all, ) @@ -240,16 +218,15 @@ class ShelfViewModel @Inject constructor( private suspend fun mapUpdated( destination: MutableList, - updated: Map, + updated: List, ) { if (updated.isEmpty()) { return } - val showPercent = settings.isReadingIndicatorsEnabled + settings.isReadingIndicatorsEnabled destination += ShelfSectionModel.Updated( - items = updated.map { (manga, counter) -> - val percent = if (showPercent) getProgress(manga.id) else PROGRESS_NONE - manga.toGridModel(counter, percent) + items = updated.map { manga -> + manga.toGridModel(listExtraProvider) }, showAllButtonText = R.string.show_all, ) @@ -263,7 +240,7 @@ class ShelfViewModel @Inject constructor( return } destination += ShelfSectionModel.Local( - items = local.toUi(ListMode.GRID, this, null), + items = local.toUi(ListMode.GRID, listExtraProvider), showAllButtonText = R.string.show_all, ) } @@ -276,7 +253,7 @@ class ShelfViewModel @Inject constructor( return } destination += ShelfSectionModel.Suggestions( - items = suggestions.toUi(ListMode.GRID, this, null), + items = suggestions.toUi(ListMode.GRID, listExtraProvider), showAllButtonText = R.string.show_all, ) } @@ -291,7 +268,7 @@ class ShelfViewModel @Inject constructor( for ((category, list) in favourites) { if (list.isNotEmpty()) { destination += ShelfSectionModel.Favourites( - items = list.toUi(ListMode.GRID, this, null), + items = list.toUi(ListMode.GRID, listExtraProvider), category = category, showAllButtonText = R.string.show_all, ) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt index 5eff7818f..40338a217 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt @@ -10,10 +10,10 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.LoadingState @@ -26,7 +26,7 @@ import javax.inject.Inject class SuggestionsViewModel @Inject constructor( repository: SuggestionRepository, settings: AppSettings, - private val tagHighlighter: MangaTagHighlighter, + private val extraProvider: ListExtraProvider, downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { @@ -44,7 +44,7 @@ class SuggestionsViewModel @Inject constructor( ), ) - else -> list.toUi(mode, tagHighlighter) + else -> list.toUi(mode, extraProvider) } }.onStart { loadingCounter.increment() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt index 0915582a1..bd9b03a83 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/data/TracksDao.kt @@ -34,9 +34,8 @@ abstract class TracksDao { abstract fun observeNewChapters(mangaId: Long): Flow @Transaction - @MapInfo(valueColumn = "chapters_new") - @Query("SELECT manga.*, chapters_new FROM tracks LEFT JOIN manga ON manga.manga_id = tracks.manga_id WHERE chapters_new > 0 ORDER BY chapters_new DESC") - abstract fun observeUpdatedManga(): Flow> + @Query("SELECT manga.* FROM tracks LEFT JOIN manga ON manga.manga_id = tracks.manga_id WHERE chapters_new > 0 ORDER BY chapters_new DESC") + abstract fun observeUpdatedManga(): Flow> @Query("DELETE FROM tracks") abstract suspend fun clear() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt index a6b3b8518..482b25fa1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt @@ -12,6 +12,7 @@ import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.core.util.ext.mapItems import org.koitharu.kotatsu.favourites.data.toFavouriteCategory import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource @@ -44,9 +45,9 @@ class TrackingRepository @Inject constructor( return db.tracksDao.observeNewChapters().map { list -> list.count { it > 0 } } } - fun observeUpdatedManga(): Flow> { + fun observeUpdatedManga(): Flow> { return db.tracksDao.observeUpdatedManga() - .map { x -> x.mapKeys { it.key.toManga() } } + .mapItems { it.toManga() } .distinctUntilChanged() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt index a3dffc059..a8c437c6b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesViewModel.kt @@ -10,22 +10,16 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.parser.MangaTagHighlighter import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.data.PROGRESS_NONE +import org.koitharu.kotatsu.list.domain.ListExtraProvider import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState -import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState -import org.koitharu.kotatsu.list.ui.model.toGridModel -import org.koitharu.kotatsu.list.ui.model.toListDetailedModel -import org.koitharu.kotatsu.list.ui.model.toListModel -import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.tracker.domain.TrackingRepository import javax.inject.Inject @@ -34,16 +28,16 @@ class UpdatesViewModel @Inject constructor( private val repository: TrackingRepository, private val settings: AppSettings, private val historyRepository: HistoryRepository, - private val tagHighlighter: MangaTagHighlighter, + private val extraProvider: ListExtraProvider, downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { override val content = combine( repository.observeUpdatedManga(), listMode, - ) { mangaMap, mode -> + ) { mangaList, mode -> when { - mangaMap.isEmpty() -> listOf( + mangaList.isEmpty() -> listOf( EmptyState( icon = R.drawable.ic_empty_history, textPrimary = R.string.text_history_holder_primary, @@ -52,7 +46,7 @@ class UpdatesViewModel @Inject constructor( ), ) - else -> mapList(mangaMap, mode) + else -> mangaList.toUi(mode, extraProvider) } }.onStart { loadingCounter.increment() @@ -65,19 +59,4 @@ class UpdatesViewModel @Inject constructor( override fun onRefresh() = Unit override fun onRetry() = Unit - - private suspend fun mapList( - mangaMap: Map, - mode: ListMode, - ): List { - val showPercent = settings.isReadingIndicatorsEnabled - return mangaMap.map { (manga, counter) -> - val percent = if (showPercent) historyRepository.getProgress(manga.id) else PROGRESS_NONE - when (mode) { - ListMode.LIST -> manga.toListModel(counter, percent) - ListMode.DETAILED_LIST -> manga.toListDetailedModel(counter, percent, tagHighlighter) - ListMode.GRID -> manga.toGridModel(counter, percent) - } - } - } } From c2ee548f0a091466dabce0ed065546c5dfb60399 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 09:34:56 +0300 Subject: [PATCH 35/90] Show errors in global search results --- .../search/ui/multi/MultiSearchListModel.kt | 7 +-- .../search/ui/multi/MultiSearchViewModel.kt | 54 +++++++------------ .../ui/multi/adapter/SearchResultsAD.kt | 5 ++ app/src/main/res/drawable/ic_error_small.xml | 11 ++++ app/src/main/res/layout/item_list_group.xml | 19 ++++++- 5 files changed, 58 insertions(+), 38 deletions(-) create mode 100644 app/src/main/res/drawable/ic_error_small.xml diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt index f8801ca11..8f6ed856e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchListModel.kt @@ -8,6 +8,7 @@ class MultiSearchListModel( val source: MangaSource, val hasMore: Boolean, val list: List, + val error: Throwable?, ) : ListModel { override fun equals(other: Any?): Boolean { @@ -19,14 +20,14 @@ class MultiSearchListModel( if (source != other.source) return false if (hasMore != other.hasMore) return false if (list != other.list) return false - - return true + return error == other.error } override fun hashCode(): Int { var result = source.hashCode() result = 31 * result + hasMore.hashCode() result = 31 * result + list.hashCode() + result = 31 * result + (error?.hashCode() ?: 0) return result } -} \ No newline at end of file +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt index f117f6d09..2f4615796 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchViewModel.kt @@ -16,8 +16,8 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.plus +import kotlinx.coroutines.withTimeout import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.exceptions.CompositeException import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.ListMode @@ -30,7 +30,6 @@ import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.LoadingFooter import org.koitharu.kotatsu.list.ui.model.LoadingState -import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.runCatchingCancellable @@ -52,20 +51,17 @@ class MultiSearchViewModel @Inject constructor( private var searchJob: Job? = null private val listData = MutableStateFlow>(emptyList()) private val loadingData = MutableStateFlow(false) - private var listError = MutableStateFlow(null) val onDownloadStarted = MutableEventFlow() val query = MutableStateFlow(savedStateHandle.get(MultiSearchActivity.EXTRA_QUERY).orEmpty()) val list: StateFlow> = combine( listData, loadingData, - listError, - ) { list, loading, error -> + ) { list, loading -> when { list.isEmpty() -> listOf( when { loading -> LoadingState - error != null -> error.toErrorState(canRetry = true) else -> EmptyState( icon = R.drawable.ic_empty_common, textPrimary = R.string.nothing_found, @@ -101,15 +97,12 @@ class MultiSearchViewModel @Inject constructor( searchJob = launchJob(Dispatchers.Default) { prevJob?.cancelAndJoin() try { - listError.value = null listData.value = emptyList() loadingData.value = true query.value = q searchImpl(q) } catch (e: CancellationException) { throw e - } catch (e: Throwable) { - listError.value = e } finally { loadingData.value = false } @@ -129,35 +122,28 @@ class MultiSearchViewModel @Inject constructor( val deferredList = sources.map { source -> async(dispatcher) { runCatchingCancellable { - val list = mangaRepositoryFactory.create(source).getList(offset = 0, query = q) - .toUi(ListMode.GRID, extraProvider) - if (list.isNotEmpty()) { - MultiSearchListModel(source, list.size > MIN_HAS_MORE_ITEMS, list) - } else { - null + withTimeout(8_000) { + mangaRepositoryFactory.create(source).getList(offset = 0, query = q) + .toUi(ListMode.GRID, extraProvider) } - }.onFailure { - it.printStackTraceDebug() - } + }.fold( + onSuccess = { list -> + if (list.isEmpty()) { + null + } else { + MultiSearchListModel(source, list.size > MIN_HAS_MORE_ITEMS, list, null) + } + }, + onFailure = { error -> + error.printStackTraceDebug() + MultiSearchListModel(source, true, emptyList(), error) + }, + ) } } - - val errors = ArrayList() for (deferred in deferredList) { - deferred.await() - .onSuccess { item -> - if (item != null) { - listData.update { x -> x + item } - } - }.onFailure { - errors.add(it) - } - } - if (listData.value.isEmpty()) { - when (errors.size) { - 0 -> Unit - 1 -> throw errors[0] - else -> throw CompositeException(errors) + deferred.await()?.let { item -> + listData.update { x -> x + item } } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt index 2fdcf1b90..9bd049052 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/adapter/SearchResultsAD.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.search.ui.multi.adapter +import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.lifecycle.LifecycleOwner import androidx.recyclerview.widget.RecyclerView.RecycledViewPool @@ -10,6 +11,8 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration +import org.koitharu.kotatsu.core.util.ext.getDisplayMessage +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ItemListGroupBinding import org.koitharu.kotatsu.list.ui.ItemSizeResolver import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration @@ -46,5 +49,7 @@ fun searchResultsAD( binding.buttonMore.isVisible = item.hasMore adapter.notifyDataSetChanged() adapter.items = item.list + binding.recyclerView.isGone = item.list.isEmpty() + binding.textViewError.textAndVisible = item.error?.getDisplayMessage(context.resources) } } diff --git a/app/src/main/res/drawable/ic_error_small.xml b/app/src/main/res/drawable/ic_error_small.xml new file mode 100644 index 000000000..964da43cc --- /dev/null +++ b/app/src/main/res/drawable/ic_error_small.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout/item_list_group.xml b/app/src/main/res/layout/item_list_group.xml index 998d7d74e..3a8becad9 100644 --- a/app/src/main/res/layout/item_list_group.xml +++ b/app/src/main/res/layout/item_list_group.xml @@ -47,4 +47,21 @@ android:paddingHorizontal="@dimen/grid_spacing" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> - \ No newline at end of file + + + From 6dc460bc20f93b059cbc2b4deeb4feb4c1d16e6c Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 10:45:23 +0300 Subject: [PATCH 36/90] Replace CloudFlareDialog with activity --- app/src/main/AndroidManifest.xml | 4 + .../kotatsu/browser/BrowserActivity.kt | 1 + .../browser/cloudflare/CloudFlareActivity.kt | 175 ++++++++++++++++++ .../browser/cloudflare/CloudFlareDialog.kt | 123 ------------ .../exceptions/resolve/ExceptionResolver.kt | 45 ++--- .../kotatsu/core/ui/AlertDialogFragment.kt | 1 + .../kotatsu/core/util/TaggedActivityResult.kt | 7 +- .../koitharu/kotatsu/core/util/ext/String.kt | 2 +- .../main/res/layout/fragment_cloudflare.xml | 21 --- 9 files changed, 204 insertions(+), 175 deletions(-) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt delete mode 100644 app/src/main/res/layout/fragment_cloudflare.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10faa7ae2..2a167d459 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -102,6 +102,10 @@ android:name="org.koitharu.kotatsu.browser.BrowserActivity" android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" android:windowSoftInputMode="adjustResize" /> + (), BrowserCallback override fun onDestroy() { super.onDestroy() + viewBinding.webView.stopLoading() viewBinding.webView.destroy() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt new file mode 100644 index 000000000..51d29fc9f --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareActivity.kt @@ -0,0 +1,175 @@ +package org.koitharu.kotatsu.browser.cloudflare + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.MenuItem +import android.webkit.CookieManager +import android.webkit.WebSettings +import androidx.activity.result.contract.ActivityResultContract +import androidx.core.graphics.Insets +import androidx.core.net.toUri +import androidx.core.view.isInvisible +import androidx.core.view.isVisible +import androidx.core.view.updatePadding +import dagger.hilt.android.AndroidEntryPoint +import okhttp3.Headers +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.browser.WebViewBackPressedCallback +import org.koitharu.kotatsu.core.network.CommonHeaders +import org.koitharu.kotatsu.core.network.CommonHeadersInterceptor +import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar +import org.koitharu.kotatsu.core.ui.BaseActivity +import org.koitharu.kotatsu.core.util.TaggedActivityResult +import org.koitharu.kotatsu.core.util.ext.catchingWebViewUnavailability +import org.koitharu.kotatsu.databinding.ActivityBrowserBinding +import javax.inject.Inject +import com.google.android.material.R as materialR + +@AndroidEntryPoint +class CloudFlareActivity : BaseActivity(), CloudFlareCallback { + + private var pendingResult = RESULT_CANCELED + + @Inject + lateinit var cookieJar: MutableCookieJar + + private var onBackPressedCallback: WebViewBackPressedCallback? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (!catchingWebViewUnavailability { setContentView(ActivityBrowserBinding.inflate(layoutInflater)) }) { + return + } + supportActionBar?.run { + setDisplayHomeAsUpEnabled(true) + setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) + } + val url = intent?.dataString.orEmpty() + with(viewBinding.webView.settings) { + javaScriptEnabled = true + cacheMode = WebSettings.LOAD_DEFAULT + domStorageEnabled = true + databaseEnabled = true + userAgentString = intent?.getStringExtra(ARG_UA) ?: CommonHeadersInterceptor.userAgentFallback + } + viewBinding.webView.webViewClient = CloudFlareClient(cookieJar, this, url) + onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView).also { + onBackPressedDispatcher.addCallback(it) + } + CookieManager.getInstance().setAcceptThirdPartyCookies(viewBinding.webView, true) + if (savedInstanceState != null) { + return + } + if (url.isEmpty()) { + finishAfterTransition() + } else { + onTitleChanged(getString(R.string.loading_), url) + viewBinding.webView.loadUrl(url) + } + } + + override fun onDestroy() { + viewBinding.webView.run { + stopLoading() + destroy() + } + super.onDestroy() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + viewBinding.webView.saveState(outState) + } + + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + viewBinding.webView.restoreState(savedInstanceState) + } + + override fun onWindowInsetsChanged(insets: Insets) { + viewBinding.appbar.updatePadding( + top = insets.top, + ) + viewBinding.root.updatePadding( + left = insets.left, + right = insets.right, + bottom = insets.bottom, + ) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { + android.R.id.home -> { + viewBinding.webView.stopLoading() + finishAfterTransition() + true + } + + else -> super.onOptionsItemSelected(item) + } + + override fun onResume() { + super.onResume() + viewBinding.webView.onResume() + } + + override fun onPause() { + viewBinding.webView.onPause() + super.onPause() + } + + override fun finish() { + setResult(pendingResult) + super.finish() + } + + override fun onPageLoaded() { + viewBinding.progressBar.isInvisible = true + } + + override fun onCheckPassed() { + pendingResult = RESULT_OK + finishAfterTransition() + } + + override fun onLoadingStateChanged(isLoading: Boolean) { + viewBinding.progressBar.isVisible = isLoading + } + + override fun onHistoryChanged() { + onBackPressedCallback?.onHistoryChanged() + } + + override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) { + setTitle(title) + supportActionBar?.subtitle = subtitle?.toString()?.toHttpUrlOrNull()?.topPrivateDomain() ?: subtitle + } + + class Contract : ActivityResultContract, TaggedActivityResult>() { + override fun createIntent(context: Context, input: Pair): Intent { + return newIntent(context, input.first, input.second) + } + + override fun parseResult(resultCode: Int, intent: Intent?): TaggedActivityResult { + return TaggedActivityResult(TAG, resultCode) + } + } + + companion object { + + const val TAG = "CloudFlareActivity" + private const val ARG_UA = "ua" + + fun newIntent( + context: Context, + url: String, + headers: Headers?, + ) = Intent(context, CloudFlareActivity::class.java).apply { + data = url.toUri() + headers?.get(CommonHeaders.USER_AGENT)?.let { + putExtra(ARG_UA, it) + } + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt deleted file mode 100644 index 0a1284448..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CloudFlareDialog.kt +++ /dev/null @@ -1,123 +0,0 @@ -package org.koitharu.kotatsu.browser.cloudflare - -import android.content.DialogInterface -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.webkit.CookieManager -import android.webkit.WebSettings -import androidx.appcompat.app.AlertDialog -import androidx.core.view.isInvisible -import androidx.fragment.app.setFragmentResult -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import dagger.hilt.android.AndroidEntryPoint -import okhttp3.Headers -import org.koitharu.kotatsu.browser.WebViewBackPressedCallback -import org.koitharu.kotatsu.core.network.CommonHeaders -import org.koitharu.kotatsu.core.network.CommonHeadersInterceptor -import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar -import org.koitharu.kotatsu.core.ui.AlertDialogFragment -import org.koitharu.kotatsu.core.util.ext.withArgs -import org.koitharu.kotatsu.databinding.FragmentCloudflareBinding -import javax.inject.Inject - -@AndroidEntryPoint -class CloudFlareDialog : AlertDialogFragment(), CloudFlareCallback { - - private lateinit var url: String - private val pendingResult = Bundle(1) - - @Inject - lateinit var cookieJar: MutableCookieJar - - private var onBackPressedCallback: WebViewBackPressedCallback? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - url = requireArguments().getString(ARG_URL).orEmpty() - } - - override fun onCreateViewBinding( - inflater: LayoutInflater, - container: ViewGroup?, - ) = FragmentCloudflareBinding.inflate(inflater, container, false) - - override fun onViewBindingCreated(binding: FragmentCloudflareBinding, savedInstanceState: Bundle?) { - super.onViewBindingCreated(binding, savedInstanceState) - with(binding.webView.settings) { - javaScriptEnabled = true - cacheMode = WebSettings.LOAD_DEFAULT - domStorageEnabled = true - databaseEnabled = true - userAgentString = arguments?.getString(ARG_UA) ?: CommonHeadersInterceptor.userAgentChrome - } - binding.webView.webViewClient = CloudFlareClient(cookieJar, this, url) - CookieManager.getInstance().setAcceptThirdPartyCookies(binding.webView, true) - if (url.isEmpty()) { - dismissAllowingStateLoss() - } else { - binding.webView.loadUrl(url) - } - } - - override fun onDestroyView() { - requireViewBinding().webView.stopLoading() - requireViewBinding().webView.destroy() - onBackPressedCallback = null - super.onDestroyView() - } - - override fun onBuildDialog(builder: MaterialAlertDialogBuilder): MaterialAlertDialogBuilder { - return super.onBuildDialog(builder).setNegativeButton(android.R.string.cancel, null) - } - - override fun onDialogCreated(dialog: AlertDialog) { - super.onDialogCreated(dialog) - onBackPressedCallback = WebViewBackPressedCallback(requireViewBinding().webView).also { - dialog.onBackPressedDispatcher.addCallback(it) - } - } - - override fun onResume() { - super.onResume() - requireViewBinding().webView.onResume() - } - - override fun onPause() { - requireViewBinding().webView.onPause() - super.onPause() - } - - override fun onDismiss(dialog: DialogInterface) { - setFragmentResult(TAG, pendingResult) - super.onDismiss(dialog) - } - - override fun onPageLoaded() { - viewBinding?.progressBar?.isInvisible = true - } - - override fun onCheckPassed() { - pendingResult.putBoolean(EXTRA_RESULT, true) - dismissAllowingStateLoss() - } - - override fun onHistoryChanged() { - onBackPressedCallback?.onHistoryChanged() - } - - companion object { - - const val TAG = "CloudFlareDialog" - const val EXTRA_RESULT = "result" - private const val ARG_URL = "url" - private const val ARG_UA = "ua" - - fun newInstance(url: String, headers: Headers?) = CloudFlareDialog().withArgs(2) { - putString(ARG_URL, url) - headers?.get(CommonHeaders.USER_AGENT)?.let { - putString(ARG_UA, it) - } - } - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt index b5e267dcb..9407ab6e9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/exceptions/resolve/ExceptionResolver.kt @@ -6,15 +6,13 @@ import androidx.annotation.StringRes import androidx.collection.ArrayMap import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity -import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.Headers import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.BrowserActivity -import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog +import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.ui.dialog.ErrorDetailsDialog import org.koitharu.kotatsu.core.util.TaggedActivityResult -import org.koitharu.kotatsu.core.util.isSuccess import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.MangaSource @@ -23,20 +21,26 @@ import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine -class ExceptionResolver private constructor( - private val activity: FragmentActivity?, - private val fragment: Fragment?, -) : ActivityResultCallback { +class ExceptionResolver : ActivityResultCallback { private val continuations = ArrayMap>(1) - private lateinit var sourceAuthContract: ActivityResultLauncher - - constructor(activity: FragmentActivity) : this(activity = activity, fragment = null) { + private val activity: FragmentActivity? + private val fragment: Fragment? + private val sourceAuthContract: ActivityResultLauncher + private val cloudflareContract: ActivityResultLauncher> + + constructor(activity: FragmentActivity) { + this.activity = activity + fragment = null sourceAuthContract = activity.registerForActivityResult(SourceAuthActivity.Contract(), this) + cloudflareContract = activity.registerForActivityResult(CloudFlareActivity.Contract(), this) } - constructor(fragment: Fragment) : this(activity = null, fragment = fragment) { + constructor(fragment: Fragment) { + this.fragment = fragment + activity = null sourceAuthContract = fragment.registerForActivityResult(SourceAuthActivity.Contract(), this) + cloudflareContract = fragment.registerForActivityResult(CloudFlareActivity.Contract(), this) } override fun onActivityResult(result: TaggedActivityResult) { @@ -58,22 +62,9 @@ class ExceptionResolver private constructor( else -> false } - private suspend fun resolveCF(url: String, headers: Headers): Boolean { - val dialog = CloudFlareDialog.newInstance(url, headers) - val fm = getFragmentManager() - return suspendCancellableCoroutine { cont -> - fm.clearFragmentResult(CloudFlareDialog.TAG) - continuations[CloudFlareDialog.TAG] = cont - fm.setFragmentResultListener(CloudFlareDialog.TAG, checkNotNull(fragment ?: activity)) { key, result -> - continuations.remove(key)?.resume(result.getBoolean(CloudFlareDialog.EXTRA_RESULT)) - } - dialog.show(fm, CloudFlareDialog.TAG) - cont.invokeOnCancellation { - continuations.remove(CloudFlareDialog.TAG, cont) - fm.clearFragmentResultListener(CloudFlareDialog.TAG) - dialog.dismissAllowingStateLoss() - } - } + private suspend fun resolveCF(url: String, headers: Headers): Boolean = suspendCoroutine { cont -> + continuations[CloudFlareActivity.TAG] = cont + cloudflareContract.launch(url to headers) } private suspend fun resolveAuthException(source: MangaSource): Boolean = suspendCoroutine { cont -> diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt index 40c091d4d..6809043ef 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/AlertDialogFragment.kt @@ -27,6 +27,7 @@ abstract class AlertDialogFragment : DialogFragment() { .setView(binding.root) .run(::onBuildDialog) .create() + .also(::onDialogCreated) } final override fun onCreateView( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt index 8fba053eb..c55aaa121 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/TaggedActivityResult.kt @@ -5,7 +5,8 @@ import android.app.Activity class TaggedActivityResult( val tag: String, val result: Int, -) +) { -val TaggedActivityResult.isSuccess: Boolean - get() = this.result == Activity.RESULT_OK + val isSuccess: Boolean + get() = result == Activity.RESULT_OK +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt index bc43c656e..e418d1d1b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.util.levenshteinDistance import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.util.UUID -inline fun String?.ifNullOrEmpty(defaultValue: () -> String): String { +inline fun C?.ifNullOrEmpty(defaultValue: () -> C): C { return if (this.isNullOrEmpty()) defaultValue() else this } diff --git a/app/src/main/res/layout/fragment_cloudflare.xml b/app/src/main/res/layout/fragment_cloudflare.xml deleted file mode 100644 index 91a115312..000000000 --- a/app/src/main/res/layout/fragment_cloudflare.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - \ No newline at end of file From 76709dda21d136b623600094b417db95bc9a0922 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 10:57:35 +0300 Subject: [PATCH 37/90] Remove replacement characters from manga description --- .../kotlin/org/koitharu/kotatsu/core/util/ext/String.kt | 6 ++++++ .../org/koitharu/kotatsu/details/ui/DetailsViewModel.kt | 3 ++- .../kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt | 3 ++- .../koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt | 3 ++- .../koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt | 3 ++- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt index e418d1d1b..bc09b90f3 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/String.kt @@ -35,3 +35,9 @@ fun String.almostEquals(other: String, @FloatRange(from = 0.0) threshold: Float) val diff = lowercase().levenshteinDistance(other.lowercase()) / ((length + other.length) / 2f) return diff < threshold } + +fun CharSequence.sanitize(): CharSequence { + return filterNot { c -> c.isReplacement() } +} + +fun Char.isReplacement() = this in '\uFFF0'..'\uFFFF' diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index 0c5c13484..ab56e71f6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -37,6 +37,7 @@ import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.computeSize import org.koitharu.kotatsu.core.util.ext.requireValue +import org.koitharu.kotatsu.core.util.ext.sanitize import org.koitharu.kotatsu.core.util.ext.toFileOrNull import org.koitharu.kotatsu.details.domain.BranchComparator import org.koitharu.kotatsu.details.domain.DetailsInteractor @@ -135,7 +136,7 @@ class DetailsViewModel @Inject constructor( if (description.isNullOrEmpty()) { emit(null) } else { - emit(description.parseAsHtml().filterSpans()) + emit(description.parseAsHtml().filterSpans().sanitize()) emit(description.parseAsHtml(imageGetter = imageGetter).filterSpans()) } }.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.WhileSubscribed(5000), null) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt index 7578154e1..34a5f8332 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt @@ -23,6 +23,7 @@ import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observeEvent +import org.koitharu.kotatsu.core.util.ext.sanitize import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.SheetScrobblingBinding @@ -122,7 +123,7 @@ class ScrobblingInfoSheet : } requireViewBinding().textViewTitle.text = scrobbling.title requireViewBinding().ratingBar.rating = scrobbling.rating * requireViewBinding().ratingBar.numStars - requireViewBinding().textViewDescription.text = scrobbling.description + requireViewBinding().textViewDescription.text = scrobbling.description?.sanitize() requireViewBinding().spinnerStatus.setSelection(scrobbling.status?.ordinal ?: -1) requireViewBinding().imageViewLogo.contentDescription = getString(scrobbling.scrobbler.titleResId) requireViewBinding().imageViewLogo.setImageResource(scrobbling.scrobbler.iconResId) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt index 3cd124561..44251693e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/domain/Scrobbler.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.util.ext.findKeyByValue +import org.koitharu.kotatsu.core.util.ext.sanitize import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.runCatchingCancellable import org.koitharu.kotatsu.scrobbling.common.data.ScrobblingEntity @@ -123,7 +124,7 @@ abstract class Scrobbler( rating = rating, title = mangaInfo.name, coverUrl = mangaInfo.cover, - description = mangaInfo.descriptionHtml.parseAsHtml(), + description = mangaInfo.descriptionHtml.parseAsHtml().sanitize(), externalUrl = mangaInfo.url, ) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index e5770a597..d58db1e4c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -41,6 +41,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.util.ext.almostEquals import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.core.util.ext.flatten +import org.koitharu.kotatsu.core.util.ext.sanitize import org.koitharu.kotatsu.core.util.ext.takeMostFrequent import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull import org.koitharu.kotatsu.core.util.ext.trySetForeground @@ -227,7 +228,7 @@ class SuggestionsWorker @AssistedInject constructor( ).toBitmapOrNull(), ) setSmallIcon(R.drawable.ic_stat_suggestion) - val description = manga.description?.parseAsHtml(HtmlCompat.FROM_HTML_MODE_COMPACT) + val description = manga.description?.parseAsHtml(HtmlCompat.FROM_HTML_MODE_COMPACT)?.sanitize() if (!description.isNullOrBlank()) { val style = NotificationCompat.BigTextStyle() style.bigText( From e794f84c6f83824afc7a0cb2aab368b7a678c78f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 11:52:56 +0300 Subject: [PATCH 38/90] Get rid of SlidingPaneLayout in settings --- .../kotatsu/core/ui/BasePreferenceFragment.kt | 10 ++-- .../kotatsu/settings/SettingsActivity.kt | 44 +++++++++++------ .../settings/SettingsHeadersFragment.kt | 49 ------------------- .../settings/sources/SourcesListFragment.kt | 4 +- .../res/layout-w600dp/activity_settings.xml | 46 +++++++++++++---- app/src/main/res/layout/activity_settings.xml | 3 +- 6 files changed, 74 insertions(+), 82 deletions(-) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt index bfffb7ab3..ce040a63e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt @@ -9,10 +9,10 @@ import androidx.core.view.updatePadding import androidx.preference.PreferenceFragmentCompat import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint +import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate -import org.koitharu.kotatsu.settings.SettingsHeadersFragment import javax.inject.Inject @Suppress("LeakingThis") @@ -56,9 +56,11 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : ) } - @Suppress("UsePropertyAccessSyntax") protected fun setTitle(title: CharSequence) { - (parentFragment as? SettingsHeadersFragment)?.setTitle(title) - ?: activity?.setTitle(title) + activity?.let { + if (!it.resources.getBoolean(R.bool.is_tablet)) { + it.title = title + } + } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt index 9b608aa96..366cd8c5e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt @@ -6,7 +6,9 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import android.view.ViewGroup.MarginLayoutParams import androidx.core.graphics.Insets +import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager @@ -43,10 +45,18 @@ class SettingsActivity : super.onCreate(savedInstanceState) setContentView(ActivitySettingsBinding.inflate(layoutInflater)) supportActionBar?.setDisplayHomeAsUpEnabled(true) - - if (supportFragmentManager.findFragmentById(R.id.container) == null) { + val isMasterDetails = viewBinding.containerMaster != null + val fm = supportFragmentManager + val currentFragment = fm.findFragmentById(R.id.container) + if (currentFragment == null || (isMasterDetails && currentFragment is RootSettingsFragment)) { openDefaultFragment() } + if (isMasterDetails && fm.findFragmentById(R.id.container_master) == null) { + supportFragmentManager.commit { + setReorderingAllowed(true) + replace(R.id.container_master, RootSettingsFragment()) + } + } } override fun onTitleChanged(title: CharSequence?, color: Int) { @@ -90,7 +100,6 @@ class SettingsActivity : } } - @Suppress("DEPRECATION") override fun onPreferenceStartFragment( caller: PreferenceFragmentCompat, pref: Preference, @@ -98,32 +107,35 @@ class SettingsActivity : val fm = supportFragmentManager val fragment = fm.fragmentFactory.instantiate(classLoader, pref.fragment ?: return false) fragment.arguments = pref.extras - fragment.setTargetFragment(caller, 0) - openFragment(fragment) + openFragment(fragment, isFromRoot = caller is RootSettingsFragment) return true } override fun onWindowInsetsChanged(insets: Insets) { - viewBinding.appbar.updatePadding( - left = insets.left, - right = insets.right, - ) - viewBinding.container.updatePadding( + viewBinding.root.updatePadding( left = insets.left, right = insets.right, ) + viewBinding.cardDetails?.updateLayoutParams { + bottomMargin = marginStart + insets.bottom + } } - fun openFragment(fragment: Fragment) { + fun openFragment(fragment: Fragment, isFromRoot: Boolean) { + val hasFragment = supportFragmentManager.findFragmentById(R.id.container) != null + val isMasterDetail = viewBinding.containerMaster != null supportFragmentManager.commit { setReorderingAllowed(true) replace(R.id.container, fragment) - setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) - addToBackStack(null) + setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + if (!isMasterDetail || (hasFragment && !isFromRoot)) { + addToBackStack(null) + } } } private fun openDefaultFragment() { + val hasMaster = viewBinding.containerMaster != null val fragment = when (intent?.action) { ACTION_READER -> ReaderSettingsFragment() ACTION_SUGGESTIONS -> SuggestionsSettingsFragment() @@ -138,12 +150,12 @@ class SettingsActivity : when (intent.data?.host) { HOST_ABOUT -> AboutSettingsFragment() HOST_SYNC_SETTINGS -> SyncSettingsFragment() - else -> SettingsHeadersFragment() + else -> null } } - else -> SettingsHeadersFragment() - } + else -> null + } ?: if (hasMaster) AppearanceSettingsFragment() else RootSettingsFragment() supportFragmentManager.commit { setReorderingAllowed(true) replace(R.id.container, fragment) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt deleted file mode 100644 index 53e1af007..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsHeadersFragment.kt +++ /dev/null @@ -1,49 +0,0 @@ -package org.koitharu.kotatsu.settings - -import android.os.Bundle -import android.view.View -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentTransaction -import androidx.fragment.app.commit -import androidx.preference.PreferenceFragmentCompat -import androidx.preference.PreferenceHeaderFragmentCompat -import androidx.slidingpanelayout.widget.SlidingPaneLayout -import org.koitharu.kotatsu.R - -class SettingsHeadersFragment : PreferenceHeaderFragmentCompat(), SlidingPaneLayout.PanelSlideListener { - - private var currentTitle: CharSequence? = null - - override fun onCreatePreferenceHeader(): PreferenceFragmentCompat = RootSettingsFragment() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - slidingPaneLayout.addPanelSlideListener(this) - } - - override fun onPanelSlide(panel: View, slideOffset: Float) = Unit - - override fun onPanelOpened(panel: View) { - activity?.title = currentTitle ?: getString(R.string.settings) - } - - override fun onPanelClosed(panel: View) { - activity?.setTitle(R.string.settings) - } - - fun setTitle(title: CharSequence?) { - currentTitle = title - if (slidingPaneLayout.width != 0 && slidingPaneLayout.isOpen) { - activity?.title = title - } - } - - fun openFragment(fragment: Fragment) { - childFragmentManager.commit { - setReorderingAllowed(true) - replace(androidx.preference.R.id.preferences_detail, fragment) - setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) - addToBackStack(null) - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt index 12b20babc..18d0f2d97 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourcesListFragment.kt @@ -26,7 +26,6 @@ import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.settings.SettingsActivity -import org.koitharu.kotatsu.settings.SettingsHeadersFragment import org.koitharu.kotatsu.settings.SourceSettingsFragment import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener @@ -90,8 +89,7 @@ class SourcesListFragment : override fun onItemSettingsClick(item: SourceConfigItem.SourceItem) { val fragment = SourceSettingsFragment.newInstance(item.source) - (parentFragment as? SettingsHeadersFragment)?.openFragment(fragment) - ?: (activity as? SettingsActivity)?.openFragment(fragment) + (activity as? SettingsActivity)?.openFragment(fragment, false) } override fun onItemEnabledChanged(item: SourceConfigItem.SourceItem, isEnabled: Boolean) { diff --git a/app/src/main/res/layout-w600dp/activity_settings.xml b/app/src/main/res/layout-w600dp/activity_settings.xml index 642380efc..63aef2083 100644 --- a/app/src/main/res/layout-w600dp/activity_settings.xml +++ b/app/src/main/res/layout-w600dp/activity_settings.xml @@ -1,17 +1,17 @@ - + android:layout_height="match_parent"> + android:id="@+id/container_master" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/card_details" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/appbar" + app:layout_constraintWidth_max="400dp" + app:layout_constraintWidth_min="320dp" + app:layout_constraintWidth_percent="0.35" /> + + + + + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 3b0616df6..459c2008f 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -13,8 +13,9 @@ From bc3a7fc21194ea4d83fd02f63f5c84b04c2a579c Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 12:53:12 +0300 Subject: [PATCH 39/90] Reorganize settings --- .../kotatsu/core/ui/BasePreferenceFragment.kt | 14 +--- .../kotatsu/local/ui/ImportDialogFragment.kt | 8 +- ...agment.kt => DownloadsSettingsFragment.kt} | 71 +---------------- .../settings/NetworkSettingsFragment.kt | 79 +++++++++++++++++++ .../kotatsu/settings/RootSettingsFragment.kt | 2 +- .../settings/ServicesSettingsFragment.kt | 29 ++++++- .../kotatsu/settings/SettingsActivity.kt | 9 ++- ...ragment.kt => UserDataSettingsFragment.kt} | 39 ++++++++- .../settings/backup/BackupDialogFragment.kt | 7 +- .../settings/backup/BackupSettingsFragment.kt | 55 ------------- .../settings/backup/RestoreDialogFragment.kt | 9 ++- app/src/main/res/drawable/ic_data_privacy.xml | 12 +++ app/src/main/res/drawable/ic_services.xml | 4 +- .../res/layout-w600dp/activity_settings.xml | 26 +++++- app/src/main/res/values/strings.xml | 7 ++ app/src/main/res/xml/pref_appearance.xml | 28 ++++--- app/src/main/res/xml/pref_backup.xml | 23 ------ app/src/main/res/xml/pref_downloads.xml | 22 ++++++ .../{pref_content.xml => pref_network.xml} | 63 ++++----------- app/src/main/res/xml/pref_reader.xml | 19 +++-- app/src/main/res/xml/pref_root.xml | 31 +++++--- app/src/main/res/xml/pref_services.xml | 6 ++ .../{pref_history.xml => pref_user_data.xml} | 22 ++++++ 23 files changed, 333 insertions(+), 252 deletions(-) rename app/src/main/kotlin/org/koitharu/kotatsu/settings/{ContentSettingsFragment.kt => DownloadsSettingsFragment.kt} (56%) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/settings/NetworkSettingsFragment.kt rename app/src/main/kotlin/org/koitharu/kotatsu/settings/{HistorySettingsFragment.kt => UserDataSettingsFragment.kt} (84%) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt create mode 100644 app/src/main/res/drawable/ic_data_privacy.xml delete mode 100644 app/src/main/res/xml/pref_backup.xml create mode 100644 app/src/main/res/xml/pref_downloads.xml rename app/src/main/res/xml/{pref_content.xml => pref_network.xml} (54%) rename app/src/main/res/xml/{pref_history.xml => pref_user_data.xml} (73%) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt index ce040a63e..23fef7433 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/BasePreferenceFragment.kt @@ -9,10 +9,10 @@ import androidx.core.view.updatePadding import androidx.preference.PreferenceFragmentCompat import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.WindowInsetsDelegate +import org.koitharu.kotatsu.settings.SettingsActivity import javax.inject.Inject @Suppress("LeakingThis") @@ -44,9 +44,7 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : override fun onResume() { super.onResume() - if (titleId != 0) { - setTitle(getString(titleId)) - } + setTitle(if (titleId != 0) getString(titleId) else null) } @CallSuper @@ -56,11 +54,7 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : ) } - protected fun setTitle(title: CharSequence) { - activity?.let { - if (!it.resources.getBoolean(R.bool.is_tablet)) { - it.title = title - } - } + protected fun setTitle(title: CharSequence?) { + (activity as? SettingsActivity)?.setSectionTitle(title) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt index 6ff59f3a3..7436ccc65 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/ImportDialogFragment.kt @@ -12,7 +12,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.AlertDialogFragment import org.koitharu.kotatsu.databinding.DialogImportBinding -import org.koitharu.kotatsu.settings.backup.BackupDialogFragment import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment class ImportDialogFragment : AlertDialogFragment(), View.OnClickListener { @@ -64,9 +63,10 @@ class ImportDialogFragment : AlertDialogFragment(), View.On } private fun restoreBackup(uri: Uri?) { - RestoreDialogFragment.newInstance(uri ?: return) - .show(parentFragmentManager, BackupDialogFragment.TAG) - dismiss() + if (uri != null) { + RestoreDialogFragment.show(parentFragmentManager, uri) + dismiss() + } } companion object { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/DownloadsSettingsFragment.kt similarity index 56% rename from app/src/main/kotlin/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/DownloadsSettingsFragment.kt index 9e9091beb..151de74e5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ContentSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/DownloadsSettingsFragment.kt @@ -3,67 +3,42 @@ package org.koitharu.kotatsu.settings import android.content.SharedPreferences import android.os.Bundle import android.view.View -import androidx.preference.ListPreference import androidx.preference.Preference -import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.cache.ContentCache -import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.BasePreferenceFragment import org.koitharu.kotatsu.core.ui.dialog.StorageSelectDialog import org.koitharu.kotatsu.core.util.ext.getStorageName -import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.local.data.LocalStorageManager -import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.util.ext.printStackTraceDebug import java.io.File -import java.net.Proxy import javax.inject.Inject @AndroidEntryPoint -class ContentSettingsFragment : - BasePreferenceFragment(R.string.content), +class DownloadsSettingsFragment : + BasePreferenceFragment(R.string.downloads), SharedPreferences.OnSharedPreferenceChangeListener, StorageSelectDialog.OnStorageSelectListener { @Inject lateinit var storageManager: LocalStorageManager - @Inject - lateinit var contentCache: ContentCache - @Inject lateinit var downloadsScheduler: DownloadWorker.Scheduler override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - addPreferencesFromResource(R.xml.pref_content) - findPreference(AppSettings.KEY_PREFETCH_CONTENT)?.isVisible = contentCache.isCachingEnabled - findPreference(AppSettings.KEY_DOH)?.run { - entryValues = arrayOf( - DoHProvider.NONE, - DoHProvider.GOOGLE, - DoHProvider.CLOUDFLARE, - DoHProvider.ADGUARD, - ).names() - setDefaultValueCompat(DoHProvider.NONE.name) - } + addPreferencesFromResource(R.xml.pref_downloads) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) findPreference(AppSettings.KEY_LOCAL_STORAGE)?.bindStorageName() - findPreference(AppSettings.KEY_SUGGESTIONS)?.setSummary( - if (settings.isSuggestionsEnabled) R.string.enabled else R.string.disabled, - ) - bindRemoteSourcesSummary() - bindProxySummary() settings.subscribe(this) } @@ -78,29 +53,9 @@ class ContentSettingsFragment : findPreference(key)?.bindStorageName() } - AppSettings.KEY_SUGGESTIONS -> { - findPreference(AppSettings.KEY_SUGGESTIONS)?.setSummary( - if (settings.isSuggestionsEnabled) R.string.enabled else R.string.disabled, - ) - } - - AppSettings.KEY_SOURCES_HIDDEN -> { - bindRemoteSourcesSummary() - } - AppSettings.KEY_DOWNLOADS_WIFI -> { updateDownloadsConstraints() } - - AppSettings.KEY_SSL_BYPASS -> { - Snackbar.make(listView, R.string.settings_apply_restart_required, Snackbar.LENGTH_INDEFINITE).show() - } - - AppSettings.KEY_PROXY_TYPE, - AppSettings.KEY_PROXY_ADDRESS, - AppSettings.KEY_PROXY_PORT -> { - bindProxySummary() - } } } @@ -131,26 +86,6 @@ class ContentSettingsFragment : } } - private fun bindRemoteSourcesSummary() { - findPreference(AppSettings.KEY_REMOTE_SOURCES)?.run { - val total = settings.remoteMangaSources.size - summary = getString(R.string.enabled_d_of_d, total - settings.hiddenSources.size, total) - } - } - - private fun bindProxySummary() { - findPreference(AppSettings.KEY_PROXY)?.run { - val type = settings.proxyType - val address = settings.proxyAddress - val port = settings.proxyPort - summary = if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { - context.getString(R.string.disabled) - } else { - "$address:$port" - } - } - } - private fun updateDownloadsConstraints() { val preference = findPreference(AppSettings.KEY_DOWNLOADS_WIFI) viewLifecycleScope.launch { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/NetworkSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/NetworkSettingsFragment.kt new file mode 100644 index 000000000..48d6f6407 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/NetworkSettingsFragment.kt @@ -0,0 +1,79 @@ +package org.koitharu.kotatsu.settings + +import android.content.SharedPreferences +import android.os.Bundle +import android.view.View +import androidx.preference.ListPreference +import androidx.preference.Preference +import com.google.android.material.snackbar.Snackbar +import dagger.hilt.android.AndroidEntryPoint +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.cache.ContentCache +import org.koitharu.kotatsu.core.network.DoHProvider +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.ui.BasePreferenceFragment +import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat +import org.koitharu.kotatsu.parsers.util.names +import java.net.Proxy +import javax.inject.Inject + +@AndroidEntryPoint +class NetworkSettingsFragment : + BasePreferenceFragment(R.string.network), + SharedPreferences.OnSharedPreferenceChangeListener { + + @Inject + lateinit var contentCache: ContentCache + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.pref_network) + findPreference(AppSettings.KEY_PREFETCH_CONTENT)?.isVisible = contentCache.isCachingEnabled + findPreference(AppSettings.KEY_DOH)?.run { + entryValues = arrayOf( + DoHProvider.NONE, + DoHProvider.GOOGLE, + DoHProvider.CLOUDFLARE, + DoHProvider.ADGUARD, + ).names() + setDefaultValueCompat(DoHProvider.NONE.name) + } + bindProxySummary() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + settings.subscribe(this) + } + + override fun onDestroyView() { + settings.unsubscribe(this) + super.onDestroyView() + } + + override fun onSharedPreferenceChanged(prefs: SharedPreferences?, key: String?) { + when (key) { + AppSettings.KEY_SSL_BYPASS -> { + Snackbar.make(listView, R.string.settings_apply_restart_required, Snackbar.LENGTH_INDEFINITE).show() + } + + AppSettings.KEY_PROXY_TYPE, + AppSettings.KEY_PROXY_ADDRESS, + AppSettings.KEY_PROXY_PORT -> { + bindProxySummary() + } + } + } + + private fun bindProxySummary() { + findPreference(AppSettings.KEY_PROXY)?.run { + val type = settings.proxyType + val address = settings.proxyAddress + val port = settings.proxyPort + summary = if (type == Proxy.Type.DIRECT || address.isNullOrEmpty() || port == 0) { + context.getString(R.string.disabled) + } else { + "$address:$port" + } + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt index 7d737ee50..e3c64b76e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/RootSettingsFragment.kt @@ -4,7 +4,7 @@ import android.os.Bundle import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BasePreferenceFragment -class RootSettingsFragment : BasePreferenceFragment(R.string.settings) { +class RootSettingsFragment : BasePreferenceFragment(0) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_root) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt index 04bbd96ad..7e1409c9d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/ServicesSettingsFragment.kt @@ -3,8 +3,10 @@ package org.koitharu.kotatsu.settings import android.accounts.AccountManager import android.content.ActivityNotFoundException import android.content.Intent +import android.content.SharedPreferences import android.net.Uri import android.os.Bundle +import android.view.View import androidx.preference.Preference import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint @@ -27,7 +29,8 @@ import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @AndroidEntryPoint -class ServicesSettingsFragment : BasePreferenceFragment(R.string.services) { +class ServicesSettingsFragment : BasePreferenceFragment(R.string.services), + SharedPreferences.OnSharedPreferenceChangeListener { @Inject lateinit var shikimoriRepository: ShikimoriRepository @@ -43,6 +46,17 @@ class ServicesSettingsFragment : BasePreferenceFragment(R.string.services) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_services) + bindSuggestionsSummary() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + settings.subscribe(this) + } + + override fun onDestroyView() { + settings.unsubscribe(this) + super.onDestroyView() } override fun onResume() { @@ -53,6 +67,13 @@ class ServicesSettingsFragment : BasePreferenceFragment(R.string.services) { bindSyncSummary() } + override fun onSharedPreferenceChanged(prefs: SharedPreferences?, key: String?) { + when (key) { + AppSettings.KEY_SUGGESTIONS -> bindSuggestionsSummary() + } + } + + override fun onPreferenceTreeClick(preference: Preference): Boolean { return when (preference.key) { AppSettings.KEY_SHIKIMORI -> { @@ -156,4 +177,10 @@ class ServicesSettingsFragment : BasePreferenceFragment(R.string.services) { findPreference(AppSettings.KEY_SYNC_SETTINGS)?.isEnabled = account != null } } + + private fun bindSuggestionsSummary() { + findPreference(AppSettings.KEY_SUGGESTIONS)?.setSummary( + if (settings.isSuggestionsEnabled) R.string.enabled else R.string.disabled, + ) + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt index 366cd8c5e..ce3731f83 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/SettingsActivity.kt @@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.core.util.ext.isScrolledToTop +import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.databinding.ActivitySettingsBinding import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.parsers.model.MangaSource @@ -121,6 +122,12 @@ class SettingsActivity : } } + fun setSectionTitle(title: CharSequence?) { + viewBinding.textViewHeader?.apply { + textAndVisible = title + } ?: setTitle(title ?: getString(R.string.settings)) + } + fun openFragment(fragment: Fragment, isFromRoot: Boolean) { val hasFragment = supportFragmentManager.findFragmentById(R.id.container) != null val isMasterDetail = viewBinding.containerMaster != null @@ -139,7 +146,7 @@ class SettingsActivity : val fragment = when (intent?.action) { ACTION_READER -> ReaderSettingsFragment() ACTION_SUGGESTIONS -> SuggestionsSettingsFragment() - ACTION_HISTORY -> HistorySettingsFragment() + ACTION_HISTORY -> UserDataSettingsFragment() ACTION_TRACKER -> TrackerSettingsFragment() ACTION_SOURCE -> SourceSettingsFragment.newInstance( intent.getSerializableExtraCompat(EXTRA_SOURCE) as? MangaSource ?: MangaSource.LOCAL, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/UserDataSettingsFragment.kt similarity index 84% rename from app/src/main/kotlin/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt rename to app/src/main/kotlin/org/koitharu/kotatsu/settings/UserDataSettingsFragment.kt index 34b2fdb37..c21c4571d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/UserDataSettingsFragment.kt @@ -1,7 +1,11 @@ package org.koitharu.kotatsu.settings +import android.content.ActivityNotFoundException +import android.net.Uri import android.os.Bundle import android.view.View +import androidx.activity.result.ActivityResultCallback +import androidx.activity.result.contract.ActivityResultContracts import androidx.lifecycle.Lifecycle import androidx.preference.Preference import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -24,11 +28,14 @@ import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.local.data.CacheDir import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.search.domain.MangaSearchRepository +import org.koitharu.kotatsu.settings.backup.BackupDialogFragment +import org.koitharu.kotatsu.settings.backup.RestoreDialogFragment import org.koitharu.kotatsu.tracker.domain.TrackingRepository +import org.koitharu.kotatsu.util.ext.printStackTraceDebug import javax.inject.Inject @AndroidEntryPoint -class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cache) { +class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privacy), ActivityResultCallback { @Inject lateinit var trackerRepo: TrackingRepository @@ -48,8 +55,13 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach @Inject lateinit var shortcutsUpdater: ShortcutsUpdater + private val backupSelectCall = registerForActivityResult( + ActivityResultContracts.OpenDocument(), + this, + ) + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - addPreferencesFromResource(R.xml.pref_history) + addPreferencesFromResource(R.xml.pref_user_data) findPreference(AppSettings.KEY_SHORTCUTS)?.isVisible = shortcutsUpdater.isDynamicShortcutsAvailable() } @@ -116,10 +128,33 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach true } + AppSettings.KEY_BACKUP -> { + BackupDialogFragment.show(childFragmentManager) + true + } + + AppSettings.KEY_RESTORE -> { + try { + backupSelectCall.launch(arrayOf("*/*")) + } catch (e: ActivityNotFoundException) { + e.printStackTraceDebug() + Snackbar.make( + listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT, + ).show() + } + true + } + else -> super.onPreferenceTreeClick(preference) } } + override fun onActivityResult(result: Uri?) { + if (result != null) { + RestoreDialogFragment.show(childFragmentManager, result) + } + } + private fun clearCache(preference: Preference, cache: CacheDir) { val ctx = preference.context.applicationContext viewLifecycleScope.launch { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt index 1a93c12d9..caf25f180 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupDialogFragment.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.isVisible +import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint @@ -101,6 +102,10 @@ class BackupDialogFragment : AlertDialogFragment() { companion object { - const val TAG = "BackupDialogFragment" + private const val TAG = "BackupDialogFragment" + + fun show(fm: FragmentManager) { + BackupDialogFragment().show(fm, TAG) + } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt deleted file mode 100644 index fbeb28594..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/BackupSettingsFragment.kt +++ /dev/null @@ -1,55 +0,0 @@ -package org.koitharu.kotatsu.settings.backup - -import android.content.ActivityNotFoundException -import android.net.Uri -import android.os.Bundle -import androidx.activity.result.ActivityResultCallback -import androidx.activity.result.contract.ActivityResultContracts -import androidx.preference.Preference -import com.google.android.material.snackbar.Snackbar -import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.prefs.AppSettings -import org.koitharu.kotatsu.core.ui.BasePreferenceFragment -import org.koitharu.kotatsu.util.ext.printStackTraceDebug - -class BackupSettingsFragment : - BasePreferenceFragment(R.string.backup_restore), - ActivityResultCallback { - - private val backupSelectCall = registerForActivityResult( - ActivityResultContracts.OpenDocument(), - this, - ) - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - addPreferencesFromResource(R.xml.pref_backup) - } - - override fun onPreferenceTreeClick(preference: Preference): Boolean { - return when (preference.key) { - AppSettings.KEY_BACKUP -> { - BackupDialogFragment().show(childFragmentManager, BackupDialogFragment.TAG) - true - } - - AppSettings.KEY_RESTORE -> { - try { - backupSelectCall.launch(arrayOf("*/*")) - } catch (e: ActivityNotFoundException) { - e.printStackTraceDebug() - Snackbar.make( - listView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT, - ).show() - } - true - } - - else -> super.onPreferenceTreeClick(preference) - } - } - - override fun onActivityResult(result: Uri?) { - RestoreDialogFragment.newInstance(result ?: return) - .show(childFragmentManager, BackupDialogFragment.TAG) - } -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt index f2d0b200e..c697a63fa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/backup/RestoreDialogFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible +import androidx.fragment.app.FragmentManager import androidx.fragment.app.viewModels import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint @@ -87,10 +88,12 @@ class RestoreDialogFragment : AlertDialogFragment() { companion object { const val ARG_FILE = "file" - const val TAG = "RestoreDialogFragment" + private const val TAG = "RestoreDialogFragment" - fun newInstance(uri: Uri) = RestoreDialogFragment().withArgs(1) { - putString(ARG_FILE, uri.toString()) + fun show(fm: FragmentManager, uri: Uri) { + RestoreDialogFragment().withArgs(1) { + putString(ARG_FILE, uri.toString()) + }.show(fm, TAG) } } } diff --git a/app/src/main/res/drawable/ic_data_privacy.xml b/app/src/main/res/drawable/ic_data_privacy.xml new file mode 100644 index 000000000..0697d42ee --- /dev/null +++ b/app/src/main/res/drawable/ic_data_privacy.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_services.xml b/app/src/main/res/drawable/ic_services.xml index fe6404dbc..593c9666c 100644 --- a/app/src/main/res/drawable/ic_services.xml +++ b/app/src/main/res/drawable/ic_services.xml @@ -2,10 +2,10 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" - android:tint="?attr/colorControlNormal" + android:tint="?colorControlNormal" android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M22,13.5C22,15.26 20.7,16.72 19,16.96V20A2,2 0 0,1 17,22H13.2V21.7A2.7,2.7 0 0,0 10.5,19C9,19 7.8,20.21 7.8,21.7V22H4A2,2 0 0,1 2,20V16.2H2.3C3.79,16.2 5,15 5,13.5C5,12 3.79,10.8 2.3,10.8H2V7A2,2 0 0,1 4,5H7.04C7.28,3.3 8.74,2 10.5,2C12.26,2 13.72,3.3 13.96,5H17A2,2 0 0,1 19,7V10.04C20.7,10.28 22,11.74 22,13.5M17,15H18.5A1.5,1.5 0 0,0 20,13.5A1.5,1.5 0 0,0 18.5,12H17V7H12V5.5A1.5,1.5 0 0,0 10.5,4A1.5,1.5 0 0,0 9,5.5V7H4V9.12C5.76,9.8 7,11.5 7,13.5C7,15.5 5.75,17.2 4,17.88V20H6.12C6.8,18.25 8.5,17 10.5,17C12.5,17 14.2,18.25 14.88,20H17V15Z" /> diff --git a/app/src/main/res/layout-w600dp/activity_settings.xml b/app/src/main/res/layout-w600dp/activity_settings.xml index 63aef2083..bbbd8dadf 100644 --- a/app/src/main/res/layout-w600dp/activity_settings.xml +++ b/app/src/main/res/layout-w600dp/activity_settings.xml @@ -2,6 +2,7 @@ @@ -50,10 +51,29 @@ app:layout_constraintStart_toEndOf="@id/container_master" app:layout_constraintTop_toBottomOf="@id/appbar"> - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5dad409f3..bd61d47ac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -433,4 +433,11 @@ Password Authorization (optional) Invalid port number + Network + Data and privacy + Restore previously created backup + Allow zoom in gesture in webtoon mode + Show the current time and reading progress at the top of the screen + Show page numbers in bottom corner + Animate page switching diff --git a/app/src/main/res/xml/pref_appearance.xml b/app/src/main/res/xml/pref_appearance.xml index 5f2058cee..ead9e176a 100644 --- a/app/src/main/res/xml/pref_appearance.xml +++ b/app/src/main/res/xml/pref_appearance.xml @@ -3,6 +3,11 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> + + - - + + + + + + - - + android:title="@string/exit_confirmation" /> diff --git a/app/src/main/res/xml/pref_backup.xml b/app/src/main/res/xml/pref_backup.xml deleted file mode 100644 index 7fc94bcba..000000000 --- a/app/src/main/res/xml/pref_backup.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/pref_downloads.xml b/app/src/main/res/xml/pref_downloads.xml new file mode 100644 index 000000000..82554d8b9 --- /dev/null +++ b/app/src/main/res/xml/pref_downloads.xml @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/app/src/main/res/xml/pref_content.xml b/app/src/main/res/xml/pref_network.xml similarity index 54% rename from app/src/main/res/xml/pref_content.xml rename to app/src/main/res/xml/pref_network.xml index ccf022e00..2d3bd6e38 100644 --- a/app/src/main/res/xml/pref_content.xml +++ b/app/src/main/res/xml/pref_network.xml @@ -4,22 +4,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> - - - - - - + + + + - - - - - - - - - - - - - + diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index 525a46202..a078e2928 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -19,8 +19,15 @@ android:entries="@array/zoom_modes" android:key="zoom_mode" android:title="@string/scale_mode" + app:allowDividerAbove="true" app:useSimpleSummaryProvider="true" /> + + - - + android:summary="@string/reader_info_bar_summary" + android:title="@string/reader_info_bar" + app:allowDividerAbove="true" /> - - + android:title="@string/remote_sources" /> + android:fragment="org.koitharu.kotatsu.settings.NetworkSettingsFragment" + android:icon="@drawable/ic_web" + android:title="@string/network" /> + + + + + android:fragment="org.koitharu.kotatsu.settings.ServicesSettingsFragment" + android:icon="@drawable/ic_services" + android:title="@string/services" /> + + + + + + + + + + + + Date: Mon, 5 Jun 2023 11:53:35 +0200 Subject: [PATCH 40/90] Translated using Weblate (Belarusian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (416 of 416 strings) Co-authored-by: Макар Разин Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/ Translation: Kotatsu/Strings --- app/src/main/res/values-be/strings.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 33e0b519d..8c17722f5 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -45,7 +45,7 @@ Тэма Светлая Цёмная - Аўтаматычна + Як у сістэме Старонкi Ачысціць Вы ўпэўненыя, што жадаеце ачысціць гісторыю\? @@ -136,8 +136,8 @@ Падагнаць па вышыні Падагнаць па шырыні Зыходны памер - Чорная цёмная тэма - Карысна для AMOLED экранаў + Чорная + Спажывае менш энергіі на экранах AMOLED Рэзервовае капіяванне і аднаўленне Стварыць рэзервовую копію Аднавіць данныя @@ -412,4 +412,9 @@ Спампоўкі былі адменены Пераклады WebView недаступны: праверце, ці ўсталяваны пастаўшчык WebView + Тып + Адрас + Порт + Проксі + Ачысціць сеткавы кэш \ No newline at end of file From cd8381cbfb8867d097649882f69f860c87b7b23b Mon Sep 17 00:00:00 2001 From: "J. Lavoie" Date: Mon, 5 Jun 2023 11:53:36 +0200 Subject: [PATCH 41/90] Translated using Weblate (French) Currently translated at 100.0% (416 of 416 strings) Co-authored-by: J. Lavoie Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translation: Kotatsu/Strings --- app/src/main/res/values-fr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ef3ad9f8a..758eedf94 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -410,4 +410,6 @@ Les téléchargements ont été supprimés Les téléchargements ont été annulés Voulez-vous recevoir des suggestions de mangas personnalisées \? + WebView non disponible : vérifier si le fournisseur WebView est installé + Traductions \ No newline at end of file From ae5cebd42df20b215839ef40498e6455a5c82dce Mon Sep 17 00:00:00 2001 From: kuragehime Date: Mon, 5 Jun 2023 11:53:36 +0200 Subject: [PATCH 42/90] Translated using Weblate (Japanese) Currently translated at 100.0% (431 of 431 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (427 of 427 strings) Translated using Weblate (Japanese) Currently translated at 91.8% (382 of 416 strings) Co-authored-by: kuragehime Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/ Translation: Kotatsu/Strings --- app/src/main/res/values-ja/strings.xml | 802 +++++++++++++------------ 1 file changed, 427 insertions(+), 375 deletions(-) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 8b9bc139c..65274a235 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,378 +1,430 @@ - 履歴 - ロード中… - チャプター %1$d of %2$d - 共有 - 履歴を削除 - 検索 - 漫画を検索 - 閉じる - お気に入り - エラーが発生しました - 詳細 - - リスト - 詳細リスト - グリッド - リストモード - リモートソース - 再試行 - 何も見つかりませんでした - まだ履歴はありません - 読む - お気に入りの本はありません - お気に入りの本 - 新たなカテゴリー - 追加 - 保存 - ショートカットを作成します… - 共有する%s - ダウンロード中… - 処理中… - ダウンロードした本 - ダウンロード - 名前 - 人気 - ローカルストレージ - 最新 - 評価 - ソート順に並べ替え - フォローシステム - クリア - すべての履歴を永久にクリアしますか? - 削除 - 「%s 」がローカルストレージから削除されました - ページを保存 - 保存しました - 画像を共有する - インポート - 消去 - この操作はサポートされていません - 説明がありません - 履歴とキャッシュ - ページのキャッシュをクリアする - B|kB|MB|GB|TB - 設定 - ライトテーマ - フィルター - ダークテーマ - ページ - テーマ - ネットワークエラー - アップデート - ZIPファイルまたはCBZファイルを選択してください。 - 標準 - ウェブトゥーン - 読み取りモード - グリッドのサイズ - %sで検索 - 漫画を削除 - お使いのデバイスから「%s」を完全に削除しますか? - リーダーの設定 - ページを変更 - エッジタップ - ボリュームボタン - 続ける - エラー - サムネイルキャッシュをクリア - クリア - ジェスチャーのみ - 内部ストレージ - ドメイン - ブラウザーで開く - この漫画には%sがあります。 すべて保存しますか? - 保存 - 通知 - %2$dの%1$d - 新しいチャプター - ダウンロード - 通知の設定 - 通知音 - LEDインジケータ - バイブレーション - お気に入りのカテゴリー - 削除 - クエリを再定式化してみてください。 - 読んだ内容がここに表示されます - サイドメニューで何を読むかを見つけてください。 - 最初に何かを保存する - 本棚 - 最近 - ページアニメーション - ダウンロード用のフォルダ - 利用出来ません - 使用可能なストレージがありません - その他のストレージ - 完了 - 全てのお気に入り - 後で読む - 更新 - あなたが読んでいるものの新しいチャプターがここに示されています - の検索結果 - サイズ:%s - 更新フィードをクリア - クリア - アップデート - フィードの更新はまもなく開始されます - アップデートを確認 - チェックしない - Kotatsuを起動したときにパスワードを入力する - パスワードを繰り返す - パスワードが違います - この本の詳細 - 現在のバージョン%s - 検索履歴をクリア - 外部ストレージ - Kotatsuの新しい更新が利用可能です - ここは空っぽです… - 空のカテゴリー - オンラインソースから保存するかファイルをインポートします。 - 新しいバージョン:%s - 画面を回転させる - パスワードを入力してください - パスワードが間違っています - アプリを保護する - 最新のアップデートを確認する - 利用可能なアップデートはありません - 右から左 - 承認済み - %sへのログインはサポートされていません - 完成 - 進行中 - デフォルト - ナンバリングページ - 使用したソース - 利用可能なソース - 新しいカテゴリー - 高さを合わせる - チャプターがありません - すべての更新履歴を完全に消去しますか? - この不足した章をダウンロードしたり、オンラインで読んだりすることができます。 - このコンテンツを表示するにはサインインしてください - ファイルが見つかりません - パスワードは4文字以上である必要があります - ちょうど今 - ずっと前 - バックアップを保存 - グループ - フィードをクリア - バックアップから復元 - 確認 - 履歴とお気に入りのバックアップを作成して復元できます - 続きを読む - ブラック - データは復元されましたがエラーが発生しました - 最近の検索クエリを全て完全に削除しますか? - 幅を合わせる - 新しいチャプターを探しています - アプリを起動するためのパスワードを入力してください - データバックアップを作成 - 解決しました - タップして再試行してください - CAPTCHAが必要です - デフォルト:%s - 昨日 - このアプリを翻訳 - 全てのデータが復元されました - 復元 - 準備中… - 開始時に維持 - バックアップと復元 - リバース - 選択した構成はこの漫画のために記憶されます - クッキーを削除 - フィットセンター - 全てのソースからログアウトされます - NSFW漫画を履歴から除外する - キュー - 全てのCookieが削除されました - 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 - ジャンル - スケールモード - 今日 - Kotatsuを翻訳する(Weblateのサイトに移動します) - 次のページ - サイレント - サインイン - ようこそ - AMOLEDスクリーンでさらに少ない電力を使用 - コンピューティング… - 許可する - 常にブロック - スクリーンショットポリシー - NSFWでブロック - 提案 - すべてのデータは、このデバイス上でローカルに分析されます。お客様のデータが他のサービスに転送されることはありません - サジェスト機能を有効 - あなたの好みに合わせて漫画を提案 - ジャンルリストを読み込めません - 無効 - マンガを読み始めると、個人的な提案を受けることができます - 有効 - NSFWのマンガを提案しない - フィルターをリセット - ジャンルを探す - Wi-Fiのみ使用 - 決して - 漫画を読みたい言語を選択します。後で設定から変更することができます。 - 常に - ページのプリロード - %sとしてログイン - 18歳以上 - さまざまな言語 - チャプターを検索 - この漫画の章はありません - %1$s%% - コンテンツ - 更新のご提案 - 外観 - ジャンルを除く - サジェストで表示したくないジャンルを指定 - 選択した項目をデバイスから完全に削除しますか? - 削除が完了しました - IPアドレスのブロックを回避することができます - 保存されたマンガの処理 - ダウンロードの速度低下 - チャプターはバックグラウンドで削除されます。時間がかかる場合があります - 隠す - 新しいマンガソースが利用可能です - 新着チャプターの確認とお知らせ - 読んでいるマンガの更新情報をお知らせします - 通知を有効にする - 通知はありませんが、新しいチャプターはリストでハイライト表示されます - 名称 - 編集 - カテゴリーを編集する - お気に入りのカテゴリーはありません - ブックマーク - ブックマーク削除 - 元に戻す - 履歴から削除 - ブックマークの追加 - ブックマークの削除 - ブックマークを追加 - HTTPS 経由の DNS - リーダーモードの自動検出 - デフォルトモード - マンガがウェブトゥーンかどうかを自動判定 - バッテリー最適化の無効化 - バックグラウンドの更新チェックを支援 - 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 - 送信 - すべて無効にする - 最近読んだ漫画 - 指紋がある場合は、指紋を使用する - お気に入りの漫画 - 報告 - 読書 - 再読込 - 完了 - 保留中 - 追跡 - ログアウト - 予定 - ドロップ - データの削除 - 履歴とお気に入りに既読率を表示する - いくつかの問題の場合に助けることができる。すべての認証が無効になります - 読書の進行状況インジケーターを表示 - NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない - すべて表示 - 無効なドメイン - 範囲を選択 - コンテンツが見つからない、または削除された - 管理 - ランダム - 選択したお気に入りカテゴリを本当に削除してもよいですか? + 履歴 + ロード中… + チャプター %1$d of %2$d + 共有 + 履歴を削除 + 検索 + 漫画を検索 + 閉じる + お気に入り + エラーが発生しました + 詳細 + + リスト + 詳細リスト + グリッド + リストモード + マンガのソース + 再試行 + 何も見つかりませんでした + まだ履歴はありません + 読む + お気に入りの本はありません + お気に入りの本 + 新たなカテゴリー + 追加 + 保存 + ショートカットを作成します… + 共有する%s + ダウンロード中… + 処理中… + ダウンロードした本 + ダウンロード + 名前 + 人気 + ローカルストレージ + 最新 + 評価 + ソート順に並べ替え + フォローシステム + クリア + すべての履歴を永久にクリアしますか? + 削除 + 「%s 」がローカルストレージから削除されました + ページを保存 + 保存しました + 画像を共有する + インポート + 消去 + この操作はサポートされていません + 説明がありません + 履歴とキャッシュ + ページのキャッシュをクリアする + B|kB|MB|GB|TB + 設定 + ライトテーマ + フィルター + ダークテーマ + ページ + テーマ + ネットワークエラー + アップデート + ZIPファイルまたはCBZファイルを選択してください。 + 標準 + ウェブトゥーン + 読み取りモード + グリッドのサイズ + %sで検索 + 漫画を削除 + お使いのデバイスから「%s」を完全に削除しますか? + リーダーの設定 + ページを変更 + エッジタップ + ボリュームボタン + 続ける + エラー + サムネイルキャッシュをクリア + クリア + ジェスチャーのみ + 内部ストレージ + ドメイン + ブラウザーで開く + この漫画には%sがあります。 すべて保存しますか? + 保存 + 通知 + %2$dの%1$d + 新しいチャプター + ダウンロード + 通知の設定 + 通知音 + LEDインジケータ + バイブレーション + お気に入りのカテゴリー + 削除 + クエリを再定式化してみてください。 + 読んだ内容がここに表示されます + サイドメニューで何を読むかを見つけてください。 + 最初に何かを保存する + 本棚 + 最近 + ページアニメーション + ダウンロード用のフォルダ + 利用出来ません + 使用可能なストレージがありません + その他のストレージ + 完了 + 全てのお気に入り + 後で読む + 更新 + あなたが読んでいるものの新しいチャプターがここに示されています + の検索結果 + サイズ:%s + 更新フィードをクリア + クリア + アップデート + フィードの更新はまもなく開始されます + アップデートを確認 + チェックしない + Kotatsuを起動したときにパスワードを入力する + パスワードを繰り返す + パスワードが違います + この本の詳細 + 現在のバージョン%s + 検索履歴をクリア + 外部ストレージ + Kotatsuの新しい更新が利用可能です + ここは空っぽです… + 空のカテゴリー + オンラインソースから保存するかファイルをインポートします。 + 新しいバージョン:%s + 画面を回転させる + パスワードを入力してください + パスワードが間違っています + アプリを保護する + 最新のアップデートを確認する + 利用可能なアップデートはありません + 右から左 + 承認済み + %sへのログインはサポートされていません + 完成 + 進行中 + デフォルト + ナンバリングページ + 使用したソース + 利用可能なソース + 新しいカテゴリー + 高さを合わせる + チャプターがありません + すべての更新履歴を完全に消去しますか? + この不足した章をダウンロードしたり、オンラインで読んだりすることができます。 + このコンテンツを表示するにはサインインしてください + ファイルが見つかりません + パスワードは4文字以上である必要があります + ちょうど今 + ずっと前 + バックアップを保存 + グループ + フィードをクリア + バックアップから復元 + 確認 + 履歴とお気に入りのバックアップを作成して復元できます + 続きを読む + ブラック + データは復元されましたがエラーが発生しました + 最近の検索クエリを全て完全に削除しますか? + 幅を合わせる + 新しいチャプターを探しています + アプリを起動するためのパスワードを入力してください + データバックアップを作成 + 解決しました + タップして再試行してください + CAPTCHAが必要です + デフォルト:%s + 昨日 + このアプリを翻訳 + 全てのデータが復元されました + 復元 + 準備中… + 開始時に維持 + バックアップと復元 + リバース + 選択した構成はこの漫画のために記憶されます + クッキーを削除 + フィットセンター + 全てのソースからログアウトされます + NSFW漫画を履歴から除外する + キュー + 全てのCookieが削除されました + 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 + ジャンル + スケールモード + 今日 + Kotatsuを翻訳する(Weblateのサイトに移動します) + 次のページ + サイレント + サインイン + ようこそ + AMOLEDスクリーンでさらに少ない電力を使用 + コンピューティング… + 許可する + 常にブロック + スクリーンショットポリシー + NSFWでブロック + 提案 + すべてのデータは、このデバイス上でローカルでのみ分析され、どこにも送信されることはありません。 + サジェスト機能を有効 + あなたの好みに合わせて漫画を提案 + ジャンルリストを読み込めません + 無効 + マンガを読み始めると、個人的な提案を受けることができます + 有効 + NSFWのマンガを提案しない + フィルターをリセット + ジャンルを探す + Wi-Fiのみ使用 + 決して + 漫画を読みたい言語を選択します。後で設定から変更することができます。 + 常に + ページのプリロード + %sとしてログイン + 18歳以上 + さまざまな言語 + チャプターを検索 + この漫画の章はありません + %1$s%% + コンテンツ + 更新のご提案 + 外観 + ジャンルを除く + サジェストで表示したくないジャンルを指定 + 選択した項目をデバイスから完全に削除しますか? + 削除が完了しました + IPアドレスのブロックを回避することができます + 保存されたマンガの処理 + ダウンロードの速度低下 + チャプターはバックグラウンドで削除されます + 隠す + 新しいマンガソースが利用可能です + 新着チャプターの確認とお知らせ + 読んでいるマンガの更新情報をお知らせします + 通知を有効にする + 通知はありませんが、新しいチャプターはリストでハイライト表示されます + 名称 + 編集 + カテゴリーを編集する + お気に入りのカテゴリーはありません + ブックマーク + ブックマーク削除 + 元に戻す + 履歴から削除 + ブックマークの追加 + ブックマークの削除 + ブックマークを追加 + HTTPS 経由の DNS + リーダーモードの自動検出 + デフォルトモード + マンガがウェブトゥーンかどうかを自動判定 + バッテリー最適化の無効化 + バックグラウンドの更新チェックを支援 + 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 + 送信 + すべて無効にする + 最近読んだ漫画 + 指紋がある場合は、指紋を使用する + お気に入りの漫画 + 報告 + 読書 + 再読込 + 完了 + 保留中 + 追跡 + ログアウト + 予定 + ドロップ + データの削除 + 履歴とお気に入りに既読率を表示する + いくつかの問題の場合に助けることができる。すべての認証が無効になります + 読書の進行状況インジケーターを表示 + NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない + すべて表示 + 無効なドメイン + 範囲を選択 + コンテンツが見つからない、または削除された + 管理 + ランダム + 選択したお気に入りカテゴリを本当に削除してもよいですか? \nその中にあるマンガはすべて失われ、元に戻すことはできません。 - - 探検 - アプリを終了するには、戻るを2回押してください - 保存したマンガ - チャプターなし - 自動スクロール - マンガのインポート - 続行するにはメールアドレスを入力してください - «探索»セクションで読むべきものを見つける - インポートが完了しました - あなたのマンガはここに表示されます - キャンセル - データの同期 - アカウントは既に存在します - 戻る - 過去 2 時間 - ブックマークはまだありません - 同期 - ページキャッシュ - 利用可能 - すべての履歴を消去する - 履歴が消去されました - 並べ替え - マンガを読みながらブックマークを作成することができます - ブックマークを削除しました - マンガのソースがない - マンガのソースを有効にして、オンラインでマンガを読めるようにする - もう一度戻るを押して終了します - %s -%s - 退出確認 - ストレージの使用状況 - その他のキャッシュ - シークレットモード - 画像を含むフォルダ - まもなくインポートが開始されます - お気に入りから削除 - オプション - ストレージから元のファイルを削除して、容量を節約することができます - Ch.%1$d/%2$d Pg.%3$d/%4$d - リーダーで情報バーを表示する - コミックアーカイブ - フィード - エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用できるか確認する<br>2. 利用できる場合は、開発者にエラーレポートを送信する</a>。 - 人間工学に基づいたリーダーコントロール - 最近のマンガのショートカットを表示 - アプリケーションアイコンを長押しして最近のマンガを利用できるようにする - 右端をタップするか、右キーを押すと、常に次のページに切り替わります - 色補正 - 輝度 - コントラスト - リセット - 未保存の変更を保存または破棄しますか\? - 選択した色の設定は、この漫画のために記憶されます - 破棄 - デバイスに空き容量がありません - ページ切り替えスライダーを表示 - サーバーサイドエラー (%1$d) です。後で再試行してください - 新しいチャプターの情報も明確に - さまざまな言語 - ネットワークが利用できません - Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます - Webtoonズーム - コンパクト - マミミ - - ここには何もありません - 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 - サービス - デバッグ目的でいくつかのアクションを記録する - ミク - ユーザー エージェント ヘッダー - コンテンツのプリロード - ログを共有 - 不安定な更新を許可 - アプリのベータ版へのアップデートを提案する - ダウンロードが開始されました - 言語 - ソースが無効になっています - 現在としてマーク - ログ記録を有効にする - 疑わしいコンテンツを表示する - ダイナミック - 配色 - グリッドビューで表示 - アスカ - ミオン - リッカ - さくら - この変更を適用するには、アプリケーションを再起動してください - + + 探検 + アプリを終了するには、戻るを2回押してください + 保存したマンガ + チャプターなし + 自動スクロール + マンガのインポート + 続行するにはメールアドレスを入力してください + «探索»セクションで読むべきものを見つける + インポートが完了しました + あなたのマンガはここに表示されます + キャンセル + データの同期 + アカウントは既に存在します + 戻る + 過去 2 時間 + ブックマークはまだありません + 同期 + ページキャッシュ + 利用可能 + すべての履歴を消去する + 履歴が消去されました + 並べ替え + マンガを読みながらブックマークを作成することができます + ブックマークを削除しました + マンガのソースがない + マンガのソースを有効にして、オンラインでマンガを読めるようにする + もう一度戻るを押して終了します + %s -%s + 退出確認 + ストレージの使用状況 + その他のキャッシュ + シークレットモード + 画像を含むフォルダ + まもなくインポートが開始されます + お気に入りから削除 + オプション + ストレージから元のファイルを削除して、容量を節約することができます + Ch.%1$d/%2$d Pg.%3$d/%4$d + リーダーで情報バーを表示する + コミックアーカイブ + フィード + エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用可能かどうか確認してください<br>2.<a href=kotatsu://about>最新版のこたつ</a><br>3.利用可能であれば、開発者にエラーレポートを送ってみてください。 + 人間工学に基づいたリーダーコントロール + 最近のマンガのショートカットを表示 + アプリケーションアイコンを長押しして最近のマンガを利用できるようにする + 右端をタップするか、右キーを押すと、常に次のページに切り替わります + 色補正 + 輝度 + コントラスト + リセット + 未保存の変更を保存または破棄しますか\? + 選択した色の設定は、この漫画のために記憶されます + 破棄 + デバイスに空き容量がありません + ページ切り替えスライダーを表示 + サーバーサイドエラー (%1$d) です。後で再試行してください + 新しいチャプターの情報も明確に + さまざまな言語 + ネットワークが利用できません + Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます + Webtoonズーム + コンパクト + マミミ + + ここには何もありません + 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 + サービス + デバッグ目的でいくつかのアクションを記録する + ミク + ユーザー エージェント ヘッダー + コンテンツのプリロード + ログを共有 + 不安定な更新を許可 + アプリのベータ版へのアップデートを提案する + ダウンロードが開始されました + 言語 + ソースが無効になっています + 現在としてマーク + ログ記録を有効にする + 疑わしいコンテンツを表示する + ダイナミック + 配色 + グリッドビューで表示 + アスカ + ミオン + リッカ + さくら + この変更を適用するには、アプリケーションを再起動してください + 項目をタップ&ホールドして並び替えをすることができます + .cbzまたは.zipファイルを1つ以上選択することができ、各ファイルは別のマンガとして認識されます。 + 了解 + 翻訳 + 過去に作成したユーザーデータのバックアップをインポートする + 棚に表示 + %1$s (%2$s) + 色を反転させる + 有効 + 結構です + ネットワークキャッシュをクリアする + ダウンロードは削除されました + 自分で用意した同期サーバーか、デフォルトのものを使用することができます。よく分からない場合は変更しないでください。 + 一時停止 + ダウンロードがキャンセルされました + WebViewが利用できません:WebView providerがインストールされているかどうかを確認してください + ダウンロード済み + 画像最適化プロキシ + wsrv.nl サービスを使用して、トラフィック使用量を削減し、可能であれば画像の読み込みを高速化します + アーカイブや画像のあるディレクトリを選択することができます。各アーカイブ(またはサブディレクトリ)は、1つのチャプターとして認識されます。 + 類似したものを探す + タイプ + アドレス + ポート + プロキシ + 同期の設定 + サーバーアドレス + 速度 + SSLエラーを無視する + ミラーを自動的に選択する + ミラーがある場合、エラー時にリモートソースのドメインを自動で切り替える + 履歴書 + 一時停止 + 全てキャンセル + Wi-Fi経由でのみダウンロード + モバイルデータ通信への切り替え時にダウンロードを停止する + 提案: %s + 提案されたマンガの通知を表示することがあります + もっと見る + アクティブなダウンロードはすべてキャンセルされ、部分的にダウンロードされたデータは失われます + ダウンロード履歴は完全に削除されます + ダウンロードはありません + ダウンロードが再開されました + ダウンロードが一時停止されました + パーソナライズされた漫画の提案を受け取りますか? + 削除が完了 + 既存のアカウントにサインインするか、新規にアカウントを作成することができます + 無効な値 + ユーザー名 + パスワード + オーソライズ(オプション) + 無効なポート番号です + \ No newline at end of file From 0639d3e6c1cacc08eb0481edbe0fa4c8ce2f8764 Mon Sep 17 00:00:00 2001 From: Insopitus Date: Mon, 5 Jun 2023 11:53:37 +0200 Subject: [PATCH 43/90] Translated using Weblate (Chinese (Simplified)) Currently translated at 99.2% (413 of 416 strings) Co-authored-by: Insopitus Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/ Translation: Kotatsu/Strings --- app/src/main/res/values-zh-rCN/strings.xml | 794 +++++++++++---------- 1 file changed, 412 insertions(+), 382 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 62b5a3e00..5b20c9e2a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,385 +1,415 @@ - 设置 - 本地存储 - 喜欢 - 历史 - 发生了一个错误 - 网络错误 - 章节 - 列表 - 数据被恢复了,但有错误 - 正在处理… - 最新 - 评分 - 已删除所有 cookie - 所有数据都被恢复了 - 无声 - 准备… - 未找到文件 - 昨日 - 你可以创建你的历史和收藏的备份并恢复它 - 现在 - 很久以前 - - 轻点以重试 - 所选择的配置将因这部漫画而被记住 - 需要验证码 - 解决 - 今天 - 清除cookies - 有新的漫画源可用 - 根据你的喜好推荐漫画 - 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 - 从不 - 你会收到你正在阅读的漫画的更新通知 - 18+ - 各种语言 - 查找章节 - 排除流派 - 建议更新 - 检查新的章节并通知有关情况 - 详细内容 - 详细列表 - 网格 - 列表模式 - 漫画源 - 加载中… - 计算中… - %1$d/%2$d章节 - 关闭 - 再试一次 - 清除历史 - 没有发现 - 尚无历史 - 阅读 - 尚无收藏夹 - 收藏此漫画 - 新分类 - 添加 - 保存 - 分享 - 创建快捷方式… - 分享%s - 搜索 - 搜索漫画 - 正在下载… - 已下载 - 下载 - 名称 - 热门 - 更新 - 排序顺序 - 过滤器 - 主题 - 深色 - 浅色 - 跟随系统 - 页数 - 清除 - 永久清除所有阅读历史\? - 删除 - \"%s\"从本地存储中删除 - 保存页面 - 保存 - 分享图片 - 导入 - 删除 - 不支持此操作 - 选择 ZIP 或 CBZ 文件. - 无描述 - 历史和缓存 - 清除页面缓存 - B|kB|MB|GB|TB - 标准 - 条漫 - 阅读模式 - 网格大小 - 在%s上搜索 - 删除漫画 - 从设备中永久删除\"%s\"\? - 阅读器设置 - 切换页面 - 音量按钮 - 继续 - 边缘点击 - 错误 - 清除缩略图缓存 - 清除搜索历史 - 清除 - 仅限手势 - 内部存储 - 外部存储 - 范围 - 新版本应用程序已经推出 - 在网络浏览器中打开 - 这部漫画有%s.全部保存\? - 保存 - 通知 - 新章节 - 下载 - 通知设置 - 通知声音 - LED指示器 - 振动 - 收藏夹分类 - 删除 - 这里有点空… - 尝试重新表述查询。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容. - 先保存内容 - 从在线来源保存或导入文件. - 书架 - 最近 - 页面动画 - 下载文件夹 - 不详 - 没有可用的存储空间 - 其他存储 - 完成 - 所有收藏夹 - 空分类 - 稍后阅读 - 更新 - 你正在阅读的新章节显示在这里 - 搜索结果 - 新版本: %s - 清除更新源 - 已清除 - 旋转屏幕 - 更新 - 源更新即将开始 - 查找更新 - 不要检查 - 输入密码 - 密码错误 - 保护应用程序 - 在启动Kotatsu时要求输入密码 - 重复密码 - 密码不匹配 - 关于 - 版本%s - 检查更新 - 没有更新 - 从右到左 - 新分类 - 缩放模式 - 适应中心 - 适应高度 - 适应宽度 - 从头开始 - 黑色 - 在AMOLED屏幕上使用更少电池 - 备份和还原 - 创建数据备份 - 从备份中恢复 - 恢复 - 清除文件 - 永久地清除所有的更新历史? - 检查新的章节 - 撤销 - 登录 - 登录后可查看此内容 - 默认值: %s - 下一页 - 输入密码以启动应用程序 - 确认 - 密码必须是4个字符或以上 - 永久地删除所有最近的搜索查询? - 欢迎 - 保存备份 - 一些设备有不同的系统行为, 这可能会破坏后台任务. - 阅读更多 - 排队 - 下载或在线阅读这缺失的章节. - 该章缺失 - 翻译此应用程序 - 翻译 - 授权 - 不支持在%s上登录 - 你将退出登录所有来源 - 类型 - 连载中 - 已完结 - 默认 - 将NSFW漫画排除在历史之外 - 页数 - 使用图源 - 现有图源 - 屏幕截图 - 允许 - 禁止18+ - 始终阻止 - 建议 - 启用建议 - 开始阅读漫画,你会得到个性化的建议 - 请勿推荐18+漫画 - 启用 - 禁用 - 无法加载流派列表 - 重置过滤器 - 查找流派 - 选择你想看的漫画的语言. 你可以在以后的设置中改变它. - 只在Wi-Fi上使用 - 总是 - 预加载页面 - 以%s身份登录 - 这部漫画中没有章节 - 外观 - 内容 - 指定您不希望在建议中看到的类型 - 从设备中永久删除所选项目\? - 删除已完成 - 下载速度减慢 - 有助于避免阻断你的IP地址 - 保存的漫画处理 - 章节将在后台被删除 - 隐藏 - 你将不会收到通知但新的章节将在列表中突出显示 - 启用通知 - 命名 - 编辑 - 编辑分类 - 没有收藏夹分类 - 添加书签 - 删除书签 - 书签 - 删除书签 - 添加书签 - 撤销 - 从历史中删除 - DNS over HTTPS - 默认模式 - 自动检测阅读器模式 - 自动检测漫画是否为条漫 - 禁用电池优化 - 帮助进行背景更新检查 - 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. - 发送 - 全部禁用 - 计划 - 暂停 - 报告 - 追踪 - 注销 - 阅读 - 重读 - 完成 - 使用指纹 - 你喜欢的漫画 - 您最近阅读的漫画 - 在历史和收藏夹中显示阅读百分比 - 显示阅读进度指标 - 数据删除 - 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 - 可以在出现一些问题时提供帮助. 所有授权将被视为无效 - 显示全部 - 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 - 无效域名 - 此处将显示你的漫画 - 在【浏览】页面搜索想要阅读的漫画 - %1$s%% - 已取消 - 账号已存在 - 返回 - 同步 - 同步您的数据 - 输入您的邮箱以继续 - 已放弃 - 选择范围 - 清除所有历史 - 过去2小时 - 书签已移除 - 历史已清除 - 管理 - 还没有书签 - 您可以在阅读漫画时创建书签 - 无漫画源 - 启用漫画源以在线阅读漫画 - 随机 - 您确定要删除选定的收藏夹吗? + 设置 + 本地存储 + 喜欢 + 历史 + 发生了一个错误 + 网络错误 + 章节 + 列表 + 数据被恢复了,但有错误 + 正在处理… + 最新 + 评分 + 已删除所有 cookie + 所有数据都被恢复了 + 无声 + 准备… + 未找到文件 + 昨日 + 你可以创建你的历史和收藏的备份并恢复它 + 现在 + 很久以前 + + 轻点以重试 + 所选择的配置将因这部漫画而被记住 + 需要验证码 + 解决 + 今天 + 清除cookies + 有新的漫画源可用 + 根据你的喜好推荐漫画 + 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 + 从不 + 你会收到你正在阅读的漫画的更新通知 + 18+ + 各种语言 + 查找章节 + 排除流派 + 建议更新 + 检查新的章节并通知有关情况 + 详细内容 + 详细列表 + 网格 + 列表模式 + 漫画源 + 加载中… + 计算中… + %1$d/%2$d章节 + 关闭 + 再试一次 + 清除历史 + 没有发现 + 尚无历史 + 阅读 + 尚无收藏夹 + 收藏此漫画 + 新分类 + 添加 + 保存 + 分享 + 创建快捷方式… + 分享%s + 搜索 + 搜索漫画 + 正在下载… + 已下载 + 下载 + 名称 + 热门 + 更新 + 排序顺序 + 过滤器 + 主题 + 深色 + 浅色 + 跟随系统 + 页数 + 清除 + 永久清除所有阅读历史\? + 删除 + \"%s\"从本地存储中删除 + 保存页面 + 保存 + 分享图片 + 导入 + 删除 + 不支持此操作 + 选择 ZIP 或 CBZ 文件. + 无描述 + 历史和缓存 + 清除页面缓存 + B|kB|MB|GB|TB + 标准 + 条漫 + 阅读模式 + 网格大小 + 在%s上搜索 + 删除漫画 + 从设备中永久删除\"%s\"\? + 阅读器设置 + 切换页面 + 音量按钮 + 继续 + 边缘点击 + 错误 + 清除缩略图缓存 + 清除搜索历史 + 清除 + 仅限手势 + 内部存储 + 外部存储 + 范围 + 新版本应用程序已经推出 + 在网络浏览器中打开 + 这部漫画有%s.全部保存\? + 保存 + 通知 + 新章节 + 下载 + 通知设置 + 通知声音 + LED指示器 + 振动 + 收藏夹分类 + 删除 + 这里有点空… + 尝试重新表述查询。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容. + 先保存内容 + 从在线来源保存或导入文件. + 书架 + 最近 + 页面动画 + 下载文件夹 + 不详 + 没有可用的存储空间 + 其他存储 + 完成 + 所有收藏夹 + 空分类 + 稍后阅读 + 更新 + 你正在阅读的新章节显示在这里 + 搜索结果 + 新版本: %s + 清除更新源 + 已清除 + 旋转屏幕 + 更新 + 源更新即将开始 + 查找更新 + 不要检查 + 输入密码 + 密码错误 + 保护应用程序 + 在启动Kotatsu时要求输入密码 + 重复密码 + 密码不匹配 + 关于 + 版本%s + 检查更新 + 没有更新 + 从右到左 + 新分类 + 缩放模式 + 适应中心 + 适应高度 + 适应宽度 + 从头开始 + 黑色 + 在AMOLED屏幕上使用更少电池 + 备份和还原 + 创建数据备份 + 从备份中恢复 + 恢复 + 清除文件 + 永久地清除所有的更新历史? + 检查新的章节 + 撤销 + 登录 + 登录后可查看此内容 + 默认值: %s + 下一页 + 输入密码以启动应用程序 + 确认 + 密码必须是4个字符或以上 + 永久地删除所有最近的搜索查询? + 欢迎 + 保存备份 + 一些设备有不同的系统行为, 这可能会破坏后台任务. + 阅读更多 + 排队 + 下载或在线阅读这缺失的章节. + 该章缺失 + 翻译此应用程序 + 翻译 + 授权 + 不支持在%s上登录 + 你将退出登录所有来源 + 类型 + 连载中 + 已完结 + 默认 + 将NSFW漫画排除在历史之外 + 页数 + 使用图源 + 现有图源 + 屏幕截图 + 允许 + 禁止18+ + 始终阻止 + 建议 + 启用建议 + 开始阅读漫画,你会得到个性化的建议 + 请勿推荐18+漫画 + 启用 + 禁用 + 无法加载流派列表 + 重置过滤器 + 查找流派 + 选择你想看的漫画的语言. 你可以在以后的设置中改变它. + 只在Wi-Fi上使用 + 总是 + 预加载页面 + 以%s身份登录 + 这部漫画中没有章节 + 外观 + 内容 + 指定您不希望在建议中看到的类型 + 从设备中永久删除所选项目\? + 删除已完成 + 下载速度减慢 + 有助于避免阻断你的IP地址 + 保存的漫画处理 + 章节将在后台被删除 + 隐藏 + 你将不会收到通知但新的章节将在列表中突出显示 + 启用通知 + 命名 + 编辑 + 编辑分类 + 没有收藏夹分类 + 添加书签 + 删除书签 + 书签 + 删除书签 + 添加书签 + 撤销 + 从历史中删除 + DNS over HTTPS + 默认模式 + 自动检测阅读器模式 + 自动检测漫画是否为条漫 + 禁用电池优化 + 帮助进行背景更新检查 + 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. + 发送 + 全部禁用 + 计划 + 暂停 + 报告 + 追踪 + 注销 + 阅读 + 重读 + 完成 + 使用指纹 + 你喜欢的漫画 + 您最近阅读的漫画 + 在历史和收藏夹中显示阅读百分比 + 显示阅读进度指标 + 数据删除 + 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 + 可以在出现一些问题时提供帮助. 所有授权将被视为无效 + 显示全部 + 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 + 无效域名 + 此处将显示你的漫画 + 在【浏览】页面搜索想要阅读的漫画 + %1$s%% + 已取消 + 账号已存在 + 返回 + 同步 + 同步您的数据 + 输入您的邮箱以继续 + 已放弃 + 选择范围 + 清除所有历史 + 过去2小时 + 书签已移除 + 历史已清除 + 管理 + 还没有书签 + 您可以在阅读漫画时创建书签 + 无漫画源 + 启用漫画源以在线阅读漫画 + 随机 + 您确定要删除选定的收藏夹吗? \n所有收藏夹中的漫画将丢失且无法恢复。 - 重新排序 - 留空 - 浏览 - 自动滚动 - 在阅读器中显示信息栏 - 漫画压缩包 - 图片文件夹 - 漫画导入中 - Ch. %1$d/%2$d Pg. %3$d/%4$d - %1$d 的 %2$d 启用 - 大小:%s - 再按一次返回键退出 - 按两次返回键退出应用 - 退出确认 - 已保存漫画 - 页面缓存 - 其他缓存 - 存储占用 - 可用 - 从收藏中移除 - 选项 - 隐身模式 - 无章节 - 导入完毕 - 您可以从存储中删除原文件以节省空间 - 即将开始导入 - 订阅源 - %s - %s - 内容未找到或已移除 - 点击屏幕右侧或按下右键翻到下一页 - 高效阅读器控制 - 长按应用图标显示最近阅读的漫画 - 显示最近阅读漫画的快捷方式 - 重置 - 颜色校正 - 亮度 - 对比度 - 所选颜色设置将会应用于此漫画 - 保存还是放弃未保存的更改? - 放弃 - 设备上没有剩余空间 - 显示换页滑块 - Webtoon 缩放 - 不同语言 - 网络不可用 - 打开 Wi-Fi 或移动网络在线阅读漫画 - 同样清除新章节信息 - 服务器端错误 (%1$d)。请稍后再试 - 紧凑 - 已禁用图源 - 内容预加载 - 标为当前 - 语言 - 启用日志记录 - 分享日志 - 出于调试目的记录某些操作 - 显示可疑内容 - 动态 - 颜色方案 - 用网格视图显示 - Miku - Asuka - Mion - Rikka - Sakura - 服务 - Mamimi - Kanade - 这里什么也没有 - 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 - 允许不稳定更新 - 提示更新到测试版 - 已开始下载 - UserAgent 标头 - 要应用这些更改请重启程序 - 点击并长按项目排序 - 知道了 - 速度 - 导入先前创建的用户数据备份 - 在书架上显示 - 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 - 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 - + 重新排序 + 留空 + 浏览 + 自动滚动 + 在阅读器中显示信息栏 + 漫画压缩包 + 图片文件夹 + 漫画导入中 + Ch. %1$d/%2$d Pg. %3$d/%4$d + %1$d 的 %2$d 启用 + 大小:%s + 再按一次返回键退出 + 按两次返回键退出应用 + 退出确认 + 已保存漫画 + 页面缓存 + 其他缓存 + 存储占用 + 可用 + 从收藏中移除 + 选项 + 隐身模式 + 无章节 + 导入完毕 + 您可以从存储中删除原文件以节省空间 + 即将开始导入 + 订阅源 + %s - %s + 内容未找到或已移除 + 点击屏幕右侧或按下右键翻到下一页 + 高效阅读器控制 + 长按应用图标显示最近阅读的漫画 + 显示最近阅读漫画的快捷方式 + 重置 + 颜色校正 + 亮度 + 对比度 + 所选颜色设置将会应用于此漫画 + 保存还是放弃未保存的更改? + 放弃 + 设备上没有剩余空间 + 显示换页滑块 + Webtoon 缩放 + 不同语言 + 网络不可用 + 打开 Wi-Fi 或移动网络在线阅读漫画 + 同样清除新章节信息 + 服务器端错误 (%1$d)。请稍后再试 + 紧凑 + 已禁用图源 + 内容预加载 + 标为当前 + 语言 + 启用日志记录 + 分享日志 + 出于调试目的记录某些操作 + 显示可疑内容 + 动态 + 颜色方案 + 用网格视图显示 + Miku + Asuka + Mion + Rikka + Sakura + 服务 + Mamimi + Kanade + 这里什么也没有 + 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 + 允许不稳定更新 + 提示更新到测试版 + 已开始下载 + UserAgent 标头 + 要应用这些更改请重启程序 + 点击并长按项目排序 + 知道了 + 速度 + 导入先前创建的用户数据备份 + 在书架上显示 + 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 + 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 + 寻找相似 + 翻译 + WebView不可用:检查是否已安装WebView + 你可以使用自建同步服务器或默认服务器。如果你不知道自己在干什么请不要修改此处。 + 自动选择镜像 + 如果存在可用镜像,在出错时自动切换域名 + 已暂停 + 切换到移动网络时停止下载 + 移除已完成 + 取消所有 + 仅通过Wi-Fi下载 + 启用 + 不,谢谢 + 同步设定 + 服务器地址 + 暂停 + 恢复 + 忽略SSL错误 + 没有下载项 + 下载已经恢复 + 暂停下载 + 下载已被移除 + 下载被取消 + 你想要接收个人漫画推荐吗? + 推荐:%s + 偶尔对建议的漫画显示通知 + 更多 + 所有进行中的下载都将被取消,未下载完成的数据将丢失 + 你的下载历史将会永久删除 + 你可以登陆一个已有账号或创建新账号 + \ No newline at end of file From 69a9ec354b6065f5f69afccf7cc591e5050d80cc Mon Sep 17 00:00:00 2001 From: InfinityDouki56 Date: Mon, 5 Jun 2023 11:53:37 +0200 Subject: [PATCH 44/90] Translated using Weblate (Filipino) Currently translated at 93.0% (387 of 416 strings) Co-authored-by: InfinityDouki56 Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fil/ Translation: Kotatsu/Strings --- app/src/main/res/values-fil/strings.xml | 796 ++++++++++++------------ 1 file changed, 412 insertions(+), 384 deletions(-) diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 9c510180a..75a3e1d2f 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -1,387 +1,415 @@ - Na-update - Pinakabago - Maliwanag - Marka - Pansala - Tema - Madilim - Sundan ang sistema - May nangyaring error - Error sa network - Mga detalye - Mga kabanata - Listahan - Na-save - I-share ang larawan - Mag-angkat - Tanggalin - Hindi suportado ang operasyong ito - Pumili ng ZIP o CBZ file. - Kasaysayan at cache - Walang paglalarawan - Laki ng grid - Hanapin sa %s - Tanggalin ang manga - Permanenteng tanggalin ang \"%s\" sa device\? - Mga setting sa pagbasa - Magpalit ng (mga) pahina - Pindutan ng volume - Magpatuloy - I-clear ang cache ng mga thumbnail - Na-clear - Mga kilos lang - Available ang isang bagong bersyon ng app - Buksan sa web browser - Ang manga na ito ay may %s. I-save ang lahat ng ito\? - Mga abiso - %1$d ng %2$d sa - Mga bagong kabanata - Subukang i-reformulate ang query. - Ang iyong nabasa ay ipapakita dito - Ang iyong manga ay ipapakita dito - Mag-save muna ng isang bagay - I-save ito mula sa mga online na source o mag import ng mga file. - Istante - Animasyon ng pahina - Hindi magagamit - Walang available na storage - Iba pang storage - Tapos na - Lahat ng paborito - Walang laman ang kategorya - Basahin mamaya - Mga update - Mga resulta ng paghahanap - Laki: %s - I-clear ang feed ng mga update - Na-clear - Update - Ang pag update ng feed ay magsisimula sa lalong madaling panahon - Maghanap ng mga update - Ilagay ang password - Humingi ng password kapag sinimulan ang Kotatsu - Tungkol rito - Maghanap ng update - Kanan sa kaliwa - Bagong Kategorya - Pagkasyahin sa gitna - Panatilihin sa simula - Gumagamit ng mas kaunting power sa mga AMOLED na screen - I-backup at i-restore - Naibalik na - Naghahanda… - Hindi nahanap ang file - Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito - Ngayon lang - Kahapon - Matagal na ang nakalipas - Ngayong araw - I-tap para subukang muli - Lutasin - Inalis ang lahat ng mga cookie - I-clear ang feed - Suriin ang mga bagong kabanata - Mag-sign in - Mag-sign in upang tingnan ang nilalamang ito - Default: %s - Susunod - Kumpirmahin - Ang password ay dapat na 4 na character o higit pa - Maligayang pagdating - Na-save ang backup - Magbasa pa - Kulang ang kabanata - Ang pag-log in sa %s ay hindi suportado - Mga genre - Patuloy - Default - Hindi isali ang NSFW manga mula sa kasaysayan - Mga pahinang may bilang - Patakaran sa screenshot - Payagan - Palaging i-block - Mga mungkahi - Paganahin ang mga mungkahi - Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi - Huwag magmungkahi ng NSFW manga - Pinagana - Maghanap ng genre - Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. - Lokal na storage - Mga paborito - Nakaraan - Mode na listahan - Detalyadong listahan - Grid - Mga setting - Mga remote na source - Naglo-load… - Isara - Walang nahanap - Tanggalin - Bagong Kategorya - Nabasa - Wala pang paborito - I-paborito ito - Idagdag - I-save - Ibahagi - Lumikha ng shortcut… - Ibahagi sa %s - Maghanap - Maghanap ng manga - Nagda-download… - Nagpoproseso… - Na-download - Mga download - Pangalan - Sikat - Mga pahina - I-clear ang kasaysayan - I-clear ang kasaysayan ng paghahanap - Bagong bersyon: %s - Hindi tumutugma sa mga password - I-clear ang mga cookie - I-clear ang page cache - I-save - I-download - Mga setting ng abiso - Tunog ng abiso - Mga paboritong kategorya - Tanggalin - Parang walang laman dito… - Hanapin kung ano ang babasahin sa side menu. - Hanapin kung ano ang babasahin sa seksyong «Mag-explore» - Kamakailan - Folder para sa mga download - I-save ang pahina - Natanggal ang \"%s\" sa lokal na storage - Wala pang kasaysayan - Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? - Huwag suriin - Ulitin ang password - Protektahan ang app - Maling password - Bersyon %s - Mode ng scale - Walang available na update - Baliktarin - Grupo - Tahimik - Pagkasyahin sa lapad - Itim - Lumikha ng data backup - Ibalik mula sa backup - Naibalik ang lahat ng data - Ang data ay naibalik, ngunit may mga error - Ang napiling pagsasaayos ay maaalala para sa manga na ito - Isalin ang app na ito - Awtorisado na - Kinakailangan ang CAPTCHA - I-clear nang permanente ang lahat ng update history\? - Maglagay ng password para simulan ang app - Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. - Nakapila na - I-download o basahin ang nawawalang kabanata online. - Mala-log out ka mula sa lahat ng source - Tapos na - Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? - Pagsasalin - I-block sa NSFW - Magmungkahi ng manga batay sa iyong mga kagustuhan - Ang lahat ng data ay sinusuri nang lokal sa aparatong ito. Walang paglipat ng iyong personal na data sa anumang mga serbisyo - Hindi pinagana - Hindi ma-load ang listahan ng mga genre - I-reset ang filter - Ang mga bagong kabanata ng iyong binabasa ay makikita dito - I-rotate ang screen - Pagkasyahin sa tangkad - Hindi kailanman - Sa Wi-Fi lang - Nagco-compute… - Kabanata %1$d ng %2$d - Subukan ulit - Pag-aayos ng order - I-clear - Mga taps ng gilid - Mga ginamit na source - Magagamit na mga source - Lagi na lang - I-preload ang mga pahina - Naka-log in bilang %s - Iba\'t ibang wika - Maghanap ng kabanata - %1$s%% - Hitsura - Hindi isali ang mga genre - Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi - Nakumpleto na ang pagtanggal - Tumutulong na maiwasan ang pag-block ng iyong IP address - Naka-save na pagproseso ng manga - Mayroon nang account - Bumalik - Pag-synchronize - Ilagay ang iyong email upang magpatuloy - Itago - May mga bagong source ng manga - Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan - Paganahin ang mga abiso - Ayusin ang kategorya - Tina-track - Walang mga paboritong kategorya - Mag-log out - Magdagdag ng bookmark - Tinanggal ang bookmark - Inalis sa kasaysayan - DNS sa HTTPS - Default na mode - Automatikong matukoy ang reader mode - May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. - Ipadala - Muling pagbabasa - Binitawan - Manga mula sa iyong mga paborito - Ang iyong kamakailang nabasa na manga - Pagtanggal ng data - Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito - Ipakita lahat - Pumili ng saklaw - I-clear ang lahat ng kasaysayan - Maaari kang lumikha ng bookmark habang nagbabasa ng manga - Tinanggal ang mga bookmark - Random - Walang mga source ng manga - Paganahin ang mga source ng manga upang basahin ang manga online - Ayusin muli - Walang laman - Pindutin muli ang Bumalik upang lumabas - Pindutin ang Bumalik nang dalawang beses upang lumabas sa app - Pagkumpirma ng paglabas - Na-save na manga - Mag-Explore - Iba pang cache - Paggamit ng storage - Magagamit na - %s - %s - Inalis sa mga paborito - Mga pagpipilian - Incognito mode - Walang mga kabanata - Awtomatikong pag-scroll - Ch. %1$d/%2$d Pg. %3$d/%4$d - Ipakita ang information bar sa pagbasa - Archive ng mga comics - Folder na may mga larawan - Nakumpleto na ang pag-import - Magsisimula na ang pag-import - Feed - Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application - Ipakita ang mga kamakailang manga shortcut - Ergonomic na kontrol sa mambabasa - Pagwawasto ng kulay - Liwanag - Kaibahan - I-save o kalimutan ang mga hindi na-save na pagbabago\? - Kalimutan - Walang natitirang espasyo sa device - Pag-zoom sa webtoon - Iba\'t ibang wika - Server side error (%1$d). Subukang muli mamaya - I-clear din ang impormasyon tungkol sa mga bagong kabanata - Preloading ng nilalaman - Markahan bilang kasalukuyan - Wika - Ibahagi ang mga log - Magpakita ng kahina-hinalang nilalaman - Dynamic - Ipakita sa grid view - Asuka - Mion - Rikka - Sakura - Mamimi - Kanade - Wala naman dito - Mga serbisyo - Payagan ang mga hindi stable na update - Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa - Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save - Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa - Imbalidong domain - Huling 2 oras - Nabura ang kasaysayan - Pamahalaan - Wala pang bookmark - 18+ - Hindi natagpuan o inalis ang nilalaman - Magtala ng ilang pagkilos para sa mga layunin ng pag-debug - Permanenteng tanggalin ang mga napiling item sa device\? - Walang mga kabanata sa manga na ito - Nag-a-update ang mga mungkahi - Nilalaman - Pagbagal ng pag-download - Tatanggalin ang mga chapters sa background. Maaari itong tumagal ng ilang oras - Kinansela - I-sync ang iyong data - Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito - Pangalan - I-edit - Tanggalin ang bookmark - Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa - Mag-undo - Nagbabasa - Cache ng mga pahina - Mga bookmark - Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? + Na-update + Pinakabago + Maliwanag + Marka + Pansala + Tema + Madilim + Sundan ang sistema + May nangyaring error + Error sa network + Mga detalye + Mga kabanata + Listahan + Na-save + I-share ang larawan + Mag-angkat + Tanggalin + Hindi suportado ang operasyong ito + Pumili ng ZIP o CBZ file. + Kasaysayan at cache + Walang paglalarawan + Laki ng grid + Hanapin sa %s + Tanggalin ang manga + Permanenteng tanggalin ang \"%s\" sa device\? + Mga setting sa pagbasa + Magpalit ng (mga) pahina + Pindutan ng volume + Magpatuloy + I-clear ang cache ng mga thumbnail + Na-clear + Mga kilos lang + Available ang isang bagong bersyon ng app + Buksan sa web browser + Ang manga na ito ay may %s. I-save ang lahat ng ito\? + Mga abiso + %1$d ng %2$d sa + Mga bagong kabanata + Subukang i-reformulate ang query. + Ang iyong nabasa ay ipapakita dito + Ang iyong manga ay ipapakita dito + Mag-save muna ng isang bagay + I-save ito mula sa mga online na source o mag import ng mga file. + Istante + Animasyon ng pahina + Hindi magagamit + Walang available na storage + Iba pang storage + Tapos na + Lahat ng paborito + Walang laman ang kategorya + Basahin mamaya + Mga update + Mga resulta ng paghahanap + Laki: %s + I-clear ang feed ng mga update + Na-clear + Update + Ang pag update ng feed ay magsisimula sa lalong madaling panahon + Maghanap ng mga update + Ilagay ang password + Humingi ng password kapag sinimulan ang Kotatsu + Tungkol rito + Maghanap ng update + Kanan sa kaliwa + Bagong Kategorya + Pagkasyahin sa gitna + Panatilihin sa simula + Gumagamit ng mas kaunting power sa mga AMOLED na screen + I-backup at i-restore + Naibalik na + Naghahanda… + Hindi nahanap ang file + Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito + Ngayon lang + Kahapon + Matagal na ang nakalipas + Ngayong araw + I-tap para subukang muli + Lutasin + Inalis ang lahat ng mga cookie + I-clear ang feed + Suriin ang mga bagong kabanata + Mag-sign in + Mag-sign in upang tingnan ang nilalamang ito + Default: %s + Susunod + Kumpirmahin + Ang password ay dapat na 4 na character o higit pa + Maligayang pagdating + Na-save ang backup + Magbasa pa + Kulang ang kabanata + Ang pag-log in sa %s ay hindi suportado + Mga genre + Patuloy + Default + Hindi isali ang NSFW manga mula sa kasaysayan + Mga pahinang may bilang + Patakaran sa screenshot + Payagan + Palaging i-block + Mga mungkahi + Paganahin ang mga mungkahi + Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi + Huwag magmungkahi ng NSFW manga + Pinagana + Maghanap ng genre + Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. + Lokal na storage + Mga paborito + Kasaysayan + Mode na listahan + Detalyadong listahan + Grid + Mga setting + Mga source ng Manga + Naglo-load… + Isara + Walang nahanap + Tanggalin + Bagong Kategorya + Nabasa + Wala pang paborito + I-paborito ito + Idagdag + I-save + Ibahagi + Lumikha ng shortcut… + Ibahagi sa %s + Maghanap + Maghanap ng manga + Nagda-download… + Nagpoproseso… + Na-download + Mga download + Pangalan + Sikat + Mga pahina + I-clear ang kasaysayan + I-clear ang kasaysayan ng paghahanap + Bagong bersyon: %s + Hindi tumutugma sa mga password + I-clear ang mga cookie + I-clear ang page cache + I-save + I-download + Mga setting ng abiso + Tunog ng abiso + Mga paboritong kategorya + Tanggalin + Parang walang laman dito… + Hanapin kung ano ang babasahin sa side menu. + Hanapin kung ano ang babasahin sa seksyong «Mag-explore» + Kamakailan + Folder para sa mga download + I-save ang pahina + Natanggal ang \"%s\" sa lokal na storage + Wala pang kasaysayan + Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? + Huwag suriin + Ulitin ang password + Protektahan ang app + Maling password + Bersyon %s + Mode ng scale + Walang available na update + Baliktarin + Grupo + Tahimik + Pagkasyahin sa lapad + Itim + Lumikha ng data backup + Ibalik mula sa backup + Naibalik ang lahat ng data + Ang data ay naibalik, ngunit may mga error + Ang napiling pagsasaayos ay maaalala para sa manga na ito + Isalin ang app na ito + Awtorisado na + Kinakailangan ang CAPTCHA + I-clear nang permanente ang lahat ng update history\? + Maglagay ng password para simulan ang app + Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. + Nakapila na + I-download o basahin ang nawawalang kabanata online. + Mala-log out ka mula sa lahat ng source + Tapos na + Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? + Pagsasalin + I-block sa NSFW + Magmungkahi ng manga batay sa iyong mga kagustuhan + Ang lahat ng data ay lokal lamang na sinusuri sa device na ito at hindi kailanman ipinadala kahit saan. + Hindi pinagana + Hindi ma-load ang listahan ng mga genre + I-reset ang filter + Ang mga bagong kabanata ng iyong binabasa ay makikita dito + I-rotate ang screen + Pagkasyahin sa tangkad + Hindi kailanman + Sa Wi-Fi lang + Nagco-compute… + Kabanata %1$d ng %2$d + Subukan ulit + Pag-aayos ng order + I-clear + Mga taps ng gilid + Mga ginamit na source + Magagamit na mga source + Lagi na lang + I-preload ang mga pahina + Naka-log in bilang %s + Iba\'t ibang wika + Maghanap ng kabanata + %1$s%% + Hitsura + Hindi isali ang mga genre + Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi + Nakumpleto na ang pagtanggal + Tumutulong na maiwasan ang pag-block ng iyong IP address + Naka-save na pagproseso ng manga + Mayroon nang account + Bumalik + Pag-synchronize + Ilagay ang iyong email upang magpatuloy + Itago + May mga bagong source ng manga + Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan + Paganahin ang mga abiso + Ayusin ang kategorya + Tina-track + Walang mga paboritong kategorya + Mag-log out + Magdagdag ng bookmark + Tinanggal ang bookmark + Inalis sa kasaysayan + DNS sa HTTPS + Default na mode + Automatikong matukoy ang reader mode + May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. + Ipadala + Muling pagbabasa + Binitawan + Manga mula sa iyong mga paborito + Ang iyong kamakailang nabasa na manga + Pagtanggal ng data + Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito + Ipakita lahat + Pumili ng saklaw + I-clear ang lahat ng kasaysayan + Maaari kang lumikha ng bookmark habang nagbabasa ng manga + Tinanggal ang mga bookmark + Random + Walang mga source ng manga + Paganahin ang mga source ng manga upang basahin ang manga online + Ayusin muli + Walang laman + Pindutin muli ang Bumalik upang lumabas + Pindutin ang Bumalik nang dalawang beses upang lumabas sa app + Pagkumpirma ng paglabas + Na-save na manga + Mag-Explore + Iba pang cache + Paggamit ng storage + Magagamit na + %s - %s + Inalis sa mga paborito + Mga pagpipilian + Incognito mode + Walang mga kabanata + Awtomatikong pag-scroll + Ch. %1$d/%2$d Pg. %3$d/%4$d + Ipakita ang information bar sa pagbasa + Archive ng mga comics + Folder na may mga larawan + Nakumpleto na ang pag-import + Magsisimula na ang pag-import + Feed + Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application + Ipakita ang mga kamakailang manga shortcut + Ergonomic na kontrol sa mambabasa + Pagwawasto ng kulay + Liwanag + Kaibahan + I-save o kalimutan ang mga hindi na-save na pagbabago\? + Kalimutan + Walang natitirang espasyo sa device + Pag-zoom sa webtoon + Iba\'t ibang wika + Server side error (%1$d). Subukang muli mamaya + I-clear din ang impormasyon tungkol sa mga bagong kabanata + Preloading ng nilalaman + Markahan bilang kasalukuyan + Wika + Ibahagi ang mga log + Magpakita ng kahina-hinalang nilalaman + Dynamic + Ipakita sa grid view + Asuka + Mion + Rikka + Sakura + Mamimi + Kanade + Wala naman dito + Mga serbisyo + Payagan ang mga hindi stable na update + Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa + Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save + Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa + Imbalidong domain + Huling 2 oras + Nabura ang kasaysayan + Pamahalaan + Wala pang bookmark + 18+ + Hindi natagpuan o inalis ang nilalaman + Magtala ng ilang pagkilos para sa mga layunin ng pag-debug + Permanenteng tanggalin ang mga napiling item sa device\? + Walang mga kabanata sa manga na ito + Nag-a-update ang mga mungkahi + Nilalaman + Pagbagal ng pag-download + Tatanggalin ang mga kabanata sa background + Kinansela + I-sync ang iyong data + Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito + Pangalan + I-edit + Tanggalin ang bookmark + Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa + Mag-undo + Nagbabasa + Cache ng mga pahina + Mga bookmark + Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? \nAng lahat ng manga sa loob nito ay mawawala at hindi na ito mababawi. - Idinagdag ang bookmark - Awtomatikong matukoy kung ang manga ay webtoon - Huwag paganahin ang pag-optimize ng baterya - Tumutulong sa mga pagsusuri sa mga update sa background - Nakaplano - Nakumpleto na - Naka-hold - Huwag paganahin ang lahat - Gumamit ng fingerprint kung magagamit - Ulat - I-reset - Magmungkahi ng mga update sa mga beta na bersyon ng app - Hindi magagamit ang network - I-on ang Wi-Fi o mobile network para magbasa ng manga online - Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina - Ipakita ang slider ng paglipat ng pahina - Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>buksan ang manga sa isang web browser</a> upang matiyak na magagamit ito sa source<br>nito 2. Kung magagamit ito, magpadala ng isang ulat ng error sa mga developer. - Paganahin ang pag-log - Hindi pinagana ang source - Pag-import ng manga - Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo - Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito - Compact - Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. - Nagsimula na ang pag-download - Scheme ng kulay - Miku - Header ng UserAgent - B|kB|MB|GB|TB - Standard - Webtoon - Read mode - Error - Internal storage - External storage - Vibration - Domain - LED indicator - Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito - Nakuha ko - I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito - Mag-import ng dating ginawa na backup ng data ng user - Ipakita sa Istante - Bilis - Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. - Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. - Maghanap ng katulad - Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago - + Idinagdag ang bookmark + Awtomatikong matukoy kung ang manga ay webtoon + Huwag paganahin ang pag-optimize ng baterya + Tumutulong sa mga pagsusuri sa mga update sa background + Nakaplano + Nakumpleto na + Naka-hold + Huwag paganahin ang lahat + Gumamit ng fingerprint kung magagamit + Ulat + I-reset + Magmungkahi ng mga update sa mga beta na bersyon ng app + Hindi magagamit ang network + I-on ang Wi-Fi o mobile network para magbasa ng manga online + Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina + Ipakita ang slider ng paglipat ng pahina + Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>magbukas ng manga sa isang web browser</a> upang matiyak na available ito sa souce<br>2. Tiyaking ginagamit mo ang <a href=kotatsu://about>pinakabagong bersyon ng Kotatsu</a><br>3. Kung available ito, magpadala ng ulat ng error sa mga developer. + Paganahin ang pag-log + Hindi pinagana ang source + Pag-import ng manga + Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo + Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito + Compact + Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. + Nagsimula na ang pag-download + Scheme ng kulay + Miku + Header ng UserAgent + B|kB|MB|GB|TB + Standard + Webtoon + Read mode + Error + Internal storage + External storage + Vibration + Domain + LED indicator + Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito + Nakuha ko + I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito + Mag-import ng dating ginawa na backup ng data ng user + Ipakita sa Istante + Bilis + Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. + Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. + Maghanap ng katulad + Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago + Mga pagsasalin + Hindi available ang WebView: tingnan kung naka-install ang WebView provider + Paganahin + Na-pause ang mga pag-download + Mga setting ng pag-synchronize + Address ng server + Maaari kang gumamit ng self-hosted synchronization server o isang default. Huwag baguhin ito kung hindi ka sigurado sa iyong ginagawa. + Huwag pansinin ang mga error sa SSL + Awtomatikong pumili ng mirror + Awtomatikong lumipat ng mga domain para sa mga remote source sa mga error kung available ang mga mirror + Kanselahin lahat + Mag-download lamang sa pamamagitan ng Wi-Fi + Itigil ang pag-download kapag lumipat sa isang mobile network + Naka-pause + Tanggalin ang nakumpleto na + Mga mungkahi: %s + I-pause + Minsang magpakita ng mga notification na may iminungkahing manga + Higit pa + Salamat nalang + Ipagpatuloy + Ang lahat ng mga aktibong pag download ay kakanselahin, bahagyang na download na data ay mawawala + Permanenteng ide-delete ang iyong history ng mga pag-download + Wala kang anumang mga pag-download + Ipinagpatuloy ang mga pag-download + Gusto mo bang makatanggap ng personalized na mga mungkahi sa manga\? + Inalis na ang mga download + Nakansela ang mga pag-download + \ No newline at end of file From 8ac95e1608bed2276e68fc860e724dfc3ab782bd Mon Sep 17 00:00:00 2001 From: tryvseu Date: Mon, 5 Jun 2023 11:53:38 +0200 Subject: [PATCH 45/90] Translated using Weblate (Norwegian Nynorsk) Currently translated at 85.5% (356 of 416 strings) Co-authored-by: tryvseu Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nn/ Translation: Kotatsu/Strings --- app/src/main/res/values-nn/strings.xml | 707 +++++++++++++------------ 1 file changed, 359 insertions(+), 348 deletions(-) diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 28c7e9b36..905125266 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -1,351 +1,362 @@ - Det hende ein feil - Rutenett - Innstillingar - Mangakjelder - Tøm historikken - Historikken er tom - Les - Lik - Ny hop - Legg til - Hent - Lag ein snarveg … - Del %s - Søk - Søk manga - Hentar … - Handsamar … - Henta - Nyaste - Omdøme - Sil ut - Ljos - Sider - Tøm - Tøm lesehistorikken for godt\? - Tak bort - Hent sida - Henta - Del biletet - Før inn - Slett - Vel ei ZIP- eller CBZ-fil. - Ingen utgreiing - Tøm mellomminnet til sida - Vanleg - Nettserie - Rutenettstorleik - Slett mangaen - Slett «%s» ifrå eininga\? - Leseinnstillingar - Bla med - Hald fram - Feil - Tøm mellomminnet for småbilete - Tøm søkehistorikken - Tømt - Berre handrørsler - Hent - Varsel - %1$d av %2$d - Hent - Varselinnstillingar - Varselljod - Varselljos - Dirring - Hopar til leiting - Hent ifrå nettkjelder eller før inn filer. - Hylla - Nytt - Legg henta mangaar i: - Gjort - Alt du likar - Tom hop - Les seinare - Oppdateringar - Søkesvar - Ny utgåve: %s - Tømt - Snu skjermen - Leit etter oppdateringar - Nei - Om - Leit etter oppdateringar - Høgre-til-venstre - Lesevising - Høv til høgda - Høv til breidda - Svart - Tryggleikskopiering og gjenoppretting - Lag ein tryggleikskopi - Gjenoppretta - Fann ikkje fila - Gjenoppretta all data - Gjenoppretta dataa, men med feil - Trykk for å røyna att - Listeslag - Henta - Likar - Historikk - Nettverksfeil - Liste - Hentar fram … - Steng - Røyn att - Fann ikkje noko - Del - Henta - Namn - Oppdatert - Vising - Lyd systemet - Mørk - Historikken og mellomminnet - Hent noko først - Ikkje tilgjengeleg - Oppdater - Storleik: %s - Brukar mindre straum på AMOLED-skjermar - Utgåve %s - Ingen tilgjengelege oppdateringar - Ny hop - Midtstill - Auk byrjinga av sida - Gjenopprett ifrå ein tryggleikskopi - Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting - Førebur … - Forval - No - I dag - I går - Lenge sida - Lesing - Randetrykk - Ljodstyrkeknappar - Ei ny utgåve av appen er tilgjengeleg - Opne i ein nettlesar - Denne mangaen har %s. Hent alle\? - Det du les vert vist her - Rit inn lykelordet - Gjentak lykelordet - Lykelorda er ulike - Brigde av oppsettet vedkjem berre denne mangaen - Stille - Krev CAPTCHA - Løys - Slett infokapslane - Sletta infokapslane - Tøm oppdateringshistorikken\? - Logg inn - Neste - Stadfest - Lykelordet må vera lengre enn fire teikn - Tryggleikskopi laga - Les meir - I kø - Omset denne appen - Omsetjing - Godkjend - Slag - Fullgjort - I gang - Utelèt mangaar med vakse innhald ifrå historikken - Sidetal - Nytta kjelder - Tilgjengelege kjelder - Skjermbilete - Hindre alltid - Råd - Slå på råd - Rå om mangaar ut ifrå det du har lese - Byrja å lesa nokre mangaar for å få personlege råd - Ikkje rå mangaar med vakse innhald - Påslegen - Kunne ikkje hente inn slaglista - Finn slag - Ulike mål - %1$s%% - Innhald - Oppdaterer råd - Utelat slag - Sletta - Avgrens hentesnøggleiken - Lægjer vona for at IP-adressa di vert blokkert - Handsamar henta manga - Avbroten - Kontoen finst alt - Attende - Synkroniser dataet ditt - Rit inn e-postadressa di for å halda fram - Skjul - Namn - Brigd - Brigd hopen - Sporing - Ingen likte hopar - Logg ut - Bokmerk - Tak bort bokmerket - Bokmerke - Teken bort ifrå historikken - DNS over HTTPS - Forvald lesing - Finn sjølvverkande ut av lesing - Finn sjølvverkande ut av om mangaen er ein nettserie - Slå av batterilenging - Send - Les - Skal lesa - Les att - Lesen - På vent - Gjeven opp - Slå av alle - Mangaar du har nyleg lese - Sletting av data - Vis % lesen i historikken og likerlista - Kan løysa nokre feil. Alle godkjenningar vert ugilde - Vis alle - Ugildt domene - Vel område - Tøm heile historikken - Tømte historikken - Ingen bokmerke endå - Du kan lage bokmerke medan du les - Tok bort bokmerka - Ingen mangakjelder - Slå på minst ei mangakjelde for å lesa mangaar på nett - Tilfeldig - Flytt - Tom - Trykk Attende att for å gå or appen - Utgåingsstadfesting - Mellominnet for sider - Mellomminnet for anna - Tilgjengeleg - %s - %s - Teken or likerlista - Fann ikkje innhaldet - Bla sjølvverkande - Teikneseriearkiv - Mappe med bilete - Fører inn manga - Brigd letar - Ljosstyrk - Still attende - Spar eller avvis dei usparte brigda\? - Avvis - Eininga er fylt - Vis ei rulleline til blading - Auk/mink nettseriar - Ulike mål - Nettverk ikkje tilgjengeleg - Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett - Tjenarfeil (%1$d). Røyn att seinare - Kjelde avslegen - Hent inn innhald på forhand - Merk som aktuelt - Mål - Del loggføringar - Slå på loggføring - Tak opp nokre gjerder til bruk i istandsetjing. - Skiftande - Letar - Vis som rutenett - Rikka - Asuka - Sakura - Mamimi - Kanade - Ingenting her - Tenester - Har byrja å hente - Tøm søkehistorikken\? - Velkomen - Du vert logga ut ifrå alle kjeldane - Hindre ved vakse innhald - Slett - Her var det tomt … - Spør om lykelordet ved byrjing av appen - Feil lykelord - Vern appen - Logg inn for å sjå dette innhaldet - Vern appen med eit lykelord - All data vert handsama på eininga di og vert ikkje førte over til noka teneste - Avslegen - Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. - Aldri - Berre på Wi-Fi - 18+ - Alltid - Hent sider på forhand - Utsjånad - Slett valde ting ifrå eininga di\? - Logga inn som %s - Opplys om kva slags slag du ikkje vil få råd om - Synkronisering - Nye mangakjelder tilgjengelege - Du kjem til å få varsel når mangaar du les vert oppdaterte - Slå på varsel - La til eit bokmerke - Tok bort bokmerket - Angre - Nytt fingermerke om tilgjengeleg - Vis leseframgang - Mangaar du likar - Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart - Slett dei valde hopane\? + Det hende ein feil + Rutenett + Innstillingar + Mangakjelder + Tøm historikken + Historikken er tom + Les + Lik + Ny hop + Legg til + Hent + Lag ein snarveg … + Del %s + Søk + Søk manga + Hentar … + Handsamar … + Henta + Nyaste + Omdøme + Sil ut + Ljos + Sider + Tøm + Tøm lesehistorikken for godt\? + Tak bort + Hent sida + Henta + Del biletet + Før inn + Slett + Vel ei ZIP- eller CBZ-fil. + Ingen utgreiing + Tøm mellomminnet til sida + Vanleg + Nettserie + Rutenettstorleik + Slett mangaen + Slett «%s» ifrå eininga\? + Leseinnstillingar + Bla med + Hald fram + Feil + Tøm mellomminnet for småbilete + Tøm søkehistorikken + Tømt + Berre handvendingar + Hent + Varsel + %1$d av %2$d + Hent + Varselinnstillingar + Varselljod + Varselljos + Dirring + Hopar til leiting + Hent ifrå nettkjelder eller før inn filer. + Hylla + Nytt + Legg henta mangaar i: + Ferdig + Alt du likar + Tom hop + Les seinare + Oppdateringar + Søkesvar + Ny utgåve: %s + Tømt + Snu skjermen + Leit etter oppdateringar + Nei + Om + Leit etter oppdateringar + Høgre-til-venstre + Lesevising + Høv til høgda + Høv til breidda + Svart + Tryggleikskopiering og gjenoppretting + Lag ein tryggleikskopi + Gjenoppretta + Fann ikkje fila + Gjenoppretta all data + Gjenoppretta dataa, men med feil + Trykk for å røyna att + Listeslag + Henta + Likar + Historikk + Nettverksfeil + Liste + Hentar fram … + Steng + Røyn att + Fann ikkje noko + Del + Henta + Namn + Oppdatert + Vising + Lyd systemet + Mørk + Historikken og mellomminnet + Hent noko først + Ikkje tilgjengeleg + Oppdater + Storleik: %s + Brukar mindre straum på AMOLED-skjermar + Utgåve %s + Ingen tilgjengelege oppdateringar + Ny hop + Midtstill + Auk byrjinga av sida + Gjenopprett ifrå ein tryggleikskopi + Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting + Førebur … + Forval + No + I dag + I går + Lenge sida + Lesing + Randetrykk + Ljodstyrkeknappar + Ei ny utgåve av appen er tilgjengeleg + Opne i ein nettlesar + Denne mangaen har %s. Hent alle\? + Det du les vert vist her + Rit inn lykelordet + Gjentak lykelordet + Lykelorda er ulike + Brigde av oppsettet vedkjem berre denne mangaen + Stille + Krev CAPTCHA + Løys + Slett infokapslane + Sletta infokapslane + Tøm oppdateringshistorikken\? + Logg inn + Neste + Stadfest + Lykelordet må vera lengre enn fire teikn + Tryggleikskopi laga + Les meir + I kø + Omset denne appen + Omsetjing + Godkjend + Slag + Fullgjort + I gang + Utelèt mangaar med vakse innhald ifrå historikken + Sidetal + Nytta kjelder + Tilgjengelege kjelder + Skjermbilete + Hindre alltid + Råd + Slå på råd + Rå om mangaar ut ifrå det du har lese + Byrja å lesa nokre mangaar for å få personlege råd + Ikkje rå mangaar med vakse innhald + Påslegen + Kunne ikkje hente inn slaglista + Finn slag + Ulike mål + %1$s%% + Innhald + Oppdaterer råd + Utelat slag + Sletta + Avgrens hentesnøggleiken + Lægjer vona for at IP-adressa di vert blokkert + Handsamar henta manga + Avbroten + Kontoen finst alt + Attende + Synkroniser dataet ditt + Rit inn e-postadressa di for å halda fram + Skjul + Namn + Brigd + Brigd hopen + Sporing + Ingen likte hopar + Logg ut + Bokmerk + Tak bort bokmerket + Bokmerke + Teken bort ifrå historikken + DNS over HTTPS + Forvald lesing + Finn sjølvverkande ut av lesing + Finn sjølvverkande ut av om mangaen er ein nettserie + Slå av batterilenging + Send + Les + Skal lesa + Les att + Lesen + På vent + Gjeven opp + Slå av alle + Mangaar du har nyleg lese + Sletting av data + Vis % lesen i historikken og likerlista + Kan løysa nokre feil. Alle godkjenningar vert ugilde + Vis alle + Ugildt domene + Vel område + Tøm heile historikken + Tømte historikken + Ingen bokmerke endå + Du kan lage bokmerke medan du les + Tok bort bokmerka + Ingen mangakjelder + Slå på minst ei mangakjelde for å lesa mangaar på nett + Tilfeldig + Flytt + Tom + Trykk Attende att for å gå or appen + Utgåingsstadfesting + Mellominnet for sider + Mellomminnet for anna + Tilgjengeleg + %s - %s + Teken or likerlista + Fann ikkje innhaldet + Bla sjølvverkande + Teikneseriearkiv + Mappe med bilete + Fører inn manga + Brigd letar + Ljosstyrk + Still attende + Spar eller avvis dei usparte brigda\? + Avvis + Eininga er fylt + Vis ei rulleline til blading + Auk/mink nettseriar + Ulike mål + Nettverk ikkje tilgjengeleg + Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett + Tjenarfeil (%1$d). Røyn att seinare + Kjelde avslegen + Hent inn innhald på forhand + Merk som aktuelt + Mål + Del loggføringar + Slå på loggføring + Tak opp nokre gjerder til bruk i istandsetjing. + Skiftande + Letar + Vis som rutenett + Rikka + Asuka + Sakura + Mamimi + Kanade + Ingenting her + Tenester + Har byrja å hente + Tøm søkehistorikken\? + Velkomen + Du vert logga ut ifrå alle kjeldane + Hindre ved vakse innhald + Slett + Her var det tomt … + Spør om lykelordet ved byrjing av appen + Feil lykelord + Vern appen + Logg inn for å sjå dette innhaldet + Vern appen med eit lykelord + All data vert handsama på eininga di og vert ikkje førte over til noka teneste + Avslegen + Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. + Aldri + Berre på Wi-Fi + 18+ + Alltid + Hent sider på forhand + Utsjånaden + Slett valde ting ifrå eininga di\? + Logga inn som %s + Opplys om kva slags slag du ikkje vil få råd om + Synkronisering + Nye mangakjelder tilgjengelege + Du kjem til å få varsel når mangaar du les vert oppdaterte + Slå på varsel + La til eit bokmerke + Tok bort bokmerket + Angre + Nytt fingermerke om tilgjengeleg + Vis leseframgang + Mangaar du likar + Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart + Slett dei valde hopane\? \nDu kan ikkje angre. Alle mangaane inni vert tekne ut av likerlista. - Innstillingar - Dei siste to timane - Handsam - Trykk Attende to gongar for å gå or appen - Henta mangaar - Privat modus - Førte inn - Slett den opphavlege fila for å frigjera rom - Byrjar å føra inn snart - Motsetjing - Brigde av letane vedkjem berre denne mangaen - Vis mistenksamt innhald - Mion - Miku - Byrja om appen for å nytta desse brigda - Kapittel - Utreknar… - Kapittel %1$d av %2$d - Ustødd gjerd - B|kB|MB|GB|TB - Domene - Nye kapittel - Mangaane dine vert viste her - Siderørsle - Nye kapittel av det du les vert viste her - Sjå etter nye kapittel - Siste øvst - Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. - Hent eller les dette saknande kapittelet på nettet. - Saknar kapittelet - Finn kapittel - Ingen kapittel i denne mangaen - Kapittel vert teken bort i bakgrunnen - Sjå etter og varsle om nye kapittel - Nye kapittel vert merkte i listene utan varsel - Gransk - Ingen kapittel - Ka. %1$d/%2$d Side %3$d/%4$d - Vis opplysingsområde i lesevisinga - Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side - Samantrengt - Vis i hylla - Før inn ei tryggleikskopi av brukardata - Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. - Snøggleik - Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. - Tøm au opplysingar om nye kapittel - Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. - Skjønar - Trykk og hald på eit element for å flytta på det - + Innstillingar + Dei siste to timane + Handsam + Trykk Attende to gongar for å gå or appen + Henta mangaar + Privat modus + Førte inn + Slett den opphavlege fila for å frigjera rom + Byrjar å føra inn snart + Motsetjing + Brigde av letane vedkjem berre denne mangaen + Vis mistenksamt innhald + Mion + Miku + Byrja om appen for å nytta desse brigda + Kapittel + Utreknar… + Kapittel %1$d av %2$d + Ustødd gjerd + B|kB|MB|GB|TB + Domene + Nye kapittel + Mangaane dine vert viste her + Siderørsle + Nye kapittel av det du les vert viste her + Sjå etter nye kapittel + Siste øvst + Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. + Hent eller les dette saknande kapittelet på nettet. + Saknar kapittelet + Finn kapittel + Ingen kapittel i denne mangaen + Kapittel vert teken bort i bakgrunnen + Sjå etter og varsle om nye kapittel + Nye kapittel vert merkte i listene utan varsel + Gransk + Ingen kapittel + Ka. %1$d/%2$d Side %3$d/%4$d + Vis opplysingsområde i lesevisinga + Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side + Samantrengt + Vis i hylla + Før inn ei tryggleikskopi av brukardata + Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. + Snøggleik + Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. + Tøm au opplysingar om nye kapittel + Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. + Skjønar + Trykk og hald på eit element for å flytta på det + Sletta «%s» ifrå eininga + Indre gøyme + Ytre gøyme + Ingen tilgjengelege gøyme + Anna gøyme + Røyn å skriva det om. + Ingen likte enno + Mest lest for tida + Søk på %s + Finn lesnadar i sidemenyen. + Finn lesnadar i «Gransk»-delen + \ No newline at end of file From c6228d3fe18b97794642205193fbfb36d3a3243f Mon Sep 17 00:00:00 2001 From: Subham Jena Date: Mon, 5 Jun 2023 11:53:38 +0200 Subject: [PATCH 46/90] Translated using Weblate (Odia) Currently translated at 7.3% (31 of 421 strings) Translated using Weblate (Odia) Currently translated at 5.5% (23 of 416 strings) Co-authored-by: Subham Jena Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/or/ Translation: Kotatsu/Strings --- app/src/main/res/values-or/strings.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index d8db4f084..b55162b4b 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -11,4 +11,19 @@ ଥିମ୍ ଵେଗ ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା + ପାଠକ ସେଟିଂ + ଵିଜ୍ଞପ୍ତି + ଥାକ + ସର୍ଵଦା + ଵିଷୟଵସ୍ତୁ + ଵିଜ୍ଞପ୍ତି ସେଟିଂ + ରୂପ + ଯାଞ୍ଚ କରନି + ଅଦ୍ୟତନ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଗତକାଲି + ଆଜି + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରି ଏହା ଵିଷୟରେ ସୂଚିତ କରିବା + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଫାଇଲ ମିଳୁନାହିଁ + ବ୍ୟାକଅପ୍ ଓ ପୁନରୁଦ୍ଧାର \ No newline at end of file From 96b6900c7001057cba55e44c195ca0f812527f49 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Mon, 5 Jun 2023 11:53:39 +0200 Subject: [PATCH 47/90] Translated using Weblate (Spanish) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (422 of 422 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (7 of 7 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (417 of 417 strings) Co-authored-by: gallegonovato Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/es/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/ Translation: Kotatsu/Strings Translation: Kotatsu/plurals --- app/src/main/res/values-es/plurals.xml | 6 +++--- app/src/main/res/values-es/strings.xml | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-es/plurals.xml b/app/src/main/res/values-es/plurals.xml index 3deb92806..f5f4a4cbb 100644 --- a/app/src/main/res/values-es/plurals.xml +++ b/app/src/main/res/values-es/plurals.xml @@ -1,9 +1,9 @@ - Total de %1$d página - Total de %1$d páginas - Total de %1$d páginas + Página total %1$d + Páginas totales %1$d + Página totales %1$d %1$d elemento diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 613c1c1f1..ae1169138 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -412,4 +412,18 @@ ¿Quieres recibir sugerencias sobre mangas personalizadas\? Traducciones WebView no está disponible: comprueba si el proveedor de WebView está instalado + Borrar la caché de la red + Tipo + Dirección + Puerto + Proxy + Valor no válido + %1$s (%2$s) + Optimización de imágenes proxy + Nombre de usuario + Descargado + Autorización (opcional) + Utiliza el servicio wsrv.nl para reducir el uso del tráfico y acelerar la carga de imágenes si es posible + Contraseña + Invertir los colores \ No newline at end of file From ff2cf9d18a558fea131f100c48ba90c79870f0d2 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 5 Jun 2023 11:53:39 +0200 Subject: [PATCH 48/90] Translated using Weblate (Turkish) Currently translated at 100.0% (431 of 431 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Turkish) Currently translated at 99.7% (416 of 417 strings) Co-authored-by: Bai Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/ Translation: Kotatsu/Strings --- app/src/main/res/values-tr/strings.xml | 802 +++++++++++++------------ 1 file changed, 427 insertions(+), 375 deletions(-) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index e5685c1b8..fdefd45bb 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,378 +1,430 @@ - Ağ hatası - Dahili Depolama - Favoriler - Geçmiş - Bölümler - Liste - Detaylı liste - Izgara - Liste modu - Yükleniyor… - Kapat - Tekrar dene - Geçmişi temizle - Hiçbir şey bulunamadı - Geçmiş yok - Oku - Henüz favorileriniz yok - Favoriniz - Yeni kategori - Ekle - Kaydet - Paylaş - %s Paylaş - Ara - Manga ara - İndiriliyor… - İşleniyor… - İndirildi - İndirilenler - Ad - Güncellenme - Yeniler - Puanlama - Litre - Tema - Açık - Koyu - Takip sistemi - Sayfalar - Temizle - Tüm okuma geçmişi kalıcı olarak silinsin mi\? - Kaldır - “%s” yerel depolama alanından sil - Sayfayı kaydet - Resmi paylaş - Popüler - Detaylar - Ayarlar - Kaydet - Bir hata oluştu - Uzak kaynaklar - Geçmiş ve önbellek - Temizlendi - Devam - Müsait değil - Boş kategori - Kaldır - Sil - Bölüm %1$d / %2$d - Bir ZIP veya CBZ dosyası seçin. - Okuma modu - Izgara boyutu - Webtoon - B|kB|MB|GB|TB - Okuyucu ayarları - Ses butonları - Hata - Küçük resim önbelleğini temizle - Yalnızca hareketler - Alan adi - Web tarayıcısında aç - Yeni bölümler - Bildirim ayarları - Bildirim sesi - LED göstergesi - Titreşim - Diğer depolama - Güncellemeler - Kısayol oluştur… - İçe aktar - Mangayı sil - Bilgi işleniyor… - Sıralama düzeni - Açıklama yok - Bu işlem desteklenmiyor - Standart - Sayfa önbelleğini temizle - %s üzerinde ara - Dahili depolama - Bildirimler - Sayfaları değiştir - Kaydet - İndir - İndirilenler klasörü - Harici depolama - Uygulamanın yeni bir sürümü mevcut - Favori kategoriler - Bitti - Sonra oku - Sayfa animasyonu - Kullanılabilir depolama alanı yok - “%s” cihazdan kalıcı olarak silinsin mi\? - Arama geçmişini temizle - Burası biraz boş… - Ekranı döndür - Ölçek modu - Yüksekliğe sığdır - Siyah - Başlangıçta tut - Akışı temizle - Bu eksik bölümü çevrim içi olarak indirin veya okuyun. - Yedekten geri yükle - Güncelle - Oturum aç - Bitti - Hakkında - Bu içeriği görüntülemek için oturum açın - Onayla - Yetkilendirildi - Az önce - Kenar dokunuşları - Bu mangada %s var. Hepsi kaydedilsin mi\? - %1$d / %2$d açık - Sorguyu yeniden biçimlendirmeyi deneyin. - Okuduklarınız burada görüntülenecek - Yan menüde ne okuyacağınızı bulun. - Önce bir şey kaydedin - Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. - Raf - Son - Boyut: %s - Temizlendi - Parola gir - Kotatsu başlatılırken parola sor - Güncellemeleri ara - Güncelleme akışını temizle - Akış güncellemesi yakında başlayacak - Sürüm %s - Güncellemeleri denetle - Merkeze sığdır - Genişliğe sığdır - AMOLED ekranlarda daha az güç kullanır - Yedekle ve geri yükle - Veri yedeği oluştur - Geri yüklendi - Hazırlanıyor… - Dün - Grup - Sessiz - Çöz - Çerezleri temizle - Öntanımlı: %s - Ters - Parola 4 veya daha fazla karakterden oluşmalıdır - Hoş geldiniz - Sıraya alındı - Bölüm eksik - Bu uygulamayı çevirin - Çeviri - Devam ediyor - Tüm kaynaklardaki oturumunuz kapatılacak - Kullanılan kaynaklar - Kullanılabilir kaynaklar - Uygunsuz mangayı geçmişten hariç tut - Numaralı sayfalar - Arama sonuçları - Parolayı tekrarla - Denetleme - Yanlış parola - Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz - Uzun zaman önce - Bugün - Güncelleme yok - Tüm favoriler - Okuduklarınızın yeni bölümleri burada gösterilir - Yeni sürüm: %s - Uygulamayı koru - Parolalar eşleşmiyor - Sağdan-sola - Yeni kategori - Dosya bulunamadı - Tüm veriler geri yüklendi - Veriler geri yüklendi, ancak hatalar var - Tekrar denemek için dokunun - İleri - CAPTCHA gerekli - Tüm çerezler kaldırıldı - Seçilen yapılandırma bu manga için hatırlanacak - Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? - Uygulamayı başlatmak için bir parola girin - Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? - Yedek kaydedildi - Türler - Öntanımlı - %s üzerinde oturum açma desteklenmiyor - Daha fazla oku - Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. - Ekran görüntüsü politikası - Uygunsuzlarda engelle - Her zaman engelle - İzin ver - Yeni bölümleri denetle - Öneriler - Önerileri etkinleştir - Tercihlerinize göre manga önerileri alın - Tüm veriler aygıt üzerinde yerel olarak işlenir. Kişisel verilerinizin herhangi bir hizmete aktarılması söz konusu değildir - Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız - Uygunsuz manga önerme - Etkin - Devre dışı - Türler listesi yüklenemiyor - Filtreyi sıfırla - Tür bul - Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. - Her zaman - Hiçbir zaman - Yalnızca Wi-Fi\'de - Sayfaları önceden yükle - %s olarak oturum açıldı - 18+ - Çeşitli diller - Bölüm bul - Bu mangada bölüm yok - %%%1$s - İçerik - Öneriler güncelleniyor - Görünüm - Türleri hariç tut - Önerilerde görmek istemediğiniz türleri belirtin - Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? - Kaldırma tamamlandı - Bölümler arka planda kaldırılacaktır. Bu biraz zaman alabilir - İndirmeyi yavaşlat - IP adresinizin engellenmesinden kaçınmanıza yardımcı olur - Kaydedilen manga işleme - Gizle - Yeni manga kaynakları var - Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak - Bildirimleri etkinleştir - Yeni bölümleri denetle ve bildirim gönder - Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız - Favori kategori yok - Ad - Düzenle - Kategoriyi düzenle - Yer imi ekle - Yer imini kaldır - Yer imleri - Yer imi kaldırıldı - Yer imi eklendi - Geri al - Geçmişten kaldırıldı - HTTPS üzerinden DNS - Okuyucu modunu otomatik algıla - Manganın webtoon olup olmadığını otomatik olarak algıla - Öntanımlı mod - Pil iyileştirmesini devre dışı bırak - Arka planda güncelleme denetimlerine yardımcı olur - Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. - Gönder - Tümünü devre dışı bırak - Varsa parmak izi kullan - Favorilerinizden mangalar - Son okuduğunuz mangalar - Bildir - İzleme - Oturumu kapat - Okunuyor - Tamamlandı - Okuma ilerleme göstergelerini göster - Verileri sil - Geçmişte ve favorilerde okunma yüzdesini göster - Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir - Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır - Beklemede - Bırakıldı - Planlandı - Yeniden okunuyor - Tümünü göster - Geçersiz etki alanı - Aralık seç - İçerik bulunamadı veya kaldırıldı - Manganız burada görüntülenecek - İptal edilmiş - Hesap zaten var - Geri - Senkronizasyon - Verini yedekle - Devam etmek için E-Postanızı girin - Tüm gecmişi temizle - Son 2 saat - Geçmiş temizlendi - Yönet - Yer işareti yok - Manga okurken yer işareti oluşturabilirsiniz - Yer işaretleri kaldırıldı - Manga kaynağı yok - Çevrimiçi manga okumak için manga kaynaklarını aktif edin - Rastgele - Boş - Keşfet - Çıkmak için tekrar Geri tıkla - Çıkmak için iki defa Geri tıkla - Favorilerden kaldırıldı - Çıkış doğrulaması - Çizgi roman arşivi - Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. Mevcutsa, geliştiricilere bir hata reporu gönderin. - «Keşfet» kısmında neler okuyacağınızı bulun - Seçilen favori kategorileri silmek istediğinizden emin misiniz\? + Ağ hatası + Dahili Depolama + Favoriler + Geçmiş + Bölümler + Liste + Detaylı liste + Izgara + Liste modu + Yükleniyor… + Kapat + Tekrar dene + Geçmişi temizle + Hiçbir şey bulunamadı + Geçmiş yok + Oku + Henüz favorileriniz yok + Favoriniz + Yeni kategori + Ekle + Kaydet + Paylaş + %s Paylaş + Ara + Manga ara + İndiriliyor… + İşleniyor… + İndirildi + İndirilenler + Ad + Güncellenme + Yeniler + Puanlama + Litre + Tema + Açık + Koyu + Takip sistemi + Sayfalar + Temizle + Tüm okuma geçmişi kalıcı olarak silinsin mi\? + Kaldır + “%s” yerel depolama alanından sil + Sayfayı kaydet + Resmi paylaş + Popüler + Detaylar + Ayarlar + Kaydet + Bir hata oluştu + Manga kaynakları + Geçmiş ve önbellek + Temizlendi + Devam + Müsait değil + Boş kategori + Kaldır + Sil + Bölüm %1$d / %2$d + Bir ZIP veya CBZ dosyası seçin. + Okuma modu + Izgara boyutu + Webtoon + B|kB|MB|GB|TB + Okuyucu ayarları + Ses butonları + Hata + Küçük resim önbelleğini temizle + Yalnızca hareketler + Alan adi + Web tarayıcısında aç + Yeni bölümler + Bildirim ayarları + Bildirim sesi + LED göstergesi + Titreşim + Diğer depolama + Güncellemeler + Kısayol oluştur… + İçe aktar + Mangayı sil + Bilgi işleniyor… + Sıralama düzeni + Açıklama yok + Bu işlem desteklenmiyor + Standart + Sayfa önbelleğini temizle + %s üzerinde ara + Dahili depolama + Bildirimler + Sayfaları değiştir + Kaydet + İndir + İndirilenler klasörü + Harici depolama + Uygulamanın yeni bir sürümü mevcut + Favori kategoriler + Bitti + Sonra oku + Sayfa animasyonu + Kullanılabilir depolama alanı yok + “%s” cihazdan kalıcı olarak silinsin mi\? + Arama geçmişini temizle + Burası biraz boş… + Ekranı döndür + Ölçek modu + Yüksekliğe sığdır + Siyah + Başlangıçta tut + Akışı temizle + Bu eksik bölümü çevrim içi olarak indirin veya okuyun. + Yedekten geri yükle + Güncelle + Oturum aç + Bitti + Hakkında + Bu içeriği görüntülemek için oturum açın + Onayla + Yetkilendirildi + Az önce + Kenar dokunuşları + Bu mangada %s var. Hepsi kaydedilsin mi\? + %1$d / %2$d açık + Sorguyu yeniden biçimlendirmeyi deneyin. + Okuduklarınız burada görüntülenecek + Yan menüde ne okuyacağınızı bulun. + Önce bir şey kaydedin + Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. + Raf + Son + Boyut: %s + Temizlendi + Parola gir + Kotatsu başlatılırken parola sor + Güncellemeleri ara + Güncelleme akışını temizle + Akış güncellemesi yakında başlayacak + Sürüm %s + Güncellemeleri denetle + Merkeze sığdır + Genişliğe sığdır + AMOLED ekranlarda daha az güç kullanır + Yedekle ve geri yükle + Veri yedeği oluştur + Geri yüklendi + Hazırlanıyor… + Dün + Grup + Sessiz + Çöz + Çerezleri temizle + Öntanımlı: %s + Ters + Parola 4 veya daha fazla karakterden oluşmalıdır + Hoş geldiniz + Sıraya alındı + Bölüm eksik + Bu uygulamayı çevirin + Çeviri + Devam ediyor + Tüm kaynaklardaki oturumunuz kapatılacak + Kullanılan kaynaklar + Kullanılabilir kaynaklar + Uygunsuz mangayı geçmişten hariç tut + Numaralı sayfalar + Arama sonuçları + Parolayı tekrarla + Denetleme + Yanlış parola + Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz + Uzun zaman önce + Bugün + Güncelleme yok + Tüm favoriler + Okuduklarınızın yeni bölümleri burada gösterilir + Yeni sürüm: %s + Uygulamayı koru + Parolalar eşleşmiyor + Sağdan-sola + Yeni kategori + Dosya bulunamadı + Tüm veriler geri yüklendi + Veriler geri yüklendi, ancak hatalar var + Tekrar denemek için dokunun + İleri + CAPTCHA gerekli + Tüm çerezler kaldırıldı + Seçilen yapılandırma bu manga için hatırlanacak + Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? + Uygulamayı başlatmak için bir parola girin + Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? + Yedek kaydedildi + Türler + Öntanımlı + %s üzerinde oturum açma desteklenmiyor + Daha fazla oku + Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. + Ekran görüntüsü politikası + Uygunsuzlarda engelle + Her zaman engelle + İzin ver + Yeni bölümleri denetle + Öneriler + Önerileri etkinleştir + Tercihlerinize göre manga önerileri alın + Tüm veriler sadece bu cihaz üzerinde yerel olarak işlenir ve asla herhangi bir yere satılmaz. + Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız + Uygunsuz manga önerme + Etkin + Devre dışı + Türler listesi yüklenemiyor + Filtreyi sıfırla + Tür bul + Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. + Her zaman + Hiçbir zaman + Yalnızca Wi-Fi\'de + Sayfaları önceden yükle + %s olarak oturum açıldı + 18+ + Çeşitli diller + Bölüm bul + Bu mangada bölüm yok + %%%1$s + İçerik + Öneriler güncelleniyor + Görünüm + Türleri hariç tut + Önerilerde görmek istemediğiniz türleri belirtin + Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? + Kaldırma tamamlandı + Bölümler arka planda kaldırılacak. + İndirmeyi yavaşlat + IP adresinizin engellenmesinden kaçınmanıza yardımcı olur + Kaydedilen manga işleme + Gizle + Yeni manga kaynakları var + Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak + Bildirimleri etkinleştir + Yeni bölümleri denetle ve bildirim gönder + Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız + Favori kategori yok + Ad + Düzenle + Kategoriyi düzenle + Yer imi ekle + Yer imini kaldır + Yer imleri + Yer imi kaldırıldı + Yer imi eklendi + Geri al + Geçmişten kaldırıldı + HTTPS üzerinden DNS + Okuyucu modunu otomatik algıla + Manganın webtoon olup olmadığını otomatik olarak algıla + Öntanımlı mod + Pil iyileştirmesini devre dışı bırak + Arka planda güncelleme denetimlerine yardımcı olur + Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. + Gönder + Tümünü devre dışı bırak + Varsa parmak izi kullan + Favorilerinizden mangalar + Son okuduğunuz mangalar + Bildir + İzleme + Oturumu kapat + Okunuyor + Tamamlandı + Okuma ilerleme göstergelerini göster + Verileri sil + Geçmişte ve favorilerde okunma yüzdesini göster + Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir + Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır + Beklemede + Bırakıldı + Planlandı + Yeniden okunuyor + Tümünü göster + Geçersiz etki alanı + Aralık seç + İçerik bulunamadı veya kaldırıldı + Manganız burada görüntülenecek + İptal edilmiş + Hesap zaten var + Geri + Senkronizasyon + Verini yedekle + Devam etmek için E-Postanızı girin + Tüm gecmişi temizle + Son 2 saat + Geçmiş temizlendi + Yönet + Yer işareti yok + Manga okurken yer işareti oluşturabilirsiniz + Yer işaretleri kaldırıldı + Manga kaynağı yok + Çevrimiçi manga okumak için manga kaynaklarını aktif edin + Rastgele + Boş + Keşfet + Çıkmak için tekrar Geri tıkla + Çıkmak için iki defa Geri tıkla + Favorilerden kaldırıldı + Çıkış doğrulaması + Çizgi roman arşivi + Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. <a href=kotatsu://about> Kotatsunun son sürümünü kullandığnızdan emin olun.</a>/br> 3. Mevcutsa, geliştiricilere bir hata reporu gönderin. + «Keşfet» kısmında neler okuyacağınızı bulun + Seçilen favori kategorileri silmek istediğinizden emin misiniz\? \nİçindeki tüm mangalar kaybolur ve bu işlem geri alınamaz. - Yeniden sırala - Sayfa önbelleği - Diğer önbellekler - Depolama kullanımı - Mevcut - %s - %s - Seçenekler - Gizli mod - Bölüm yok - Otomatik kaydır - Böl. %1$d/%2$d Sayf. %3$d/%4$d - Okuyucuda bilgi çubuğu göster - Resimlerle klasör - Manga içe aktarılıyor - İçe aktarım tamamlandı - Yer açmak için orijinal dosyayı depolamadan silebilirsiniz - İçe aktarım birazdan başlayacak - Akış - En son manga kısayollarını göster - Ergonomik okuyucu kontrol - Renk düzeltme - Parlaklık - Kontrast - Sıfırla - Seçilen renk ayarları bu manga için hatırlanacaktır - Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? - Yoksay - Cihazda yer yok - Webtoon yakınlaştırma - Sayfa değiştirme kaydırıcısını göster - Ayrıca yeni bölümler hakkındaki bilgileri temizle - Sıkı - Farklı diller - Ağ kullanılamıyor - Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın - Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin - Kaydedilen mangalar - Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin - Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir - Kaynak devre dışı - İçerik ön yüklemesi - Geçerli olarak işaretle - Dil - Günlükleri paylaş - Günlük kaydını etkinleştir - Hata ayıklama amacıyla bazı eylemleri kaydedin - Şüpheli içeriği göster - Hizmetler - Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. - burada hiçbir şey yok - Dinamik - renk vurgusu - Izgara görünümünde göster - Mamimi - Kanade - UserAgent başlığı - Uygulamanın beta sürümleri için güncellemeler öner - Kararsız güncellemelere izin ver - İndirme başladı - Miku - Asuka - Mion - Rikka - Sakura - Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın - + Yeniden sırala + Sayfa önbelleği + Diğer önbellekler + Depolama kullanımı + Mevcut + %s - %s + Seçenekler + Gizli mod + Bölüm yok + Otomatik kaydır + Böl. %1$d/%2$d Sayf. %3$d/%4$d + Okuyucuda bilgi çubuğu göster + Resimlerle klasör + Manga içe aktarılıyor + İçe aktarım tamamlandı + Yer açmak için orijinal dosyayı depolamadan silebilirsiniz + İçe aktarım birazdan başlayacak + Akış + En son manga kısayollarını göster + Ergonomik okuyucu kontrol + Renk düzeltme + Parlaklık + Kontrast + Sıfırla + Seçilen renk ayarları bu manga için hatırlanacaktır + Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? + Yoksay + Cihazda yer yok + Webtoon yakınlaştırma + Sayfa değiştirme kaydırıcısını göster + Ayrıca yeni bölümler hakkındaki bilgileri temizle + Sıkı + Farklı diller + Ağ kullanılamıyor + Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın + Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin + Kaydedilen mangalar + Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin + Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir + Kaynak devre dışı + İçerik ön yüklemesi + Geçerli olarak işaretle + Dil + Günlükleri paylaş + Günlük kaydını etkinleştir + Hata ayıklama amacıyla bazı eylemleri kaydedin + Şüpheli içeriği göster + Hizmetler + Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. + burada hiçbir şey yok + Dinamik + renk vurgusu + Izgara görünümünde göster + Mamimi + Kanade + UserAgent başlığı + Uygulamanın beta sürümleri için güncellemeler öner + Kararsız güncellemelere izin ver + İndirme başladı + Miku + Asuka + Mion + Rikka + Sakura + Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın + Benzerini bul + Çeviriler + WebView kullanılamıyor: WebView sağlayıcısının kurulu olup olmadığını kontrol edin + Etkinleştir + Hayır teşekkürler + İnternet geçmişini temizle + Eşitleme seçenekleri + Sunucu adresi + "Şirket içinde barındırılan bir eşitleme sunucusu veya varsayılan bir sunucu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin." + Yansıtmalar varsa, hatalarda uzak kaynaklar için etki alanlarını otomatik olarak değiştir + Mobil ağa geçerken indirmeyi durdur + Bitirilenleri kaldır + Hepsini iptal et + Sadece Wi-Fi ile indir + Anladım + Yeniden sıralamak için bir öğeye dokunun ve basılı tutun + Bir veya daha fazla .cbz veya .zip dosyası seçebilirsiniz, her dosya ayrı bir manga olarak tanınacaktır. + Arşivler veya resimler içeren bir dizin seçebilirsiniz. Her arşiv (veya alt dizin) bir bölüm olarak tanınacaktır. + Hız + Kullanıcı verilerinin önceden oluşturulmuş bir yedeğini içe aktarın + Rafta Göster + Mevcut bir hesapta oturum açabilir veya yeni bir hesap oluşturabilirsiniz. + SSL hatalarını görmezden gel + Durdur + Devam et + Durduruldu + Öneri:%s + Bazen manga öneri bildirimlerilerini göster + Daha fazla + Tüm aktif indirmeler iptal edilecek, kısmen indirilen veriler kaybolacak + İndirme geçmişin tamamen silinecek + Hiçbir indirmeniz yok + İndirmeler devam ettirildi + İndirmeler durduruldu + İndirmeler silindi + Aynayı otomatik olarak seç + İndirmeler iptal edildi + Kişiselleştirilmiş manga önerileri almak istiyor musunuz\? + Adres + Tür + %1$s (%2$s) + Menü + Proxy + Geçersiz değer + Geçersiz port numarası + Renkleri ters çevir + Görüntü optimizasyon proxy\'si + Şifre + Doğrulama (isteğe bağlı) + İndirildi + Trafik kullanımını azaltmak ve mümkünse resim yüklemeyi hızlandırmak için wsrv.nl hizmetini kullanın + Kullanıcı adı + \ No newline at end of file From c14b2ceeff5457fcc5fd570d1fc799092af622f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D0=B0=D1=80=20=D0=A0=D0=B0=D0=B7=D0=B8?= =?UTF-8?q?=D0=BD?= Date: Mon, 5 Jun 2023 11:53:40 +0200 Subject: [PATCH 49/90] Translated using Weblate (Ukrainian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (431 of 431 strings) Translated using Weblate (Russian) Currently translated at 100.0% (431 of 431 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (431 of 431 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Russian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Polish) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Russian) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (French) Currently translated at 100.0% (421 of 421 strings) Co-authored-by: Макар Разин Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pl/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/ Translation: Kotatsu/Strings --- app/src/main/res/values-be/strings.xml | 10 + app/src/main/res/values-fr/strings.xml | 5 + app/src/main/res/values-pl/strings.xml | 768 ++++++++++++++----------- app/src/main/res/values-ru/strings.xml | 15 + app/src/main/res/values-uk/strings.xml | 15 + 5 files changed, 463 insertions(+), 350 deletions(-) diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 8c17722f5..dec1c2e78 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -417,4 +417,14 @@ Порт Проксі Ачысціць сеткавы кэш + %1$s (%2$s) + Няправільнае значэнне + Спампавана + Проксі для аптымізацыі малюнкаў + Імя карыстальніка + Няправільны нумар порта + Аўтарызацыя (неабавязкова) + Выкарыстоўвайце службу wsrv.nl, каб паменшыць выкарыстанне трафіку і паскорыць загрузку малюнкаў, калі гэта магчыма + Пароль + Інвертаваць колеры \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 758eedf94..cd7193ee6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -412,4 +412,9 @@ Voulez-vous recevoir des suggestions de mangas personnalisées \? WebView non disponible : vérifier si le fournisseur WebView est installé Traductions + Effacer le cache réseau + Taper + Adresse + Port + Proxy \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c42b524c2..9dc982b98 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,352 +1,420 @@ - Ulubione - Historia - Napotkano błąd - Szczegółowy - Rozdziały - Lista - Lista szczegółowa - Siatka - Tryb listy - Ustawienia - Ładowanie… - Rozdział %1$d z %2$d - Zamknij - Wyczyść historię - Dodaj - Zapisz - Udostępnij - Szukaj - Szukaj mang - Pobieranie… - Pobrano - Pobrane - Nazwa - Popularność - Najnowsze - Ocena - Filtry - Jasny - Ciemny - Strony - Wyczyść - Usuń - Udostępnij zdjęcie - Usuń - Brak opisu - Tryb czytania - Błąd sieci - Obliczanie… - Spróbuj ponownie - Nic nie znaleziono - Brak historii - Czytaj - Brak ulubionych - Dodaj do ulubionych - Nowa kategoria - Stwórz skrót - Udostępnij %s - Przetwarzanie… - Zaktualizowane - Zapisz stronę - Zapisano - Wibracje - Biblioteka - Ostatnie - Tryb czarny - Przygotowywanie… - Plik nieznaleziony - Wczoraj - Dawno temu - Grupa - Dzisiaj - Zaloguj - Dalej - Potwierdź - Witaj - Skończone - W trakcie - Zezwól - Proponowane - Włącz propozycje - Włączone - Wyłączone - Nigdy - Zawsze - Znajdź rozdział - %1$s%% - Wygląd - Schowaj - Synchronizacja - Synchronizuj swoje dane - Nazwa - Edytuj - Wyloguj - Cofnij - Wyślij - Planowane - Czytane - Czytane ponownie - Skończone - Pokaż wszystkie - Wybierz zakres - Wyczyść całą historię - Ostatnie 2 godziny - Historia wyczyszczona - Zarządzaj - Losowe - Puste - Przeglądaj - Dostępne - Ustawienia - Źródło wyłączone - Kompaktowy - Błąd po stronie serwera (%1$d). Sprónuj ponownie później - Sieć niedostępna - Inne języki - Odrzuć - Jasność - Kontrast - Korekcja kolorów - Automatyczne przewijanie - Brak rozdziałów - Tryb incognito - Usunięto z ulubionych - Wykorzystana pamięć - Zapisane mangi - Brak zakładek - Możesz tworzyć zakładki w trakcie czytania mangi - Zakładki usunięte - Twoje ostatnio czytane mangi - Wyłącz wszystkie - Wyłącz optymalizację baterii - Autowykrywanie trybu czytania - Usunięte z historii - Dodano zakładkę - Usunięto zakładkę - Zakładki - Usuń zakładkę - Dodaj zakładkę - Brak ulubionych kategorii - Edytuj kategorię - Włącz powiadomienia - Wróć - Konto już istnieje - Anulowano - Zwolnienie pobierania - Brak rozdziałów w tej mandze - Różne języki - Tylko na Wi-Fi - Zawsze blokuj - Gatunki - Znajdź gatunek - Czytaj więcej - Rozwiąż - Wymagane CAPTCHA - Cichy - Dotknij aby spróbować ponownie - Teraz - Przywrócone - Dopasuj do szerokości - Dopasuj do wysokości - Dopasuj do środka - Nowa kategoria - Brak nowych aktualizacji - Sprawdź dostępność aktualizacji - Wersja %s - O aplikacji - Usuń - Jest tu dosyć pusto… - Ulubione kategorie - Powiadomienie LED - Nowe rozdziały - Pamięć wewnętrzna - Tutaj będą wyświetlane Twoje mangi - Znajdź materiały do czytania w zakładce „Przeglądaj” - W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz - Strony w pamięci podręcznej - Animacja przewracania strony - Inne rzeczy w pamięci podręcznej - Otwórz w przeglądarce - Numerowane strony - Powiadomienia - Dźwięk powiadomień - Ustawienia powiadomień - Zewnętrzne źródła - Motyw - Systemowy - Historia i pamięć podręczna - Wyczyść pamięć podręczną stron - B|kB|MB|GB|TB - Wielkość siatki - Szukaj na %s - Usuń mangę - Dalej - Błąd - Wyczyszczone - Pamięć wewnętrzna - Pamięć zewnętrzna - Domena - Nowa wersja aplikacji jest dostępna - Ta manga ma %s. Zapisać wszystko? - Zapisz - Pobierz - Najpierw coś zapisz - Niedostępne - Zapisz - Wszystkie ulubione - Pusta kategoria - Czytaj później - Aktualizacje - Nowa wersja: %s - Wielkość: %s - Obróć ekran - Odśwież - Szukaj aktualizacji - Nie sprawdzaj - Wprowadź hasło - Złe hasło - Chroń aplikację - Pytaj o hasło przy starcie Kotatsu - Wprowadź ponownie hasło - Zużywa mniej prądu na ekranach AMOLED - Kopia zapasowa i przywracanie - Utwórz kopię zapasową danych - Przywróć z kopii zapasowej - 18+ - %1$d na %2$d włączone - Standardowy - Webtoon - Ustawienia czytnika - Zmiana strony - Przyciski głośności - Dotknięcie krawędzi - Wyczyszczone - Tryb skalowania - Wyczyść ciasteczka - Wszystkie ciasteczka wyczyszczone - Przetłumacz tą aplikację - Tłumaczenie - Dostępne źródła - Tylko gesty - Brak dostępnej pamięci - Inny - Wyniki wyszukiwania - Wszystkie dane zostały przywrócone - Dane zostały przywrócone, ale z błędami - Od tyłu - Domyślny - Polityka zrzutów ekranu - Wyklucz gatunki - Określ gatunki, których nie chcesz widzieć w sugestiach - Zalogowano jako %s - Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. - Zgłoś - Usuwanie danych - Nieważna domena - Zmień kolejność - Potwierdzenie wyjścia - %s - %s - Rozdz. %1$d/%2$d Str. %3$d/%4$d - Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online - Importuj - Wybierz plik ZIP lub CBZ. - Wyczyść historię wyszukiwania - Ta operacja nie jest obsługiwana - Tryb sortowania - Treści - Nie można załadować listy gatunków - Wstrzymane - Porzucone - Użyj odcisku palca, jeśli jest dostępny - Mangi z Twoich ulubionych - Pokaż wskaźniki postępu czytania - Pokaż procent przeczytania w historii i ulubionych - Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane - DNS przez HTTPS - Tryb domyślny - Trwale wyczyścić całą historię czytania? - „%s” usunięte z pamięci lokalnej - Wyczyść tablicę aktualizacji - Tablica - Usunąć trwale „%s” z urządzenia? - Wyczyść pamięć podręczną miniatur - Spróbuj przeformułować zapytanie. - To co czytasz będzie wyświetlane tutaj - Znajdź to, co warto przeczytać, w menu bocznym. - Zapisz ze źródeł online lub zaimportuj pliki. - Folder pobranych - Aktualizacja tablicy rozpocznie się wkrótce - Niezgodne hasła - Od prawej do lewej - Trzymaj na starcie - Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją - Wybrana konfiguracja zostanie zapamiętana dla tej mangi - Wyczyść tablicę - Wyczyścić trwale całą historię aktualizacji? - Szukanie nowych rozdziałów - Zaloguj się, aby wyświetlić tę zawartość - Domyślnie: %s - Wprowadź hasło, aby uruchomić aplikację - Hasło musi mieć co najmniej 4 znaki - Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? - Zapisano kopię zapasową - Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. - W kolejce - Pobierz lub przeczytaj ten brakujący rozdział online. - Brak rozdziału - Uprawniony - Logowanie na %s nie jest obsługiwane - Zostaniesz wylogowany ze wszystkich źródeł - Wyklucz mangi NSFW z historii - Wykorzystane źródła - Zablokuj na NSFW - Proponuj mangi na podstawie Twoich preferencji - Wszystkie dane są analizowane lokalnie na tym urządzeniu. Twoje dane osobowe nie są przekazywane do żadnych usług - Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie - Nie proponuj mang NSFW - Zresetuj filtr - Ładuj wstępnie strony - Aktualizowanie sugestii - Trwale usunąć wybrane elementy z urządzenia? - Usuwanie zakończone - Pomaga uniknąć blokowania Twojego adresu IP - Przetwarzanie zapisanej mangi - Rozdziały zostaną usunięte w tle. Może to zająć trochę czasu - Wpisz swój adres e-mail, aby kontynuować - Dostępne są nowe źródła mang - Sprawdzaj dostępność nowych rozdziałów i informuj o nich - Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz - Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach - Śledzenie - Automatycznie wykryj, czy manga to webtoon - Pomaga w sprawdzaniu aktualizacji w tle - Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. - Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione - Brak źródeł mang - Włącz źródła mang do czytania mang online - Czy na pewno chcesz usunąć wybrane ulubione kategorie? Wszystkie w nich mangi zostaną usunięte i nie będzie można tego cofnąć. - Naciśnij ponownie Wstecz, aby wyjść - Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji - Treść nie została znaleziona lub została usunięta - Pokaż pasek informacji w czytniku - Archiwum komiksów - Folder z obrazami - Importowanie mangi - Importowanie zakończone - Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce - Import rozpocznie się wkrótce - Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi - Pokaż ostatnie skróty do mang - Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji - Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony - Ergonomiczne sterowanie czytnikiem - Zapisać czy odrzucić niezapisane zmiany? - Brak miejsca w urządzeniu - Pokaż suwak przełączania stron - Powiększanie webtoon - Wyczyść też informacje o nowych rozdziałach - Resetuj - Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a> aby upewnić się, że jest dostępna w źródle<br>2. Jeśli jest dostępna, wyślij raport o błędzie do programistów. - + Ulubione + Historia + Napotkano błąd + Szczegółowy + Rozdziały + Lista + Lista szczegółowa + Siatka + Tryb listy + Ustawienia + Ładowanie… + Rozdział %1$d z %2$d + Zamknij + Wyczyść historię + Dodaj + Zapisz + Udostępnij + Szukaj + Szukaj mang + Pobieranie… + Pobrano + Pobrane + Nazwa + Popularność + Najnowsze + Ocena + Filtry + Jasny + Ciemny + Strony + Wyczyść + Usuń + Udostępnij zdjęcie + Usuń + Brak opisu + Tryb czytania + Błąd sieci + Obliczanie… + Spróbuj ponownie + Nic nie znaleziono + Brak historii + Czytaj + Brak ulubionych + Dodaj do ulubionych + Nowa kategoria + Stwórz skrót… + Udostępnij %s + Przetwarzanie… + Zaktualizowane + Zapisz stronę + Zapisano + Wibracje + Biblioteka + Ostatnie + Tryb czarny + Przygotowywanie… + Plik nieznaleziony + Wczoraj + Dawno temu + Grupa + Dzisiaj + Zaloguj + Dalej + Potwierdź + Witaj + Skończone + W trakcie + Zezwól + Proponowane + Włącz propozycje + Włączone + Wyłączone + Nigdy + Zawsze + Znajdź rozdział + %1$s%% + Wygląd + Schowaj + Synchronizacja + Synchronizuj swoje dane + Nazwa + Edytuj + Wyloguj + Cofnij + Wyślij + Planowane + Czytane + Czytane ponownie + Skończone + Pokaż wszystkie + Wybierz zakres + Wyczyść całą historię + Ostatnie 2 godziny + Historia wyczyszczona + Zarządzaj + Losowe + Puste + Przeglądaj + Dostępne + Ustawienia + Źródło wyłączone + Kompaktowy + Błąd po stronie serwera (%1$d). Sprónuj ponownie później + Sieć niedostępna + Inne języki + Odrzuć + Jasność + Kontrast + Korekcja kolorów + Automatyczne przewijanie + Brak rozdziałów + Tryb incognito + Usunięto z ulubionych + Wykorzystana pamięć + Zapisane mangi + Brak zakładek + Możesz tworzyć zakładki w trakcie czytania mangi + Zakładki usunięte + Twoje ostatnio czytane mangi + Wyłącz wszystkie + Wyłącz optymalizację baterii + Autowykrywanie trybu czytania + Usunięte z historii + Dodano zakładkę + Usunięto zakładkę + Zakładki + Usuń zakładkę + Dodaj zakładkę + Brak ulubionych kategorii + Edytuj kategorię + Włącz powiadomienia + Wróć + Konto już istnieje + Anulowano + Zwolnienie pobierania + Brak rozdziałów w tej mandze + Różne języki + Tylko na Wi-Fi + Zawsze blokuj + Gatunki + Znajdź gatunek + Czytaj więcej + Rozwiąż + Wymagane CAPTCHA + Cichy + Dotknij aby spróbować ponownie + Teraz + Przywrócone + Dopasuj do szerokości + Dopasuj do wysokości + Dopasuj do środka + Nowa kategoria + Brak nowych aktualizacji + Sprawdź dostępność aktualizacji + Wersja %s + O aplikacji + Usuń + Jest tu dosyć pusto… + Ulubione kategorie + Powiadomienie LED + Nowe rozdziały + Pamięć wewnętrzna + Tutaj będą wyświetlane Twoje mangi + Znajdź materiały do czytania w zakładce „Przeglądaj” + W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz + Strony w pamięci podręcznej + Animacja przewracania strony + Inne rzeczy w pamięci podręcznej + Otwórz w przeglądarce + Numerowane strony + Powiadomienia + Dźwięk powiadomień + Ustawienia powiadomień + Zewnętrzne źródła + Motyw + Systemowy + Historia i pamięć podręczna + Wyczyść pamięć podręczną stron + B|kB|MB|GB|TB + Wielkość siatki + Szukaj na %s + Usuń mangę + Dalej + Błąd + Wyczyszczone + Pamięć wewnętrzna + Pamięć zewnętrzna + Domena + Nowa wersja aplikacji jest dostępna + Ta manga ma %s. Zapisać wszystko? + Zapisz + Pobierz + Najpierw coś zapisz + Niedostępne + Zapisz + Wszystkie ulubione + Pusta kategoria + Czytaj później + Aktualizacje + Nowa wersja: %s + Wielkość: %s + Obróć ekran + Odśwież + Szukaj aktualizacji + Nie sprawdzaj + Wprowadź hasło + Złe hasło + Chroń aplikację + Pytaj o hasło przy starcie Kotatsu + Wprowadź ponownie hasło + Zużywa mniej prądu na ekranach AMOLED + Kopia zapasowa i przywracanie + Utwórz kopię zapasową danych + Przywróć z kopii zapasowej + 18+ + %1$d na %2$d włączone + Standardowy + Webtoon + Ustawienia czytnika + Zmiana strony + Przyciski głośności + Dotknięcie krawędzi + Wyczyszczone + Tryb skalowania + Wyczyść ciasteczka + Wszystkie ciasteczka wyczyszczone + Przetłumacz tą aplikację + Tłumaczenie + Dostępne źródła + Tylko gesty + Brak dostępnej pamięci + Inny + Wyniki wyszukiwania + Wszystkie dane zostały przywrócone + Dane zostały przywrócone, ale z błędami + Od tyłu + Domyślny + Polityka zrzutów ekranu + Wyklucz gatunki + Określ gatunki, których nie chcesz widzieć w sugestiach + Zalogowano jako %s + Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. + Zgłoś + Usuwanie danych + Nieważna domena + Zmień kolejność + Potwierdzenie wyjścia + %s - %s + Rozdz. %1$d/%2$d Str. %3$d/%4$d + Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online + Importuj + Wybierz plik ZIP lub CBZ. + Wyczyść historię wyszukiwania + Ta operacja nie jest obsługiwana + Tryb sortowania + Treści + Nie można załadować listy gatunków + Wstrzymane + Porzucone + Użyj odcisku palca, jeśli jest dostępny + Mangi z Twoich ulubionych + Pokaż wskaźniki postępu czytania + Pokaż procent przeczytania w historii i ulubionych + Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane + DNS przez HTTPS + Tryb domyślny + Trwale wyczyścić całą historię czytania? + „%s” usunięte z pamięci lokalnej + Wyczyść tablicę aktualizacji + Tablica + Usunąć trwale „%s” z urządzenia? + Wyczyść pamięć podręczną miniatur + Spróbuj przeformułować zapytanie. + To co czytasz będzie wyświetlane tutaj + Znajdź to, co warto przeczytać, w menu bocznym. + Zapisz ze źródeł online lub zaimportuj pliki. + Folder pobranych + Aktualizacja tablicy rozpocznie się wkrótce + Niezgodne hasła + Od prawej do lewej + Trzymaj na starcie + Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją + Wybrana konfiguracja zostanie zapamiętana dla tej mangi + Wyczyść tablicę + Wyczyścić trwale całą historię aktualizacji? + Szukanie nowych rozdziałów + Zaloguj się, aby wyświetlić tę zawartość + Domyślnie: %s + Wprowadź hasło, aby uruchomić aplikację + Hasło musi mieć co najmniej 4 znaki + Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? + Zapisano kopię zapasową + Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. + W kolejce + Pobierz lub przeczytaj ten brakujący rozdział online. + Brak rozdziału + Uprawniony + Logowanie na %s nie jest obsługiwane + Zostaniesz wylogowany ze wszystkich źródeł + Wyklucz mangi NSFW z historii + Wykorzystane źródła + Zablokuj na NSFW + Proponuj mangi na podstawie Twoich preferencji + Wszystkie dane są analizowane tylko lokalnie na tym urządzeniu i nigdy nie są nigdzie wysyłane. + Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie + Nie proponuj mang NSFW + Zresetuj filtr + Ładuj wstępnie strony + Aktualizowanie sugestii + Trwale usunąć wybrane elementy z urządzenia? + Usuwanie zakończone + Pomaga uniknąć blokowania Twojego adresu IP + Przetwarzanie zapisanej mangi + Rozdziały zostaną usunięte w tle + Wpisz swój adres e-mail, aby kontynuować + Dostępne są nowe źródła mang + Sprawdzaj dostępność nowych rozdziałów i informuj o nich + Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz + Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach + Śledzenie + Automatycznie wykryj, czy manga to webtoon + Pomaga w sprawdzaniu aktualizacji w tle + Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. + Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione + Brak źródeł mang + Włącz źródła mang do czytania mang online + Czy na pewno chcesz usunąć wybrane ulubione kategorie\? +\nWszystkie w nich mangi zostaną usunięte i nie będzie można tego cofnąć. + Naciśnij ponownie Wstecz, aby wyjść + Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji + Treść nie została znaleziona lub została usunięta + Pokaż pasek informacji w czytniku + Archiwum komiksów + Folder z obrazami + Importowanie mangi + Importowanie zakończone + Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce + Import rozpocznie się wkrótce + Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi + Pokaż ostatnie skróty do mang + Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji + Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony + Ergonomiczne sterowanie czytnikiem + Zapisać czy odrzucić niezapisane zmiany? + Brak miejsca w urządzeniu + Pokaż suwak przełączania stron + Powiększanie webtoon + Wyczyść też informacje o nowych rozdziałach + Resetuj + Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a>, aby upewnić się, że jest dostępna w swoim źródle<br>2. Upewnij się, że używasz <a href=kotatsu://about>najnowszej wersji Kotatsu</a><br>3. Jeśli jest dostępny, wyślij raport o błędzie do programistów. + Mamimi + Kanade + Usługi + Tutaj nic nie ma + By śledzić postęp w czytaniu, wybierz Menu → Śledź na ekranie detali mangi. + Znajdź podobne + Nagłówek UserAgent + Tłumaczenia + Udostępnij dzienniki + Zapisz niektóre działania do celów debugowania + Zezwól na niestabilne altualizacje + Rozumiem + Uruchom ponownie aplikację by wprowadzić te zmiany + Prędkość + Stuknij i przytrzymaj element, aby zmienić jego kolejność + Możesz wybrać jeden lub więcej plików .cbz lub .zip, każdy plik zostanie rozpoznany jako osobna manga. + Możesz wybrać katalog z archiwami lub obrazami. Każde archiwum (lub podkatalog) zostanie rozpoznane jako rozdział. + Włączać + Wstępne ładowanie treści + Oznacz jako aktualne + Włącz logowanie + Pokaż podejrzane treści + Schemat kolorów + Pokaż w widoku siatki + Miku + Dynamiczne + Asuka + Rikka + Sakura + Mion + Ignoruj błędy SSL + Wybierz lustro automatycznie + Zaimportuj utworzoną wcześniej kopię zapasową danych użytkownika + Pokaż na półce + Automatycznie przełączaj domeny dla zdalnych źródeł w przypadku błędów, jeśli dostępne są kopie lustrzane + Pauza + Wznawiać + Wstrzymane + Anulować całość + Pobieraj tylko przez Wi-Fi + Zatrzymaj pobieranie po przełączeniu na sieć komórkową + Sugestia: %s + Czasami wyświetlaj powiadomienia z sugerowaną mangą + Więcej + Nie, dziękuję + Wszystkie aktywne pobrania zostaną anulowane, częściowo pobrane dane zostaną utracone + Usuwanie zakończone + Język + Zaproponuj aktualizacje do wersji beta aplikacji + Pobieranie rozpoczęte + Ustawienia synchronizacji + Adres serwera + Możesz użyć samoobsługowego serwera synchronizacji lub serwera domyślnego. Nie zmieniaj tego, jeśli nie jesteś pewien, co robisz. + Twoja historia pobrań zostanie trwale usunięta + Nie masz żadnych pobrań + Pobieranie zostało wstrzymane + Pobieranie zostało wznowione + Pobieranie zostało anulowane + Pliki do pobrania zostały usunięte + Czy chcesz otrzymywać spersonalizowane sugestie dotyczące mangi\? + WebView niedostępny: sprawdź, czy dostawca WebView jest zainstalowany + Wyczyść pamięć podręczną sieci + Typ + Adres + Port + Proxy + Możesz zalogować się na istniejące konto lub utworzyć nowe + \ 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 3ce28e5c0..8c4ba3aa2 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -412,4 +412,19 @@ Хотите ли Вы получать персонализированные рекомендации манги\? Переводы WebView недоступен: проверьте, установлен ли провайдер WebView + Очистить сетевой кеш + Адрес + Тип + Прокси + Порт + %1$s (%2$s) + Неверное значение + Неверный номер порта + Имя пользователя + Пароль + Авторизация (необязательна) + Скачано + Прокси для оптимизации изображений + Используйте службу wsrv.nl, чтобы уменьшить использование трафика и ускорить загрузку изображений, если это возможно + Инвертировать цвета \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0304f772b..38574837e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -412,4 +412,19 @@ Хочете отримувати персоналізовані пропозиції щодо манги\? WebView недоступний: перевірте, чи встановлено провайдер WebView Переклади + Очистити мережевий кеш + Порт + Проксі + Тип + Адреса + %1$s (%2$s) + Недійсне значення + Недійсний номер порту + Використовуйте службу wsrv.nl, щоб зменшити використання трафіку та прискорити завантаження зображень, якщо це можливо + Завантажено + Проксі для оптимізації зображень + Авторизація (необов\'язково) + Пароль + Ім\'я користувача + Інвертувати кольори \ No newline at end of file From 056ef5433d60102b3b3eb0460b199697ebb682cf Mon Sep 17 00:00:00 2001 From: Reza Almanda Date: Mon, 5 Jun 2023 11:53:40 +0200 Subject: [PATCH 50/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (421 of 421 strings) Co-authored-by: Reza Almanda Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index bd3346c8a..7cda7bcce 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1,6 +1,6 @@ - Lokal + Penyimpanan lokal Favorit Riwayat Terjadi kesalahan @@ -160,7 +160,7 @@ Selalu blokir Saran Aktifkan saran - Sarankan komik berdasarkan preferensi Anda + Sarankan manga berdasarkan preferensi Anda Semua data hanya dianalisis secara lokal pada perangkat ini dan tidak pernah dikirim ke mana pun. Mulai membaca komik dan Anda akan mendapatkan saran yang dipersonalisasi Jangan menyarankan komik NSFW @@ -296,7 +296,7 @@ Folder dengan gambar Anda bisa menghapus berkas asli dari penyimpanan untuk menghemat ruang Umpan - Detail kesalahan:<br><tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka komik di browser</a> untuk memastikan komik tersedia di sumbernya<br>2. Pastikan Anda menggunakan <a href=kotatsu://about>Kotatsu versi terbaru</a><br>3. Jika tersedia, kirim laporan kesalahan ke pengembang. + Rincian error:<tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka manga di peramban web</a> untuk memastikan manga tersebut tersedia di sumbernya</a>2. Pastikan Anda menggunakan <a href= >manga versi terbaru</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Pastikan Anda menggunakan <a href=kotatsu://about>versi terbaru Kotatsu</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Kecerahan Kontras Atur Ulang @@ -375,12 +375,12 @@ Zoom webtoon Berbagai bahasa Jaringan tidak tersedia - Mengerti + Oke Ketuk dan tahan item untuk menyusun ulang Anda dapat memilih satu atau beberapa file .cbz atau .zip, setiap file akan dikenali sebagai komik terpisah. Anda dapat memilih direktori yang berisi arsip atau gambar. Setiap arsip (atau subdirektori) akan dikenali sebagai sebuah bab. Kecepatan - Impor cadangan data pengguna yang dibuat sebelumnya + Impor cadangan data pengguna yang telah dibuat sebelumnya Tampilkan di Rak Anda dapat masuk ke akun yang sudah ada atau membuat akun baru Temukan serupa @@ -401,7 +401,7 @@ Batalkan semua Berhenti mengunduh saat beralih ke jaringan seluler Saran: %s - Terkadang menampilkan notifikasi dengan komik yang disarankan + Terkadang menampilkan notifikasi dengan manga yang disarankan Lebih Semua pengunduhan yang aktif akan dibatalkan, data yang sudah terunduh sebagian akan hilang Riwayat unduhan Anda akan dihapus secara permanen @@ -410,4 +410,11 @@ Unduhan telah dijeda Unduhan telah dihapus Apakah Anda ingin menerima saran manga yang dipersonalisasi\? + Terjemahan + WebView tidak tersedia: periksa apakah penyedia WebView telah diinstal + Hapus cache jaringan + Tipe + Alamat + Port + Proksi \ No newline at end of file From 00307062261a455d66b305068bfec5ddd775bed1 Mon Sep 17 00:00:00 2001 From: Clxff H3r4ld0 <123844876+clxf12@users.noreply.github.com> Date: Mon, 5 Jun 2023 11:53:41 +0200 Subject: [PATCH 51/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (422 of 422 strings) Co-authored-by: Clxff H3r4ld0 <123844876+clxf12@users.noreply.github.com> Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 7cda7bcce..cd8f8db8a 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -148,7 +148,7 @@ Anda akan keluar dari semua sumber Genre Selesai - Berlanjut + Sedang berlangsung Standar Kecualikan komik NSFW dari riwayat Nomor halaman @@ -187,7 +187,7 @@ Hapus yang dipilih dari perangkat secara permanen\? Selesai menghapus Perlambat unduhan - Pembaruan saran + Memperbarui saran Membantu menghidari pemblokiran alamat IP Anda Bab akan dihapus di latar belakang Sembunyikan @@ -216,7 +216,7 @@ Kategori favorit Hapus Bersihkan umpan pembaruan - Kanan ke kiri + Kanan-ke-kiri Putar layar Pembaruan umpan akan dimulai Masukkan kata sandi @@ -248,8 +248,8 @@ Pas tinggi Pas lebar Balik - Antri - Diotorisasi + Mengantri + Resmi Simpan dari sumber daring atau berkas impor. Komik Anda akan ditampilkan di sini Cari apa untuk dibaca di bagian «Jelajah» @@ -354,7 +354,7 @@ Tampilkan indikator kemajuan membaca Tampilkan persentase baca dalam riwayat dan favorit Bahasa - Cobalah untuk merubah kueri. + Cobalah untuk memformulasi ulang kueri. Tetap di awal Bab. %1$d/%2$d Hal. %3$d/%4$d Aktifkan pencatatan @@ -417,4 +417,13 @@ Alamat Port Proksi + Nilai tidak valid + %1$s (%2$s) + Gunakan layanan wsrv.nl untuk mengurangi penggunaan lalu lintas dan mempercepat pemuatan gambar jika memungkinkan + Proksi pengoptimalan gambar + NamaUser + Diunduh + Balikkan warna + Kata sandi + Otorisasi (opsional) \ No newline at end of file From 50e67daea4f6174ad4e2ecb797e68e9a3121056f Mon Sep 17 00:00:00 2001 From: wr131 Date: Mon, 5 Jun 2023 11:53:41 +0200 Subject: [PATCH 52/90] Translated using Weblate (Chinese (Traditional)) Currently translated at 23.4% (99 of 422 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 99.2% (419 of 422 strings) Co-authored-by: wr131 Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hant/ Translation: Kotatsu/Strings --- app/src/main/res/values-zh-rCN/strings.xml | 7 +- app/src/main/res/values-zh-rTW/strings.xml | 191 +++++++++++---------- 2 files changed, 108 insertions(+), 90 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5b20c9e2a..6ca5165d3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -407,9 +407,14 @@ 下载被取消 你想要接收个人漫画推荐吗? 推荐:%s - 偶尔对建议的漫画显示通知 + 偶尔显示建议漫画通知 更多 所有进行中的下载都将被取消,未下载完成的数据将丢失 你的下载历史将会永久删除 你可以登陆一个已有账号或创建新账号 + 地址 + 清除网络缓存 + 代理 + 类型 + 无效值 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 9d6ec4c85..830fe30b2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,91 +1,104 @@ - 你将不会收到通知,但新的章节将在列表中突出显示 - 计算… - 再试一次 - 尚无历史记录 - 不支持这种操作 - 在 \"探索 \"部分找到要读的内容 - 从在线来源保存或导入文件。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容。 - 你的漫画将显示在这里 - 这里有点空… - 饲料更新将很快开始 - 所选择的配置将因这部漫画而被记住 - 数据被恢复了,但有错误 - 在AMOLED屏幕上使用更少的电力 - 登录后可查看此内容 - 永久地删除所有最近的搜索查询? - 永久地清除所有的更新历史? - 你将从所有来源中注销 - 從歷史中排除NSFW漫畫 - 开始阅读漫画,你会得到个性化的建议 - 根据你的喜好推荐漫画 - 指定您不希望在建议中看到的体裁 - 从设备中永久删除选定的项目? - 无法加载流派列表 - 章节将在后台被删除。这可能需要一些时间 - 检查新的章节并通知有关情况 - 有助于避免阻断你的IP地址 - 输入你的电子邮件以继续 - 有了新的漫画来源 - 自动检测漫画是否为网络漫画 - 在历史和收藏夹中显示阅读百分比 - 再次按 \"返回 \"键退出 - 本地存储 - 轻敲右边缘或按右键总是切换到下一页 - 你有未保存的修改,你想保存还是丢弃它们? - 您可以從儲存中刪除原始檔案以節省空間 - 最爱 - 章节 - 列表 - 栅格 - 设置 - 没有发现 - 选择你想看的漫画的语言。你可以在以后的设置中改变它。 - 可以在出现一些问题时提供帮助。所有授权将被视为无效 - 历史 - 发生了一个错误 - 无法连接到互联网 - 详情 - 第%1$d 。%2$d - 详细列表 - 列表模式 - 远程资源 - 正在加载… - 关闭 - 清除历史 - 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 - 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 - 你可以创建你的历史和收藏的备份并恢复它 - 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 - 所选择的颜色设置将被铭记在这部漫画中 - 要么选择ZIP或CBZ文件。 - 你可以在阅读漫画时创建书签 - 你会收到你正在阅读的漫画的更新通知 - 一些设备有不同的系统行为,这可能会破坏后台任务。 - 输入密码以启动应用程序 - 下载或在线阅读这缺失的章节。 - 在启动Kotatsu时要求输入密码 - 这部漫画中没有章节 - 你正在阅读的新章节显示在这里 - 通过长按应用程序图标来提供最近的漫画 - 这部漫画有%s 。全部保存? - 新版本的应用程序已经推出 - 密码必须是4个字符或以上 - 不支持在%s 上登录 - \"%s\" 从本地存储中删除 - 按两次 \"返回 \"键,退出应用程序 - 启用漫画来源,在线阅读漫画 - 永久清除所有阅读历史? - 从设备中永久删除 \"%s\"? - 尝试重新表述查询。 - 帮助进行背景更新检查 - 请勿推荐NSFW漫画 - 新类别 - 阅读 - 暂时没有喜欢的人 - 最喜欢这个 - 添加 - + 你将不会收到通知,但新的章节将在列表中突出显示 + 计算… + 再试一次 + 尚无历史记录 + 不支持这种操作 + 在 \"探索 \"部分找到要读的内容 + 从在线来源保存或导入文件。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容。 + 你的漫画将显示在这里 + 这里有点空… + 饲料更新将很快开始 + 所选择的配置将因这部漫画而被记住 + 数据被恢复了,但有错误 + 在AMOLED屏幕上使用更少的电力 + 登录后可查看此内容 + 永久地删除所有最近的搜索查询? + 永久地清除所有的更新历史? + 你将从所有来源中注销 + 從歷史中排除NSFW漫畫 + 开始阅读漫画,你会得到个性化的建议 + 根据你的喜好推荐漫画 + 指定您不希望在建议中看到的体裁 + 从设备中永久删除选定的项目? + 无法加载流派列表 + 章节将在后台被删除。这可能需要一些时间 + 检查新的章节并通知有关情况 + 有助于避免阻断你的IP地址 + 输入你的电子邮件以继续 + 有了新的漫画来源 + 自动检测漫画是否为网络漫画 + 在历史和收藏夹中显示阅读百分比 + 再次按 \"返回 \"键退出 + 本地存储 + 轻敲右边缘或按右键总是切换到下一页 + 你有未保存的修改,你想保存还是丢弃它们? + 您可以從儲存中刪除原始檔案以節省空間 + 最爱 + 章节 + 列表 + 栅格 + 设置 + 没有发现 + 选择你想看的漫画的语言。你可以在以后的设置中改变它。 + 可以在出现一些问题时提供帮助。所有授权将被视为无效 + 历史 + 发生了一个错误 + 无法连接到互联网 + 详情 + 第%1$d 。%2$d + 详细列表 + 列表模式 + 远程资源 + 正在加载… + 关闭 + 清除历史 + 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 + 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 + 你可以创建你的历史和收藏的备份并恢复它 + 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 + 所选择的颜色设置将被铭记在这部漫画中 + 要么选择ZIP或CBZ文件。 + 你可以在阅读漫画时创建书签 + 你会收到你正在阅读的漫画的更新通知 + 一些设备有不同的系统行为,这可能会破坏后台任务。 + 输入密码以启动应用程序 + 下载或在线阅读这缺失的章节。 + 在启动Kotatsu时要求输入密码 + 这部漫画中没有章节 + 你正在阅读的新章节显示在这里 + 通过长按应用程序图标来提供最近的漫画 + 这部漫画有%s 。全部保存? + 新版本的应用程序已经推出 + 密码必须是4个字符或以上 + 不支持在%s 上登录 + \"%s\" 从本地存储中删除 + 按两次 \"返回 \"键,退出应用程序 + 启用漫画来源,在线阅读漫画 + 永久清除所有阅读历史? + 从设备中永久删除 \"%s\"? + 尝试重新表述查询。 + 帮助进行背景更新检查 + 请勿推荐NSFW漫画 + 新类别 + 阅读 + 暂时没有喜欢的人 + 最喜欢这个 + 添加 + 存儲 + 分享 %s + 搜尋 + 下載中…… + 已下載 + 過濾器 + 主題 + 淺色 + 清除 + 刪除 + 分享圖片 + 刪除 + 清除頁面快取 + \ No newline at end of file From 61a98f54b98cc751d88b10738eb643dd98d5a8b1 Mon Sep 17 00:00:00 2001 From: FateXBlood Date: Mon, 5 Jun 2023 11:53:42 +0200 Subject: [PATCH 53/90] Translated using Weblate (Nepali) Currently translated at 34.1% (144 of 422 strings) Co-authored-by: FateXBlood Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ne/ Translation: Kotatsu/Strings --- app/src/main/res/values-ne/strings.xml | 193 ++++++++++++++++++------- 1 file changed, 141 insertions(+), 52 deletions(-) diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 9d72ad6df..446981da9 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1,53 +1,142 @@ - - डाउनलोड गर्दै… - डाउनलोड गरेको - फिल्टर - अँध्यारो - खाली गर्नुहोस् - पृष्ठहरू - एउटा त्रुटि भयो - सूची मोड - सूची - पुनः प्रयास गर्नुहोस् - केही पनि फेला परेन - पढ्नुहोस् - लोकल भण्डारण - इतिहास - नेटवर्क त्रुटि - अध्यायहरू - सेटिङहरू - रिमोट स्रोतहरू - लोड हुँदै… - इतिहास खाली गर्नुहोस् - अहिले कुनै मनपर्ने छैन - मनपर्ने मा राख्नुहोस् - नयाँ वर्ग - %s साझा गर्नुहोस् - खोज्नुहोस् - माङ्गा खोज्नुहोस् - प्रक्रिया गर्दैछ… - डाउनलोडहरू - नाम - अपडेट गरियो - नवीनतम - क्रमबद्ध क्रम - थीम - उज्यालो - सिस्टम पालना गर्नुहोस् - कम्प्युटिङ… - मनपर्नेहरू - विवरणहरू - विस्तृत सूची - ग्रिड - %2$d को अध्याय %1$d - बन्द गर्नुहोस् - अहिलेसम्म इतिहास छैन - थप्नुहोस् - बचत गर्नुहोस् - साझा गर्नुहोस् - सर्टकट सिर्जना गर्नुहोस्… - लोकप्रिय - मूल्याङ्कन - नयाँ अध्यायहरू - + + डाउनलोड गर्दै… + डाउनलोड गरेको + फिल्टर + अँध्यारो + खाली गर्नुहोस् + पृष्ठहरू + एउटा त्रुटि भयो + सूची मोड + सूची + पुनः प्रयास गर्नुहोस् + केही पनि फेला परेन + पढ्नुहोस् + लोकल भण्डारण + इतिहास + नेटवर्क त्रुटि + अध्यायहरू + सेटिङहरू + माङ्गा स्रोतहरू + लोड हुँदै… + इतिहास खाली गर्नुहोस् + अहिले कुनै मनपर्ने छैन + मनपर्ने मा राख्नुहोस् + नयाँ वर्ग + %s साझा गर्नुहोस् + खोज्नुहोस् + माङ्गा खोज्नुहोस् + प्रक्रिया गर्दैछ… + डाउनलोडहरू + नाम + अपडेट गरिएको + नवीनतम + क्रमबद्ध क्रम + थीम + उज्यालो + सिस्टम पालना गर्नुहोस् + कम्प्युटिङ… + मनपर्नेहरू + विवरणहरू + विस्तृत सूची + ग्रिड + %2$d को अध्याय %1$d + बन्द गर्नुहोस् + अहिलेसम्म इतिहास छैन + थप्नुहोस् + बचत गर्नुहोस् + साझा गर्नुहोस् + सर्टकट सिर्जना गर्नुहोस्… + लोकप्रिय + मूल्याङ्कन + नयाँ अध्यायहरू + सबै पढेको इतिहास स्थायी रूपमा खाली गर्ने हो\? + हटाउनुहोस् + लोकल भण्डारणबाट %s हटाइयो + सेभ गरियो + पृष्ठ सेभ गर्नुहोस् + छवि साझा गर्नुहोस् + आयात गर्नुहोस् + स्ट्यानडर्ड + वेबटून + पढ्ने मोड + ग्रिड साइज + यन्त्रबाट %s स्थायी रूपमा हटाउने हो\? + रिडर सेटिङहरू + %s मा खोज्नुहोस् + माङ्गा हटाउनुहोस् + पृष्ठ स्विच गर्नुहोस् + किनारा ट्यापहरू + भोल्युम बटन + जारी राख्नुहोस् + त्रुटि + खाली गरियो + जेस्चर मात्र + थम्बनेल क्यास खाली गर्नुहोस् + खोज इतिहास खाली गर्नुहोस् + डोमेन + यो माङ्गामा %s छ। यो सबै सेभ गर्ने\? + आन्तरिक भण्डारण + एपको नयाँ संस्करण उपलब्ध छ + बाह्य भण्डारण + वेब ब्राउजरमा खोल्नुहोस् + डाउनलोड + सूचना सेटिङ + LED सूचक + भाईब्रेशन + मनपर्ने वर्गहरू + हटाउनुहोस् + यहाँ अलि खाली जस्तो छ… + सोधपुछ सुधार गर्ने प्रयास गर्नुहोस्। + तपाईँले पढेको कुरा यहाँ देखाइनेछ + साइड मेनुमा के पढ्ने फेला पार्नुहोस्। + पृष्ठ एनिमेसन + डाउनलोडका लागि फोल्डर + हालैका + उपलब्ध छैन + तपाईंले पढिरहनु भएको माङ्गाको नयाँ अध्यायहरू यहाँ देखाइएको छ + खोज परिणामहरू + अपडेट फिड खाली गर्नुहोस् + स्क्रिन घुमाउनुहोस् + अपडेट + पासवर्डहरू म्याच गरेनन् + बारेमा + संस्करण %s + यो अपरेशन समर्थित छैन + कुनै विवरण छैन + इतिहास र क्यास + पृष्ठ क्यास खाली गर्नुहोस् + सूचना आवाज + पहिले केही सेभ गर्नुहोस् + यसलाई अनलाइन स्रोतहरूबाट सेभ गर्नुहोस् वा फाइलहरू आयात गर्नुहोस्। + खाली गरियो + एप सुरक्षित गर्नुहोस् + Kotatsu सुरु गर्दा पासवर्ड माग्नुहोस् + पासवर्ड दोहोर्याउनुहोस् + हटाउनुहोस् + या त ZIP वा CBZ फाइल छान्नुहोस्। + B|kB|MB|GB|TB + सेभ + सूचनाहरू + %2$d को %1$d अन + तपाईंको माङ्गा यहाँ देखाउनेछ + «अन्वेषण» भागमा के पढ्ने फेला पार्नुहोस् + दराज + भण्डारण उपलब्ध छैन + अन्य भण्डारण + सकियो + सबै मनपर्नेहरू + खाली वर्ग + पछि पढ्ने + अपडेटहरू + नयाँ संस्करण: %s + साइज: %s + फिड अपडेट चाँडै सुरु हुनेछ + अपडेटहरू खोज्नुहोस् + जाँच नगर्नुहोस् + गलत पासवर्ड + अपडेटका लागि जाँच गर्नुहोस् + कुनै अपडेट उपलब्ध छैन + अन्वेषण + पासवर्ड एन्टर गर्नुहोस् + \ No newline at end of file From f11e964f0b2cbeba43651a5b8a1c7a7a8c1106cc Mon Sep 17 00:00:00 2001 From: frablock Date: Mon, 5 Jun 2023 11:53:42 +0200 Subject: [PATCH 54/90] Translated using Weblate (French) Currently translated at 100.0% (7 of 7 strings) Translated using Weblate (French) Currently translated at 100.0% (430 of 430 strings) Co-authored-by: frablock Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translation: Kotatsu/Strings Translation: Kotatsu/plurals --- app/src/main/res/values-fr/plurals.xml | 65 ++++++++++++++------------ app/src/main/res/values-fr/strings.xml | 9 ++++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/app/src/main/res/values-fr/plurals.xml b/app/src/main/res/values-fr/plurals.xml index 31a0ce3e8..c0da2ac13 100644 --- a/app/src/main/res/values-fr/plurals.xml +++ b/app/src/main/res/values-fr/plurals.xml @@ -1,31 +1,38 @@ - - Il y a %1$d minute - Il y a %1$d minutes - - - %1$d page au total - %1$d pages au total - - - %1$d élément - %1$d éléments - - - %1$d nouveau chapitre - %1$d nouveaux chapitres - - - %1$d chapitre - %1$d chapitres - - - Il y a %1$d heure - Il y a %1$d heures - - - Il y a %1$d jour - Il y a %1$d jours - - + + Il y a %1$d minute + Il y a %1$d minutes + Il y a %1$d minutes + + + %1$d page au total + %1$d pages au total + %1$d pages au total + + + %1$d élément + %1$d éléments + %1$d éléments + + + %1$d nouveau chapitre + %1$d nouveaux chapitres + %1$d nouveaux chapitres + + + %1$d chapitre + %1$d chapitres + %1$d chapitres + + + Il y a %1$d heure + Il y a %1$d heures + Il y a %1$d heures + + + Il y a %1$d jour + Il y a %1$d jours + Il y a %1$d jours + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index cd7193ee6..04f0ee800 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -417,4 +417,13 @@ Adresse Port Proxy + Téléchargé + Pseudonyme + Proxy d\'optimisation des images + Inverser les couleurs + Utilisez le service wsrv.nl pour réduire le trafic et augmenter la vitesse de chargement des images si possible + %1$s (%2$s) + Mot de passe + Valeur invalide + Autorisation (optionnel) \ No newline at end of file From de2952780559dd04f10432b57ff81083a7db59a4 Mon Sep 17 00:00:00 2001 From: GpixeL Date: Mon, 5 Jun 2023 11:53:43 +0200 Subject: [PATCH 55/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (430 of 430 strings) Co-authored-by: GpixeL Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index cd8f8db8a..de4eb06bd 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -131,7 +131,7 @@ Selesaikan Bersihkan kuki Semua kuki telah dihapus - Bersihkan umpan + Bersihkan aliran Periksa bab baru Masuk untuk melihat konten ini Selanjutnya @@ -215,10 +215,10 @@ Getaran Kategori favorit Hapus - Bersihkan umpan pembaruan + Bersihkan aliran pembaruan Kanan-ke-kiri Putar layar - Pembaruan umpan akan dimulai + Pembaruan aliran akan dimulai Masukkan kata sandi Tanya kata sandi ketika memulai Kotatsu Tentang From 09343632980a69ef8055b66bca3dda9c0cb41457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D0=B0=D1=80=20=D0=A0=D0=B0=D0=B7=D0=B8?= =?UTF-8?q?=D0=BD?= Date: Sun, 4 Jun 2023 12:57:01 +0200 Subject: [PATCH 56/90] Translated using Weblate (Belarusian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (416 of 416 strings) Co-authored-by: Макар Разин Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/ Translation: Kotatsu/Strings --- app/src/main/res/values-be/strings.xml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 33e0b519d..8c17722f5 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -45,7 +45,7 @@ Тэма Светлая Цёмная - Аўтаматычна + Як у сістэме Старонкi Ачысціць Вы ўпэўненыя, што жадаеце ачысціць гісторыю\? @@ -136,8 +136,8 @@ Падагнаць па вышыні Падагнаць па шырыні Зыходны памер - Чорная цёмная тэма - Карысна для AMOLED экранаў + Чорная + Спажывае менш энергіі на экранах AMOLED Рэзервовае капіяванне і аднаўленне Стварыць рэзервовую копію Аднавіць данныя @@ -412,4 +412,9 @@ Спампоўкі былі адменены Пераклады WebView недаступны: праверце, ці ўсталяваны пастаўшчык WebView + Тып + Адрас + Порт + Проксі + Ачысціць сеткавы кэш \ No newline at end of file From e7c2a7621907e17ed4346dc5809e7b513446160a Mon Sep 17 00:00:00 2001 From: "J. Lavoie" Date: Sun, 4 Jun 2023 12:57:02 +0200 Subject: [PATCH 57/90] Translated using Weblate (French) Currently translated at 100.0% (416 of 416 strings) Co-authored-by: J. Lavoie Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translation: Kotatsu/Strings --- app/src/main/res/values-fr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ef3ad9f8a..758eedf94 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -410,4 +410,6 @@ Les téléchargements ont été supprimés Les téléchargements ont été annulés Voulez-vous recevoir des suggestions de mangas personnalisées \? + WebView non disponible : vérifier si le fournisseur WebView est installé + Traductions \ No newline at end of file From 6bd5033858b98a0b7d5297ab67015f94355504e0 Mon Sep 17 00:00:00 2001 From: kuragehime Date: Sun, 4 Jun 2023 12:57:02 +0200 Subject: [PATCH 58/90] Translated using Weblate (Japanese) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (427 of 427 strings) Translated using Weblate (Japanese) Currently translated at 91.8% (382 of 416 strings) Co-authored-by: kuragehime Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ja/ Translation: Kotatsu/Strings --- app/src/main/res/values-ja/strings.xml | 801 +++++++++++++------------ 1 file changed, 426 insertions(+), 375 deletions(-) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 8b9bc139c..160cd572a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,378 +1,429 @@ - 履歴 - ロード中… - チャプター %1$d of %2$d - 共有 - 履歴を削除 - 検索 - 漫画を検索 - 閉じる - お気に入り - エラーが発生しました - 詳細 - - リスト - 詳細リスト - グリッド - リストモード - リモートソース - 再試行 - 何も見つかりませんでした - まだ履歴はありません - 読む - お気に入りの本はありません - お気に入りの本 - 新たなカテゴリー - 追加 - 保存 - ショートカットを作成します… - 共有する%s - ダウンロード中… - 処理中… - ダウンロードした本 - ダウンロード - 名前 - 人気 - ローカルストレージ - 最新 - 評価 - ソート順に並べ替え - フォローシステム - クリア - すべての履歴を永久にクリアしますか? - 削除 - 「%s 」がローカルストレージから削除されました - ページを保存 - 保存しました - 画像を共有する - インポート - 消去 - この操作はサポートされていません - 説明がありません - 履歴とキャッシュ - ページのキャッシュをクリアする - B|kB|MB|GB|TB - 設定 - ライトテーマ - フィルター - ダークテーマ - ページ - テーマ - ネットワークエラー - アップデート - ZIPファイルまたはCBZファイルを選択してください。 - 標準 - ウェブトゥーン - 読み取りモード - グリッドのサイズ - %sで検索 - 漫画を削除 - お使いのデバイスから「%s」を完全に削除しますか? - リーダーの設定 - ページを変更 - エッジタップ - ボリュームボタン - 続ける - エラー - サムネイルキャッシュをクリア - クリア - ジェスチャーのみ - 内部ストレージ - ドメイン - ブラウザーで開く - この漫画には%sがあります。 すべて保存しますか? - 保存 - 通知 - %2$dの%1$d - 新しいチャプター - ダウンロード - 通知の設定 - 通知音 - LEDインジケータ - バイブレーション - お気に入りのカテゴリー - 削除 - クエリを再定式化してみてください。 - 読んだ内容がここに表示されます - サイドメニューで何を読むかを見つけてください。 - 最初に何かを保存する - 本棚 - 最近 - ページアニメーション - ダウンロード用のフォルダ - 利用出来ません - 使用可能なストレージがありません - その他のストレージ - 完了 - 全てのお気に入り - 後で読む - 更新 - あなたが読んでいるものの新しいチャプターがここに示されています - の検索結果 - サイズ:%s - 更新フィードをクリア - クリア - アップデート - フィードの更新はまもなく開始されます - アップデートを確認 - チェックしない - Kotatsuを起動したときにパスワードを入力する - パスワードを繰り返す - パスワードが違います - この本の詳細 - 現在のバージョン%s - 検索履歴をクリア - 外部ストレージ - Kotatsuの新しい更新が利用可能です - ここは空っぽです… - 空のカテゴリー - オンラインソースから保存するかファイルをインポートします。 - 新しいバージョン:%s - 画面を回転させる - パスワードを入力してください - パスワードが間違っています - アプリを保護する - 最新のアップデートを確認する - 利用可能なアップデートはありません - 右から左 - 承認済み - %sへのログインはサポートされていません - 完成 - 進行中 - デフォルト - ナンバリングページ - 使用したソース - 利用可能なソース - 新しいカテゴリー - 高さを合わせる - チャプターがありません - すべての更新履歴を完全に消去しますか? - この不足した章をダウンロードしたり、オンラインで読んだりすることができます。 - このコンテンツを表示するにはサインインしてください - ファイルが見つかりません - パスワードは4文字以上である必要があります - ちょうど今 - ずっと前 - バックアップを保存 - グループ - フィードをクリア - バックアップから復元 - 確認 - 履歴とお気に入りのバックアップを作成して復元できます - 続きを読む - ブラック - データは復元されましたがエラーが発生しました - 最近の検索クエリを全て完全に削除しますか? - 幅を合わせる - 新しいチャプターを探しています - アプリを起動するためのパスワードを入力してください - データバックアップを作成 - 解決しました - タップして再試行してください - CAPTCHAが必要です - デフォルト:%s - 昨日 - このアプリを翻訳 - 全てのデータが復元されました - 復元 - 準備中… - 開始時に維持 - バックアップと復元 - リバース - 選択した構成はこの漫画のために記憶されます - クッキーを削除 - フィットセンター - 全てのソースからログアウトされます - NSFW漫画を履歴から除外する - キュー - 全てのCookieが削除されました - 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 - ジャンル - スケールモード - 今日 - Kotatsuを翻訳する(Weblateのサイトに移動します) - 次のページ - サイレント - サインイン - ようこそ - AMOLEDスクリーンでさらに少ない電力を使用 - コンピューティング… - 許可する - 常にブロック - スクリーンショットポリシー - NSFWでブロック - 提案 - すべてのデータは、このデバイス上でローカルに分析されます。お客様のデータが他のサービスに転送されることはありません - サジェスト機能を有効 - あなたの好みに合わせて漫画を提案 - ジャンルリストを読み込めません - 無効 - マンガを読み始めると、個人的な提案を受けることができます - 有効 - NSFWのマンガを提案しない - フィルターをリセット - ジャンルを探す - Wi-Fiのみ使用 - 決して - 漫画を読みたい言語を選択します。後で設定から変更することができます。 - 常に - ページのプリロード - %sとしてログイン - 18歳以上 - さまざまな言語 - チャプターを検索 - この漫画の章はありません - %1$s%% - コンテンツ - 更新のご提案 - 外観 - ジャンルを除く - サジェストで表示したくないジャンルを指定 - 選択した項目をデバイスから完全に削除しますか? - 削除が完了しました - IPアドレスのブロックを回避することができます - 保存されたマンガの処理 - ダウンロードの速度低下 - チャプターはバックグラウンドで削除されます。時間がかかる場合があります - 隠す - 新しいマンガソースが利用可能です - 新着チャプターの確認とお知らせ - 読んでいるマンガの更新情報をお知らせします - 通知を有効にする - 通知はありませんが、新しいチャプターはリストでハイライト表示されます - 名称 - 編集 - カテゴリーを編集する - お気に入りのカテゴリーはありません - ブックマーク - ブックマーク削除 - 元に戻す - 履歴から削除 - ブックマークの追加 - ブックマークの削除 - ブックマークを追加 - HTTPS 経由の DNS - リーダーモードの自動検出 - デフォルトモード - マンガがウェブトゥーンかどうかを自動判定 - バッテリー最適化の無効化 - バックグラウンドの更新チェックを支援 - 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 - 送信 - すべて無効にする - 最近読んだ漫画 - 指紋がある場合は、指紋を使用する - お気に入りの漫画 - 報告 - 読書 - 再読込 - 完了 - 保留中 - 追跡 - ログアウト - 予定 - ドロップ - データの削除 - 履歴とお気に入りに既読率を表示する - いくつかの問題の場合に助けることができる。すべての認証が無効になります - 読書の進行状況インジケーターを表示 - NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない - すべて表示 - 無効なドメイン - 範囲を選択 - コンテンツが見つからない、または削除された - 管理 - ランダム - 選択したお気に入りカテゴリを本当に削除してもよいですか? + 履歴 + ロード中… + チャプター %1$d of %2$d + 共有 + 履歴を削除 + 検索 + 漫画を検索 + 閉じる + お気に入り + エラーが発生しました + 詳細 + + リスト + 詳細リスト + グリッド + リストモード + マンガのソース + 再試行 + 何も見つかりませんでした + まだ履歴はありません + 読む + お気に入りの本はありません + お気に入りの本 + 新たなカテゴリー + 追加 + 保存 + ショートカットを作成します… + 共有する%s + ダウンロード中… + 処理中… + ダウンロードした本 + ダウンロード + 名前 + 人気 + ローカルストレージ + 最新 + 評価 + ソート順に並べ替え + フォローシステム + クリア + すべての履歴を永久にクリアしますか? + 削除 + 「%s 」がローカルストレージから削除されました + ページを保存 + 保存しました + 画像を共有する + インポート + 消去 + この操作はサポートされていません + 説明がありません + 履歴とキャッシュ + ページのキャッシュをクリアする + B|kB|MB|GB|TB + 設定 + ライトテーマ + フィルター + ダークテーマ + ページ + テーマ + ネットワークエラー + アップデート + ZIPファイルまたはCBZファイルを選択してください。 + 標準 + ウェブトゥーン + 読み取りモード + グリッドのサイズ + %sで検索 + 漫画を削除 + お使いのデバイスから「%s」を完全に削除しますか? + リーダーの設定 + ページを変更 + エッジタップ + ボリュームボタン + 続ける + エラー + サムネイルキャッシュをクリア + クリア + ジェスチャーのみ + 内部ストレージ + ドメイン + ブラウザーで開く + この漫画には%sがあります。 すべて保存しますか? + 保存 + 通知 + %2$dの%1$d + 新しいチャプター + ダウンロード + 通知の設定 + 通知音 + LEDインジケータ + バイブレーション + お気に入りのカテゴリー + 削除 + クエリを再定式化してみてください。 + 読んだ内容がここに表示されます + サイドメニューで何を読むかを見つけてください。 + 最初に何かを保存する + 本棚 + 最近 + ページアニメーション + ダウンロード用のフォルダ + 利用出来ません + 使用可能なストレージがありません + その他のストレージ + 完了 + 全てのお気に入り + 後で読む + 更新 + あなたが読んでいるものの新しいチャプターがここに示されています + の検索結果 + サイズ:%s + 更新フィードをクリア + クリア + アップデート + フィードの更新はまもなく開始されます + アップデートを確認 + チェックしない + Kotatsuを起動したときにパスワードを入力する + パスワードを繰り返す + パスワードが違います + この本の詳細 + 現在のバージョン%s + 検索履歴をクリア + 外部ストレージ + Kotatsuの新しい更新が利用可能です + ここは空っぽです… + 空のカテゴリー + オンラインソースから保存するかファイルをインポートします。 + 新しいバージョン:%s + 画面を回転させる + パスワードを入力してください + パスワードが間違っています + アプリを保護する + 最新のアップデートを確認する + 利用可能なアップデートはありません + 右から左 + 承認済み + %sへのログインはサポートされていません + 完成 + 進行中 + デフォルト + ナンバリングページ + 使用したソース + 利用可能なソース + 新しいカテゴリー + 高さを合わせる + チャプターがありません + すべての更新履歴を完全に消去しますか? + この不足した章をダウンロードしたり、オンラインで読んだりすることができます。 + このコンテンツを表示するにはサインインしてください + ファイルが見つかりません + パスワードは4文字以上である必要があります + ちょうど今 + ずっと前 + バックアップを保存 + グループ + フィードをクリア + バックアップから復元 + 確認 + 履歴とお気に入りのバックアップを作成して復元できます + 続きを読む + ブラック + データは復元されましたがエラーが発生しました + 最近の検索クエリを全て完全に削除しますか? + 幅を合わせる + 新しいチャプターを探しています + アプリを起動するためのパスワードを入力してください + データバックアップを作成 + 解決しました + タップして再試行してください + CAPTCHAが必要です + デフォルト:%s + 昨日 + このアプリを翻訳 + 全てのデータが復元されました + 復元 + 準備中… + 開始時に維持 + バックアップと復元 + リバース + 選択した構成はこの漫画のために記憶されます + クッキーを削除 + フィットセンター + 全てのソースからログアウトされます + NSFW漫画を履歴から除外する + キュー + 全てのCookieが削除されました + 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 + ジャンル + スケールモード + 今日 + Kotatsuを翻訳する(Weblateのサイトに移動します) + 次のページ + サイレント + サインイン + ようこそ + AMOLEDスクリーンでさらに少ない電力を使用 + コンピューティング… + 許可する + 常にブロック + スクリーンショットポリシー + NSFWでブロック + 提案 + すべてのデータは、このデバイス上でローカルでのみ分析され、どこにも送信されることはありません。 + サジェスト機能を有効 + あなたの好みに合わせて漫画を提案 + ジャンルリストを読み込めません + 無効 + マンガを読み始めると、個人的な提案を受けることができます + 有効 + NSFWのマンガを提案しない + フィルターをリセット + ジャンルを探す + Wi-Fiのみ使用 + 決して + 漫画を読みたい言語を選択します。後で設定から変更することができます。 + 常に + ページのプリロード + %sとしてログイン + 18歳以上 + さまざまな言語 + チャプターを検索 + この漫画の章はありません + %1$s%% + コンテンツ + 更新のご提案 + 外観 + ジャンルを除く + サジェストで表示したくないジャンルを指定 + 選択した項目をデバイスから完全に削除しますか? + 削除が完了しました + IPアドレスのブロックを回避することができます + 保存されたマンガの処理 + ダウンロードの速度低下 + チャプターはバックグラウンドで削除されます + 隠す + 新しいマンガソースが利用可能です + 新着チャプターの確認とお知らせ + 読んでいるマンガの更新情報をお知らせします + 通知を有効にする + 通知はありませんが、新しいチャプターはリストでハイライト表示されます + 名称 + 編集 + カテゴリーを編集する + お気に入りのカテゴリーはありません + ブックマーク + ブックマーク削除 + 元に戻す + 履歴から削除 + ブックマークの追加 + ブックマークの削除 + ブックマークを追加 + HTTPS 経由の DNS + リーダーモードの自動検出 + デフォルトモード + マンガがウェブトゥーンかどうかを自動判定 + バッテリー最適化の無効化 + バックグラウンドの更新チェックを支援 + 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 + 送信 + すべて無効にする + 最近読んだ漫画 + 指紋がある場合は、指紋を使用する + お気に入りの漫画 + 報告 + 読書 + 再読込 + 完了 + 保留中 + 追跡 + ログアウト + 予定 + ドロップ + データの削除 + 履歴とお気に入りに既読率を表示する + いくつかの問題の場合に助けることができる。すべての認証が無効になります + 読書の進行状況インジケーターを表示 + NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない + すべて表示 + 無効なドメイン + 範囲を選択 + コンテンツが見つからない、または削除された + 管理 + ランダム + 選択したお気に入りカテゴリを本当に削除してもよいですか? \nその中にあるマンガはすべて失われ、元に戻すことはできません。 - - 探検 - アプリを終了するには、戻るを2回押してください - 保存したマンガ - チャプターなし - 自動スクロール - マンガのインポート - 続行するにはメールアドレスを入力してください - «探索»セクションで読むべきものを見つける - インポートが完了しました - あなたのマンガはここに表示されます - キャンセル - データの同期 - アカウントは既に存在します - 戻る - 過去 2 時間 - ブックマークはまだありません - 同期 - ページキャッシュ - 利用可能 - すべての履歴を消去する - 履歴が消去されました - 並べ替え - マンガを読みながらブックマークを作成することができます - ブックマークを削除しました - マンガのソースがない - マンガのソースを有効にして、オンラインでマンガを読めるようにする - もう一度戻るを押して終了します - %s -%s - 退出確認 - ストレージの使用状況 - その他のキャッシュ - シークレットモード - 画像を含むフォルダ - まもなくインポートが開始されます - お気に入りから削除 - オプション - ストレージから元のファイルを削除して、容量を節約することができます - Ch.%1$d/%2$d Pg.%3$d/%4$d - リーダーで情報バーを表示する - コミックアーカイブ - フィード - エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用できるか確認する<br>2. 利用できる場合は、開発者にエラーレポートを送信する</a>。 - 人間工学に基づいたリーダーコントロール - 最近のマンガのショートカットを表示 - アプリケーションアイコンを長押しして最近のマンガを利用できるようにする - 右端をタップするか、右キーを押すと、常に次のページに切り替わります - 色補正 - 輝度 - コントラスト - リセット - 未保存の変更を保存または破棄しますか\? - 選択した色の設定は、この漫画のために記憶されます - 破棄 - デバイスに空き容量がありません - ページ切り替えスライダーを表示 - サーバーサイドエラー (%1$d) です。後で再試行してください - 新しいチャプターの情報も明確に - さまざまな言語 - ネットワークが利用できません - Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます - Webtoonズーム - コンパクト - マミミ - - ここには何もありません - 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 - サービス - デバッグ目的でいくつかのアクションを記録する - ミク - ユーザー エージェント ヘッダー - コンテンツのプリロード - ログを共有 - 不安定な更新を許可 - アプリのベータ版へのアップデートを提案する - ダウンロードが開始されました - 言語 - ソースが無効になっています - 現在としてマーク - ログ記録を有効にする - 疑わしいコンテンツを表示する - ダイナミック - 配色 - グリッドビューで表示 - アスカ - ミオン - リッカ - さくら - この変更を適用するには、アプリケーションを再起動してください - + + 探検 + アプリを終了するには、戻るを2回押してください + 保存したマンガ + チャプターなし + 自動スクロール + マンガのインポート + 続行するにはメールアドレスを入力してください + «探索»セクションで読むべきものを見つける + インポートが完了しました + あなたのマンガはここに表示されます + キャンセル + データの同期 + アカウントは既に存在します + 戻る + 過去 2 時間 + ブックマークはまだありません + 同期 + ページキャッシュ + 利用可能 + すべての履歴を消去する + 履歴が消去されました + 並べ替え + マンガを読みながらブックマークを作成することができます + ブックマークを削除しました + マンガのソースがない + マンガのソースを有効にして、オンラインでマンガを読めるようにする + もう一度戻るを押して終了します + %s -%s + 退出確認 + ストレージの使用状況 + その他のキャッシュ + シークレットモード + 画像を含むフォルダ + まもなくインポートが開始されます + お気に入りから削除 + オプション + ストレージから元のファイルを削除して、容量を節約することができます + Ch.%1$d/%2$d Pg.%3$d/%4$d + リーダーで情報バーを表示する + コミックアーカイブ + フィード + エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用可能かどうか確認してください<br>2.<a href=kotatsu://about>最新版のこたつ</a><br>3.利用可能であれば、開発者にエラーレポートを送ってみてください。 + 人間工学に基づいたリーダーコントロール + 最近のマンガのショートカットを表示 + アプリケーションアイコンを長押しして最近のマンガを利用できるようにする + 右端をタップするか、右キーを押すと、常に次のページに切り替わります + 色補正 + 輝度 + コントラスト + リセット + 未保存の変更を保存または破棄しますか\? + 選択した色の設定は、この漫画のために記憶されます + 破棄 + デバイスに空き容量がありません + ページ切り替えスライダーを表示 + サーバーサイドエラー (%1$d) です。後で再試行してください + 新しいチャプターの情報も明確に + さまざまな言語 + ネットワークが利用できません + Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます + Webtoonズーム + コンパクト + マミミ + + ここには何もありません + 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 + サービス + デバッグ目的でいくつかのアクションを記録する + ミク + ユーザー エージェント ヘッダー + コンテンツのプリロード + ログを共有 + 不安定な更新を許可 + アプリのベータ版へのアップデートを提案する + ダウンロードが開始されました + 言語 + ソースが無効になっています + 現在としてマーク + ログ記録を有効にする + 疑わしいコンテンツを表示する + ダイナミック + 配色 + グリッドビューで表示 + アスカ + ミオン + リッカ + さくら + この変更を適用するには、アプリケーションを再起動してください + 項目をタップ&ホールドして並び替えをすることができます + .cbzまたは.zipファイルを1つ以上選択することができ、各ファイルは別のマンガとして認識されます。 + 了解 + 翻訳 + 過去に作成したユーザーデータのバックアップをインポートする + 棚に表示 + %1$s (%2$s) + 色を反転させる + 有効 + 結構です + ネットワークキャッシュをクリアする + ダウンロードは削除されました + 自分で用意した同期サーバーか、デフォルトのものを使用することができます。よく分からない場合は変更しないでください。 + 一時停止 + ダウンロードがキャンセルされました + WebViewが利用できません:WebView providerがインストールされているかどうかを確認してください + ダウンロード済み + 画像最適化プロキシ + wsrv.nl サービスを使用して、トラフィック使用量を削減し、可能であれば画像の読み込みを高速化します + アーカイブや画像のあるディレクトリを選択することができます。各アーカイブ(またはサブディレクトリ)は、1つのチャプターとして認識されます。 + 類似したものを探す + タイプ + アドレス + ポート + プロキシ + 同期の設定 + サーバーアドレス + 速度 + SSLエラーを無視する + ミラーを自動的に選択する + ミラーがある場合、エラー時にリモートソースのドメインを自動で切り替える + 履歴書 + 一時停止 + 全てキャンセル + Wi-Fi経由でのみダウンロード + モバイルデータ通信への切り替え時にダウンロードを停止する + 提案: %s + 提案されたマンガの通知を表示することがあります + もっと見る + アクティブなダウンロードはすべてキャンセルされ、部分的にダウンロードされたデータは失われます + ダウンロード履歴は完全に削除されます + ダウンロードはありません + ダウンロードが再開されました + ダウンロードが一時停止されました + パーソナライズされた漫画の提案を受け取りますか? + 削除が完了 + 既存のアカウントにサインインするか、新規にアカウントを作成することができます + 無効な値 + ユーザー名 + パスワード + オーソライズ(オプション) + \ No newline at end of file From 9c2a57812ed0eb0e1dc76cb36d9fe481a48505fe Mon Sep 17 00:00:00 2001 From: Insopitus Date: Sun, 4 Jun 2023 12:57:03 +0200 Subject: [PATCH 59/90] Translated using Weblate (Chinese (Simplified)) Currently translated at 99.2% (413 of 416 strings) Co-authored-by: Insopitus Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/ Translation: Kotatsu/Strings --- app/src/main/res/values-zh-rCN/strings.xml | 794 +++++++++++---------- 1 file changed, 412 insertions(+), 382 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 62b5a3e00..5b20c9e2a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,385 +1,415 @@ - 设置 - 本地存储 - 喜欢 - 历史 - 发生了一个错误 - 网络错误 - 章节 - 列表 - 数据被恢复了,但有错误 - 正在处理… - 最新 - 评分 - 已删除所有 cookie - 所有数据都被恢复了 - 无声 - 准备… - 未找到文件 - 昨日 - 你可以创建你的历史和收藏的备份并恢复它 - 现在 - 很久以前 - - 轻点以重试 - 所选择的配置将因这部漫画而被记住 - 需要验证码 - 解决 - 今天 - 清除cookies - 有新的漫画源可用 - 根据你的喜好推荐漫画 - 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 - 从不 - 你会收到你正在阅读的漫画的更新通知 - 18+ - 各种语言 - 查找章节 - 排除流派 - 建议更新 - 检查新的章节并通知有关情况 - 详细内容 - 详细列表 - 网格 - 列表模式 - 漫画源 - 加载中… - 计算中… - %1$d/%2$d章节 - 关闭 - 再试一次 - 清除历史 - 没有发现 - 尚无历史 - 阅读 - 尚无收藏夹 - 收藏此漫画 - 新分类 - 添加 - 保存 - 分享 - 创建快捷方式… - 分享%s - 搜索 - 搜索漫画 - 正在下载… - 已下载 - 下载 - 名称 - 热门 - 更新 - 排序顺序 - 过滤器 - 主题 - 深色 - 浅色 - 跟随系统 - 页数 - 清除 - 永久清除所有阅读历史\? - 删除 - \"%s\"从本地存储中删除 - 保存页面 - 保存 - 分享图片 - 导入 - 删除 - 不支持此操作 - 选择 ZIP 或 CBZ 文件. - 无描述 - 历史和缓存 - 清除页面缓存 - B|kB|MB|GB|TB - 标准 - 条漫 - 阅读模式 - 网格大小 - 在%s上搜索 - 删除漫画 - 从设备中永久删除\"%s\"\? - 阅读器设置 - 切换页面 - 音量按钮 - 继续 - 边缘点击 - 错误 - 清除缩略图缓存 - 清除搜索历史 - 清除 - 仅限手势 - 内部存储 - 外部存储 - 范围 - 新版本应用程序已经推出 - 在网络浏览器中打开 - 这部漫画有%s.全部保存\? - 保存 - 通知 - 新章节 - 下载 - 通知设置 - 通知声音 - LED指示器 - 振动 - 收藏夹分类 - 删除 - 这里有点空… - 尝试重新表述查询。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容. - 先保存内容 - 从在线来源保存或导入文件. - 书架 - 最近 - 页面动画 - 下载文件夹 - 不详 - 没有可用的存储空间 - 其他存储 - 完成 - 所有收藏夹 - 空分类 - 稍后阅读 - 更新 - 你正在阅读的新章节显示在这里 - 搜索结果 - 新版本: %s - 清除更新源 - 已清除 - 旋转屏幕 - 更新 - 源更新即将开始 - 查找更新 - 不要检查 - 输入密码 - 密码错误 - 保护应用程序 - 在启动Kotatsu时要求输入密码 - 重复密码 - 密码不匹配 - 关于 - 版本%s - 检查更新 - 没有更新 - 从右到左 - 新分类 - 缩放模式 - 适应中心 - 适应高度 - 适应宽度 - 从头开始 - 黑色 - 在AMOLED屏幕上使用更少电池 - 备份和还原 - 创建数据备份 - 从备份中恢复 - 恢复 - 清除文件 - 永久地清除所有的更新历史? - 检查新的章节 - 撤销 - 登录 - 登录后可查看此内容 - 默认值: %s - 下一页 - 输入密码以启动应用程序 - 确认 - 密码必须是4个字符或以上 - 永久地删除所有最近的搜索查询? - 欢迎 - 保存备份 - 一些设备有不同的系统行为, 这可能会破坏后台任务. - 阅读更多 - 排队 - 下载或在线阅读这缺失的章节. - 该章缺失 - 翻译此应用程序 - 翻译 - 授权 - 不支持在%s上登录 - 你将退出登录所有来源 - 类型 - 连载中 - 已完结 - 默认 - 将NSFW漫画排除在历史之外 - 页数 - 使用图源 - 现有图源 - 屏幕截图 - 允许 - 禁止18+ - 始终阻止 - 建议 - 启用建议 - 开始阅读漫画,你会得到个性化的建议 - 请勿推荐18+漫画 - 启用 - 禁用 - 无法加载流派列表 - 重置过滤器 - 查找流派 - 选择你想看的漫画的语言. 你可以在以后的设置中改变它. - 只在Wi-Fi上使用 - 总是 - 预加载页面 - 以%s身份登录 - 这部漫画中没有章节 - 外观 - 内容 - 指定您不希望在建议中看到的类型 - 从设备中永久删除所选项目\? - 删除已完成 - 下载速度减慢 - 有助于避免阻断你的IP地址 - 保存的漫画处理 - 章节将在后台被删除 - 隐藏 - 你将不会收到通知但新的章节将在列表中突出显示 - 启用通知 - 命名 - 编辑 - 编辑分类 - 没有收藏夹分类 - 添加书签 - 删除书签 - 书签 - 删除书签 - 添加书签 - 撤销 - 从历史中删除 - DNS over HTTPS - 默认模式 - 自动检测阅读器模式 - 自动检测漫画是否为条漫 - 禁用电池优化 - 帮助进行背景更新检查 - 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. - 发送 - 全部禁用 - 计划 - 暂停 - 报告 - 追踪 - 注销 - 阅读 - 重读 - 完成 - 使用指纹 - 你喜欢的漫画 - 您最近阅读的漫画 - 在历史和收藏夹中显示阅读百分比 - 显示阅读进度指标 - 数据删除 - 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 - 可以在出现一些问题时提供帮助. 所有授权将被视为无效 - 显示全部 - 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 - 无效域名 - 此处将显示你的漫画 - 在【浏览】页面搜索想要阅读的漫画 - %1$s%% - 已取消 - 账号已存在 - 返回 - 同步 - 同步您的数据 - 输入您的邮箱以继续 - 已放弃 - 选择范围 - 清除所有历史 - 过去2小时 - 书签已移除 - 历史已清除 - 管理 - 还没有书签 - 您可以在阅读漫画时创建书签 - 无漫画源 - 启用漫画源以在线阅读漫画 - 随机 - 您确定要删除选定的收藏夹吗? + 设置 + 本地存储 + 喜欢 + 历史 + 发生了一个错误 + 网络错误 + 章节 + 列表 + 数据被恢复了,但有错误 + 正在处理… + 最新 + 评分 + 已删除所有 cookie + 所有数据都被恢复了 + 无声 + 准备… + 未找到文件 + 昨日 + 你可以创建你的历史和收藏的备份并恢复它 + 现在 + 很久以前 + + 轻点以重试 + 所选择的配置将因这部漫画而被记住 + 需要验证码 + 解决 + 今天 + 清除cookies + 有新的漫画源可用 + 根据你的喜好推荐漫画 + 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 + 从不 + 你会收到你正在阅读的漫画的更新通知 + 18+ + 各种语言 + 查找章节 + 排除流派 + 建议更新 + 检查新的章节并通知有关情况 + 详细内容 + 详细列表 + 网格 + 列表模式 + 漫画源 + 加载中… + 计算中… + %1$d/%2$d章节 + 关闭 + 再试一次 + 清除历史 + 没有发现 + 尚无历史 + 阅读 + 尚无收藏夹 + 收藏此漫画 + 新分类 + 添加 + 保存 + 分享 + 创建快捷方式… + 分享%s + 搜索 + 搜索漫画 + 正在下载… + 已下载 + 下载 + 名称 + 热门 + 更新 + 排序顺序 + 过滤器 + 主题 + 深色 + 浅色 + 跟随系统 + 页数 + 清除 + 永久清除所有阅读历史\? + 删除 + \"%s\"从本地存储中删除 + 保存页面 + 保存 + 分享图片 + 导入 + 删除 + 不支持此操作 + 选择 ZIP 或 CBZ 文件. + 无描述 + 历史和缓存 + 清除页面缓存 + B|kB|MB|GB|TB + 标准 + 条漫 + 阅读模式 + 网格大小 + 在%s上搜索 + 删除漫画 + 从设备中永久删除\"%s\"\? + 阅读器设置 + 切换页面 + 音量按钮 + 继续 + 边缘点击 + 错误 + 清除缩略图缓存 + 清除搜索历史 + 清除 + 仅限手势 + 内部存储 + 外部存储 + 范围 + 新版本应用程序已经推出 + 在网络浏览器中打开 + 这部漫画有%s.全部保存\? + 保存 + 通知 + 新章节 + 下载 + 通知设置 + 通知声音 + LED指示器 + 振动 + 收藏夹分类 + 删除 + 这里有点空… + 尝试重新表述查询。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容. + 先保存内容 + 从在线来源保存或导入文件. + 书架 + 最近 + 页面动画 + 下载文件夹 + 不详 + 没有可用的存储空间 + 其他存储 + 完成 + 所有收藏夹 + 空分类 + 稍后阅读 + 更新 + 你正在阅读的新章节显示在这里 + 搜索结果 + 新版本: %s + 清除更新源 + 已清除 + 旋转屏幕 + 更新 + 源更新即将开始 + 查找更新 + 不要检查 + 输入密码 + 密码错误 + 保护应用程序 + 在启动Kotatsu时要求输入密码 + 重复密码 + 密码不匹配 + 关于 + 版本%s + 检查更新 + 没有更新 + 从右到左 + 新分类 + 缩放模式 + 适应中心 + 适应高度 + 适应宽度 + 从头开始 + 黑色 + 在AMOLED屏幕上使用更少电池 + 备份和还原 + 创建数据备份 + 从备份中恢复 + 恢复 + 清除文件 + 永久地清除所有的更新历史? + 检查新的章节 + 撤销 + 登录 + 登录后可查看此内容 + 默认值: %s + 下一页 + 输入密码以启动应用程序 + 确认 + 密码必须是4个字符或以上 + 永久地删除所有最近的搜索查询? + 欢迎 + 保存备份 + 一些设备有不同的系统行为, 这可能会破坏后台任务. + 阅读更多 + 排队 + 下载或在线阅读这缺失的章节. + 该章缺失 + 翻译此应用程序 + 翻译 + 授权 + 不支持在%s上登录 + 你将退出登录所有来源 + 类型 + 连载中 + 已完结 + 默认 + 将NSFW漫画排除在历史之外 + 页数 + 使用图源 + 现有图源 + 屏幕截图 + 允许 + 禁止18+ + 始终阻止 + 建议 + 启用建议 + 开始阅读漫画,你会得到个性化的建议 + 请勿推荐18+漫画 + 启用 + 禁用 + 无法加载流派列表 + 重置过滤器 + 查找流派 + 选择你想看的漫画的语言. 你可以在以后的设置中改变它. + 只在Wi-Fi上使用 + 总是 + 预加载页面 + 以%s身份登录 + 这部漫画中没有章节 + 外观 + 内容 + 指定您不希望在建议中看到的类型 + 从设备中永久删除所选项目\? + 删除已完成 + 下载速度减慢 + 有助于避免阻断你的IP地址 + 保存的漫画处理 + 章节将在后台被删除 + 隐藏 + 你将不会收到通知但新的章节将在列表中突出显示 + 启用通知 + 命名 + 编辑 + 编辑分类 + 没有收藏夹分类 + 添加书签 + 删除书签 + 书签 + 删除书签 + 添加书签 + 撤销 + 从历史中删除 + DNS over HTTPS + 默认模式 + 自动检测阅读器模式 + 自动检测漫画是否为条漫 + 禁用电池优化 + 帮助进行背景更新检查 + 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. + 发送 + 全部禁用 + 计划 + 暂停 + 报告 + 追踪 + 注销 + 阅读 + 重读 + 完成 + 使用指纹 + 你喜欢的漫画 + 您最近阅读的漫画 + 在历史和收藏夹中显示阅读百分比 + 显示阅读进度指标 + 数据删除 + 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 + 可以在出现一些问题时提供帮助. 所有授权将被视为无效 + 显示全部 + 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 + 无效域名 + 此处将显示你的漫画 + 在【浏览】页面搜索想要阅读的漫画 + %1$s%% + 已取消 + 账号已存在 + 返回 + 同步 + 同步您的数据 + 输入您的邮箱以继续 + 已放弃 + 选择范围 + 清除所有历史 + 过去2小时 + 书签已移除 + 历史已清除 + 管理 + 还没有书签 + 您可以在阅读漫画时创建书签 + 无漫画源 + 启用漫画源以在线阅读漫画 + 随机 + 您确定要删除选定的收藏夹吗? \n所有收藏夹中的漫画将丢失且无法恢复。 - 重新排序 - 留空 - 浏览 - 自动滚动 - 在阅读器中显示信息栏 - 漫画压缩包 - 图片文件夹 - 漫画导入中 - Ch. %1$d/%2$d Pg. %3$d/%4$d - %1$d 的 %2$d 启用 - 大小:%s - 再按一次返回键退出 - 按两次返回键退出应用 - 退出确认 - 已保存漫画 - 页面缓存 - 其他缓存 - 存储占用 - 可用 - 从收藏中移除 - 选项 - 隐身模式 - 无章节 - 导入完毕 - 您可以从存储中删除原文件以节省空间 - 即将开始导入 - 订阅源 - %s - %s - 内容未找到或已移除 - 点击屏幕右侧或按下右键翻到下一页 - 高效阅读器控制 - 长按应用图标显示最近阅读的漫画 - 显示最近阅读漫画的快捷方式 - 重置 - 颜色校正 - 亮度 - 对比度 - 所选颜色设置将会应用于此漫画 - 保存还是放弃未保存的更改? - 放弃 - 设备上没有剩余空间 - 显示换页滑块 - Webtoon 缩放 - 不同语言 - 网络不可用 - 打开 Wi-Fi 或移动网络在线阅读漫画 - 同样清除新章节信息 - 服务器端错误 (%1$d)。请稍后再试 - 紧凑 - 已禁用图源 - 内容预加载 - 标为当前 - 语言 - 启用日志记录 - 分享日志 - 出于调试目的记录某些操作 - 显示可疑内容 - 动态 - 颜色方案 - 用网格视图显示 - Miku - Asuka - Mion - Rikka - Sakura - 服务 - Mamimi - Kanade - 这里什么也没有 - 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 - 允许不稳定更新 - 提示更新到测试版 - 已开始下载 - UserAgent 标头 - 要应用这些更改请重启程序 - 点击并长按项目排序 - 知道了 - 速度 - 导入先前创建的用户数据备份 - 在书架上显示 - 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 - 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 - + 重新排序 + 留空 + 浏览 + 自动滚动 + 在阅读器中显示信息栏 + 漫画压缩包 + 图片文件夹 + 漫画导入中 + Ch. %1$d/%2$d Pg. %3$d/%4$d + %1$d 的 %2$d 启用 + 大小:%s + 再按一次返回键退出 + 按两次返回键退出应用 + 退出确认 + 已保存漫画 + 页面缓存 + 其他缓存 + 存储占用 + 可用 + 从收藏中移除 + 选项 + 隐身模式 + 无章节 + 导入完毕 + 您可以从存储中删除原文件以节省空间 + 即将开始导入 + 订阅源 + %s - %s + 内容未找到或已移除 + 点击屏幕右侧或按下右键翻到下一页 + 高效阅读器控制 + 长按应用图标显示最近阅读的漫画 + 显示最近阅读漫画的快捷方式 + 重置 + 颜色校正 + 亮度 + 对比度 + 所选颜色设置将会应用于此漫画 + 保存还是放弃未保存的更改? + 放弃 + 设备上没有剩余空间 + 显示换页滑块 + Webtoon 缩放 + 不同语言 + 网络不可用 + 打开 Wi-Fi 或移动网络在线阅读漫画 + 同样清除新章节信息 + 服务器端错误 (%1$d)。请稍后再试 + 紧凑 + 已禁用图源 + 内容预加载 + 标为当前 + 语言 + 启用日志记录 + 分享日志 + 出于调试目的记录某些操作 + 显示可疑内容 + 动态 + 颜色方案 + 用网格视图显示 + Miku + Asuka + Mion + Rikka + Sakura + 服务 + Mamimi + Kanade + 这里什么也没有 + 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 + 允许不稳定更新 + 提示更新到测试版 + 已开始下载 + UserAgent 标头 + 要应用这些更改请重启程序 + 点击并长按项目排序 + 知道了 + 速度 + 导入先前创建的用户数据备份 + 在书架上显示 + 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 + 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 + 寻找相似 + 翻译 + WebView不可用:检查是否已安装WebView + 你可以使用自建同步服务器或默认服务器。如果你不知道自己在干什么请不要修改此处。 + 自动选择镜像 + 如果存在可用镜像,在出错时自动切换域名 + 已暂停 + 切换到移动网络时停止下载 + 移除已完成 + 取消所有 + 仅通过Wi-Fi下载 + 启用 + 不,谢谢 + 同步设定 + 服务器地址 + 暂停 + 恢复 + 忽略SSL错误 + 没有下载项 + 下载已经恢复 + 暂停下载 + 下载已被移除 + 下载被取消 + 你想要接收个人漫画推荐吗? + 推荐:%s + 偶尔对建议的漫画显示通知 + 更多 + 所有进行中的下载都将被取消,未下载完成的数据将丢失 + 你的下载历史将会永久删除 + 你可以登陆一个已有账号或创建新账号 + \ No newline at end of file From c8794d59f78e253565f5a633ef23b2025eb46f30 Mon Sep 17 00:00:00 2001 From: InfinityDouki56 Date: Sun, 4 Jun 2023 12:57:03 +0200 Subject: [PATCH 60/90] Translated using Weblate (Filipino) Currently translated at 93.0% (387 of 416 strings) Co-authored-by: InfinityDouki56 Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fil/ Translation: Kotatsu/Strings --- app/src/main/res/values-fil/strings.xml | 796 ++++++++++++------------ 1 file changed, 412 insertions(+), 384 deletions(-) diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 9c510180a..75a3e1d2f 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -1,387 +1,415 @@ - Na-update - Pinakabago - Maliwanag - Marka - Pansala - Tema - Madilim - Sundan ang sistema - May nangyaring error - Error sa network - Mga detalye - Mga kabanata - Listahan - Na-save - I-share ang larawan - Mag-angkat - Tanggalin - Hindi suportado ang operasyong ito - Pumili ng ZIP o CBZ file. - Kasaysayan at cache - Walang paglalarawan - Laki ng grid - Hanapin sa %s - Tanggalin ang manga - Permanenteng tanggalin ang \"%s\" sa device\? - Mga setting sa pagbasa - Magpalit ng (mga) pahina - Pindutan ng volume - Magpatuloy - I-clear ang cache ng mga thumbnail - Na-clear - Mga kilos lang - Available ang isang bagong bersyon ng app - Buksan sa web browser - Ang manga na ito ay may %s. I-save ang lahat ng ito\? - Mga abiso - %1$d ng %2$d sa - Mga bagong kabanata - Subukang i-reformulate ang query. - Ang iyong nabasa ay ipapakita dito - Ang iyong manga ay ipapakita dito - Mag-save muna ng isang bagay - I-save ito mula sa mga online na source o mag import ng mga file. - Istante - Animasyon ng pahina - Hindi magagamit - Walang available na storage - Iba pang storage - Tapos na - Lahat ng paborito - Walang laman ang kategorya - Basahin mamaya - Mga update - Mga resulta ng paghahanap - Laki: %s - I-clear ang feed ng mga update - Na-clear - Update - Ang pag update ng feed ay magsisimula sa lalong madaling panahon - Maghanap ng mga update - Ilagay ang password - Humingi ng password kapag sinimulan ang Kotatsu - Tungkol rito - Maghanap ng update - Kanan sa kaliwa - Bagong Kategorya - Pagkasyahin sa gitna - Panatilihin sa simula - Gumagamit ng mas kaunting power sa mga AMOLED na screen - I-backup at i-restore - Naibalik na - Naghahanda… - Hindi nahanap ang file - Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito - Ngayon lang - Kahapon - Matagal na ang nakalipas - Ngayong araw - I-tap para subukang muli - Lutasin - Inalis ang lahat ng mga cookie - I-clear ang feed - Suriin ang mga bagong kabanata - Mag-sign in - Mag-sign in upang tingnan ang nilalamang ito - Default: %s - Susunod - Kumpirmahin - Ang password ay dapat na 4 na character o higit pa - Maligayang pagdating - Na-save ang backup - Magbasa pa - Kulang ang kabanata - Ang pag-log in sa %s ay hindi suportado - Mga genre - Patuloy - Default - Hindi isali ang NSFW manga mula sa kasaysayan - Mga pahinang may bilang - Patakaran sa screenshot - Payagan - Palaging i-block - Mga mungkahi - Paganahin ang mga mungkahi - Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi - Huwag magmungkahi ng NSFW manga - Pinagana - Maghanap ng genre - Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. - Lokal na storage - Mga paborito - Nakaraan - Mode na listahan - Detalyadong listahan - Grid - Mga setting - Mga remote na source - Naglo-load… - Isara - Walang nahanap - Tanggalin - Bagong Kategorya - Nabasa - Wala pang paborito - I-paborito ito - Idagdag - I-save - Ibahagi - Lumikha ng shortcut… - Ibahagi sa %s - Maghanap - Maghanap ng manga - Nagda-download… - Nagpoproseso… - Na-download - Mga download - Pangalan - Sikat - Mga pahina - I-clear ang kasaysayan - I-clear ang kasaysayan ng paghahanap - Bagong bersyon: %s - Hindi tumutugma sa mga password - I-clear ang mga cookie - I-clear ang page cache - I-save - I-download - Mga setting ng abiso - Tunog ng abiso - Mga paboritong kategorya - Tanggalin - Parang walang laman dito… - Hanapin kung ano ang babasahin sa side menu. - Hanapin kung ano ang babasahin sa seksyong «Mag-explore» - Kamakailan - Folder para sa mga download - I-save ang pahina - Natanggal ang \"%s\" sa lokal na storage - Wala pang kasaysayan - Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? - Huwag suriin - Ulitin ang password - Protektahan ang app - Maling password - Bersyon %s - Mode ng scale - Walang available na update - Baliktarin - Grupo - Tahimik - Pagkasyahin sa lapad - Itim - Lumikha ng data backup - Ibalik mula sa backup - Naibalik ang lahat ng data - Ang data ay naibalik, ngunit may mga error - Ang napiling pagsasaayos ay maaalala para sa manga na ito - Isalin ang app na ito - Awtorisado na - Kinakailangan ang CAPTCHA - I-clear nang permanente ang lahat ng update history\? - Maglagay ng password para simulan ang app - Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. - Nakapila na - I-download o basahin ang nawawalang kabanata online. - Mala-log out ka mula sa lahat ng source - Tapos na - Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? - Pagsasalin - I-block sa NSFW - Magmungkahi ng manga batay sa iyong mga kagustuhan - Ang lahat ng data ay sinusuri nang lokal sa aparatong ito. Walang paglipat ng iyong personal na data sa anumang mga serbisyo - Hindi pinagana - Hindi ma-load ang listahan ng mga genre - I-reset ang filter - Ang mga bagong kabanata ng iyong binabasa ay makikita dito - I-rotate ang screen - Pagkasyahin sa tangkad - Hindi kailanman - Sa Wi-Fi lang - Nagco-compute… - Kabanata %1$d ng %2$d - Subukan ulit - Pag-aayos ng order - I-clear - Mga taps ng gilid - Mga ginamit na source - Magagamit na mga source - Lagi na lang - I-preload ang mga pahina - Naka-log in bilang %s - Iba\'t ibang wika - Maghanap ng kabanata - %1$s%% - Hitsura - Hindi isali ang mga genre - Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi - Nakumpleto na ang pagtanggal - Tumutulong na maiwasan ang pag-block ng iyong IP address - Naka-save na pagproseso ng manga - Mayroon nang account - Bumalik - Pag-synchronize - Ilagay ang iyong email upang magpatuloy - Itago - May mga bagong source ng manga - Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan - Paganahin ang mga abiso - Ayusin ang kategorya - Tina-track - Walang mga paboritong kategorya - Mag-log out - Magdagdag ng bookmark - Tinanggal ang bookmark - Inalis sa kasaysayan - DNS sa HTTPS - Default na mode - Automatikong matukoy ang reader mode - May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. - Ipadala - Muling pagbabasa - Binitawan - Manga mula sa iyong mga paborito - Ang iyong kamakailang nabasa na manga - Pagtanggal ng data - Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito - Ipakita lahat - Pumili ng saklaw - I-clear ang lahat ng kasaysayan - Maaari kang lumikha ng bookmark habang nagbabasa ng manga - Tinanggal ang mga bookmark - Random - Walang mga source ng manga - Paganahin ang mga source ng manga upang basahin ang manga online - Ayusin muli - Walang laman - Pindutin muli ang Bumalik upang lumabas - Pindutin ang Bumalik nang dalawang beses upang lumabas sa app - Pagkumpirma ng paglabas - Na-save na manga - Mag-Explore - Iba pang cache - Paggamit ng storage - Magagamit na - %s - %s - Inalis sa mga paborito - Mga pagpipilian - Incognito mode - Walang mga kabanata - Awtomatikong pag-scroll - Ch. %1$d/%2$d Pg. %3$d/%4$d - Ipakita ang information bar sa pagbasa - Archive ng mga comics - Folder na may mga larawan - Nakumpleto na ang pag-import - Magsisimula na ang pag-import - Feed - Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application - Ipakita ang mga kamakailang manga shortcut - Ergonomic na kontrol sa mambabasa - Pagwawasto ng kulay - Liwanag - Kaibahan - I-save o kalimutan ang mga hindi na-save na pagbabago\? - Kalimutan - Walang natitirang espasyo sa device - Pag-zoom sa webtoon - Iba\'t ibang wika - Server side error (%1$d). Subukang muli mamaya - I-clear din ang impormasyon tungkol sa mga bagong kabanata - Preloading ng nilalaman - Markahan bilang kasalukuyan - Wika - Ibahagi ang mga log - Magpakita ng kahina-hinalang nilalaman - Dynamic - Ipakita sa grid view - Asuka - Mion - Rikka - Sakura - Mamimi - Kanade - Wala naman dito - Mga serbisyo - Payagan ang mga hindi stable na update - Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa - Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save - Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa - Imbalidong domain - Huling 2 oras - Nabura ang kasaysayan - Pamahalaan - Wala pang bookmark - 18+ - Hindi natagpuan o inalis ang nilalaman - Magtala ng ilang pagkilos para sa mga layunin ng pag-debug - Permanenteng tanggalin ang mga napiling item sa device\? - Walang mga kabanata sa manga na ito - Nag-a-update ang mga mungkahi - Nilalaman - Pagbagal ng pag-download - Tatanggalin ang mga chapters sa background. Maaari itong tumagal ng ilang oras - Kinansela - I-sync ang iyong data - Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito - Pangalan - I-edit - Tanggalin ang bookmark - Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa - Mag-undo - Nagbabasa - Cache ng mga pahina - Mga bookmark - Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? + Na-update + Pinakabago + Maliwanag + Marka + Pansala + Tema + Madilim + Sundan ang sistema + May nangyaring error + Error sa network + Mga detalye + Mga kabanata + Listahan + Na-save + I-share ang larawan + Mag-angkat + Tanggalin + Hindi suportado ang operasyong ito + Pumili ng ZIP o CBZ file. + Kasaysayan at cache + Walang paglalarawan + Laki ng grid + Hanapin sa %s + Tanggalin ang manga + Permanenteng tanggalin ang \"%s\" sa device\? + Mga setting sa pagbasa + Magpalit ng (mga) pahina + Pindutan ng volume + Magpatuloy + I-clear ang cache ng mga thumbnail + Na-clear + Mga kilos lang + Available ang isang bagong bersyon ng app + Buksan sa web browser + Ang manga na ito ay may %s. I-save ang lahat ng ito\? + Mga abiso + %1$d ng %2$d sa + Mga bagong kabanata + Subukang i-reformulate ang query. + Ang iyong nabasa ay ipapakita dito + Ang iyong manga ay ipapakita dito + Mag-save muna ng isang bagay + I-save ito mula sa mga online na source o mag import ng mga file. + Istante + Animasyon ng pahina + Hindi magagamit + Walang available na storage + Iba pang storage + Tapos na + Lahat ng paborito + Walang laman ang kategorya + Basahin mamaya + Mga update + Mga resulta ng paghahanap + Laki: %s + I-clear ang feed ng mga update + Na-clear + Update + Ang pag update ng feed ay magsisimula sa lalong madaling panahon + Maghanap ng mga update + Ilagay ang password + Humingi ng password kapag sinimulan ang Kotatsu + Tungkol rito + Maghanap ng update + Kanan sa kaliwa + Bagong Kategorya + Pagkasyahin sa gitna + Panatilihin sa simula + Gumagamit ng mas kaunting power sa mga AMOLED na screen + I-backup at i-restore + Naibalik na + Naghahanda… + Hindi nahanap ang file + Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito + Ngayon lang + Kahapon + Matagal na ang nakalipas + Ngayong araw + I-tap para subukang muli + Lutasin + Inalis ang lahat ng mga cookie + I-clear ang feed + Suriin ang mga bagong kabanata + Mag-sign in + Mag-sign in upang tingnan ang nilalamang ito + Default: %s + Susunod + Kumpirmahin + Ang password ay dapat na 4 na character o higit pa + Maligayang pagdating + Na-save ang backup + Magbasa pa + Kulang ang kabanata + Ang pag-log in sa %s ay hindi suportado + Mga genre + Patuloy + Default + Hindi isali ang NSFW manga mula sa kasaysayan + Mga pahinang may bilang + Patakaran sa screenshot + Payagan + Palaging i-block + Mga mungkahi + Paganahin ang mga mungkahi + Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi + Huwag magmungkahi ng NSFW manga + Pinagana + Maghanap ng genre + Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. + Lokal na storage + Mga paborito + Kasaysayan + Mode na listahan + Detalyadong listahan + Grid + Mga setting + Mga source ng Manga + Naglo-load… + Isara + Walang nahanap + Tanggalin + Bagong Kategorya + Nabasa + Wala pang paborito + I-paborito ito + Idagdag + I-save + Ibahagi + Lumikha ng shortcut… + Ibahagi sa %s + Maghanap + Maghanap ng manga + Nagda-download… + Nagpoproseso… + Na-download + Mga download + Pangalan + Sikat + Mga pahina + I-clear ang kasaysayan + I-clear ang kasaysayan ng paghahanap + Bagong bersyon: %s + Hindi tumutugma sa mga password + I-clear ang mga cookie + I-clear ang page cache + I-save + I-download + Mga setting ng abiso + Tunog ng abiso + Mga paboritong kategorya + Tanggalin + Parang walang laman dito… + Hanapin kung ano ang babasahin sa side menu. + Hanapin kung ano ang babasahin sa seksyong «Mag-explore» + Kamakailan + Folder para sa mga download + I-save ang pahina + Natanggal ang \"%s\" sa lokal na storage + Wala pang kasaysayan + Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? + Huwag suriin + Ulitin ang password + Protektahan ang app + Maling password + Bersyon %s + Mode ng scale + Walang available na update + Baliktarin + Grupo + Tahimik + Pagkasyahin sa lapad + Itim + Lumikha ng data backup + Ibalik mula sa backup + Naibalik ang lahat ng data + Ang data ay naibalik, ngunit may mga error + Ang napiling pagsasaayos ay maaalala para sa manga na ito + Isalin ang app na ito + Awtorisado na + Kinakailangan ang CAPTCHA + I-clear nang permanente ang lahat ng update history\? + Maglagay ng password para simulan ang app + Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. + Nakapila na + I-download o basahin ang nawawalang kabanata online. + Mala-log out ka mula sa lahat ng source + Tapos na + Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? + Pagsasalin + I-block sa NSFW + Magmungkahi ng manga batay sa iyong mga kagustuhan + Ang lahat ng data ay lokal lamang na sinusuri sa device na ito at hindi kailanman ipinadala kahit saan. + Hindi pinagana + Hindi ma-load ang listahan ng mga genre + I-reset ang filter + Ang mga bagong kabanata ng iyong binabasa ay makikita dito + I-rotate ang screen + Pagkasyahin sa tangkad + Hindi kailanman + Sa Wi-Fi lang + Nagco-compute… + Kabanata %1$d ng %2$d + Subukan ulit + Pag-aayos ng order + I-clear + Mga taps ng gilid + Mga ginamit na source + Magagamit na mga source + Lagi na lang + I-preload ang mga pahina + Naka-log in bilang %s + Iba\'t ibang wika + Maghanap ng kabanata + %1$s%% + Hitsura + Hindi isali ang mga genre + Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi + Nakumpleto na ang pagtanggal + Tumutulong na maiwasan ang pag-block ng iyong IP address + Naka-save na pagproseso ng manga + Mayroon nang account + Bumalik + Pag-synchronize + Ilagay ang iyong email upang magpatuloy + Itago + May mga bagong source ng manga + Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan + Paganahin ang mga abiso + Ayusin ang kategorya + Tina-track + Walang mga paboritong kategorya + Mag-log out + Magdagdag ng bookmark + Tinanggal ang bookmark + Inalis sa kasaysayan + DNS sa HTTPS + Default na mode + Automatikong matukoy ang reader mode + May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. + Ipadala + Muling pagbabasa + Binitawan + Manga mula sa iyong mga paborito + Ang iyong kamakailang nabasa na manga + Pagtanggal ng data + Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito + Ipakita lahat + Pumili ng saklaw + I-clear ang lahat ng kasaysayan + Maaari kang lumikha ng bookmark habang nagbabasa ng manga + Tinanggal ang mga bookmark + Random + Walang mga source ng manga + Paganahin ang mga source ng manga upang basahin ang manga online + Ayusin muli + Walang laman + Pindutin muli ang Bumalik upang lumabas + Pindutin ang Bumalik nang dalawang beses upang lumabas sa app + Pagkumpirma ng paglabas + Na-save na manga + Mag-Explore + Iba pang cache + Paggamit ng storage + Magagamit na + %s - %s + Inalis sa mga paborito + Mga pagpipilian + Incognito mode + Walang mga kabanata + Awtomatikong pag-scroll + Ch. %1$d/%2$d Pg. %3$d/%4$d + Ipakita ang information bar sa pagbasa + Archive ng mga comics + Folder na may mga larawan + Nakumpleto na ang pag-import + Magsisimula na ang pag-import + Feed + Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application + Ipakita ang mga kamakailang manga shortcut + Ergonomic na kontrol sa mambabasa + Pagwawasto ng kulay + Liwanag + Kaibahan + I-save o kalimutan ang mga hindi na-save na pagbabago\? + Kalimutan + Walang natitirang espasyo sa device + Pag-zoom sa webtoon + Iba\'t ibang wika + Server side error (%1$d). Subukang muli mamaya + I-clear din ang impormasyon tungkol sa mga bagong kabanata + Preloading ng nilalaman + Markahan bilang kasalukuyan + Wika + Ibahagi ang mga log + Magpakita ng kahina-hinalang nilalaman + Dynamic + Ipakita sa grid view + Asuka + Mion + Rikka + Sakura + Mamimi + Kanade + Wala naman dito + Mga serbisyo + Payagan ang mga hindi stable na update + Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa + Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save + Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa + Imbalidong domain + Huling 2 oras + Nabura ang kasaysayan + Pamahalaan + Wala pang bookmark + 18+ + Hindi natagpuan o inalis ang nilalaman + Magtala ng ilang pagkilos para sa mga layunin ng pag-debug + Permanenteng tanggalin ang mga napiling item sa device\? + Walang mga kabanata sa manga na ito + Nag-a-update ang mga mungkahi + Nilalaman + Pagbagal ng pag-download + Tatanggalin ang mga kabanata sa background + Kinansela + I-sync ang iyong data + Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito + Pangalan + I-edit + Tanggalin ang bookmark + Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa + Mag-undo + Nagbabasa + Cache ng mga pahina + Mga bookmark + Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? \nAng lahat ng manga sa loob nito ay mawawala at hindi na ito mababawi. - Idinagdag ang bookmark - Awtomatikong matukoy kung ang manga ay webtoon - Huwag paganahin ang pag-optimize ng baterya - Tumutulong sa mga pagsusuri sa mga update sa background - Nakaplano - Nakumpleto na - Naka-hold - Huwag paganahin ang lahat - Gumamit ng fingerprint kung magagamit - Ulat - I-reset - Magmungkahi ng mga update sa mga beta na bersyon ng app - Hindi magagamit ang network - I-on ang Wi-Fi o mobile network para magbasa ng manga online - Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina - Ipakita ang slider ng paglipat ng pahina - Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>buksan ang manga sa isang web browser</a> upang matiyak na magagamit ito sa source<br>nito 2. Kung magagamit ito, magpadala ng isang ulat ng error sa mga developer. - Paganahin ang pag-log - Hindi pinagana ang source - Pag-import ng manga - Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo - Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito - Compact - Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. - Nagsimula na ang pag-download - Scheme ng kulay - Miku - Header ng UserAgent - B|kB|MB|GB|TB - Standard - Webtoon - Read mode - Error - Internal storage - External storage - Vibration - Domain - LED indicator - Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito - Nakuha ko - I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito - Mag-import ng dating ginawa na backup ng data ng user - Ipakita sa Istante - Bilis - Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. - Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. - Maghanap ng katulad - Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago - + Idinagdag ang bookmark + Awtomatikong matukoy kung ang manga ay webtoon + Huwag paganahin ang pag-optimize ng baterya + Tumutulong sa mga pagsusuri sa mga update sa background + Nakaplano + Nakumpleto na + Naka-hold + Huwag paganahin ang lahat + Gumamit ng fingerprint kung magagamit + Ulat + I-reset + Magmungkahi ng mga update sa mga beta na bersyon ng app + Hindi magagamit ang network + I-on ang Wi-Fi o mobile network para magbasa ng manga online + Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina + Ipakita ang slider ng paglipat ng pahina + Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>magbukas ng manga sa isang web browser</a> upang matiyak na available ito sa souce<br>2. Tiyaking ginagamit mo ang <a href=kotatsu://about>pinakabagong bersyon ng Kotatsu</a><br>3. Kung available ito, magpadala ng ulat ng error sa mga developer. + Paganahin ang pag-log + Hindi pinagana ang source + Pag-import ng manga + Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo + Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito + Compact + Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. + Nagsimula na ang pag-download + Scheme ng kulay + Miku + Header ng UserAgent + B|kB|MB|GB|TB + Standard + Webtoon + Read mode + Error + Internal storage + External storage + Vibration + Domain + LED indicator + Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito + Nakuha ko + I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito + Mag-import ng dating ginawa na backup ng data ng user + Ipakita sa Istante + Bilis + Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. + Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. + Maghanap ng katulad + Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago + Mga pagsasalin + Hindi available ang WebView: tingnan kung naka-install ang WebView provider + Paganahin + Na-pause ang mga pag-download + Mga setting ng pag-synchronize + Address ng server + Maaari kang gumamit ng self-hosted synchronization server o isang default. Huwag baguhin ito kung hindi ka sigurado sa iyong ginagawa. + Huwag pansinin ang mga error sa SSL + Awtomatikong pumili ng mirror + Awtomatikong lumipat ng mga domain para sa mga remote source sa mga error kung available ang mga mirror + Kanselahin lahat + Mag-download lamang sa pamamagitan ng Wi-Fi + Itigil ang pag-download kapag lumipat sa isang mobile network + Naka-pause + Tanggalin ang nakumpleto na + Mga mungkahi: %s + I-pause + Minsang magpakita ng mga notification na may iminungkahing manga + Higit pa + Salamat nalang + Ipagpatuloy + Ang lahat ng mga aktibong pag download ay kakanselahin, bahagyang na download na data ay mawawala + Permanenteng ide-delete ang iyong history ng mga pag-download + Wala kang anumang mga pag-download + Ipinagpatuloy ang mga pag-download + Gusto mo bang makatanggap ng personalized na mga mungkahi sa manga\? + Inalis na ang mga download + Nakansela ang mga pag-download + \ No newline at end of file From 7bc33adca8c30e55b2a5a302a7f3ea62619b2b11 Mon Sep 17 00:00:00 2001 From: tryvseu Date: Sun, 4 Jun 2023 12:57:04 +0200 Subject: [PATCH 61/90] Translated using Weblate (Norwegian Nynorsk) Currently translated at 85.5% (356 of 416 strings) Co-authored-by: tryvseu Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/nn/ Translation: Kotatsu/Strings --- app/src/main/res/values-nn/strings.xml | 707 +++++++++++++------------ 1 file changed, 359 insertions(+), 348 deletions(-) diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 28c7e9b36..905125266 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -1,351 +1,362 @@ - Det hende ein feil - Rutenett - Innstillingar - Mangakjelder - Tøm historikken - Historikken er tom - Les - Lik - Ny hop - Legg til - Hent - Lag ein snarveg … - Del %s - Søk - Søk manga - Hentar … - Handsamar … - Henta - Nyaste - Omdøme - Sil ut - Ljos - Sider - Tøm - Tøm lesehistorikken for godt\? - Tak bort - Hent sida - Henta - Del biletet - Før inn - Slett - Vel ei ZIP- eller CBZ-fil. - Ingen utgreiing - Tøm mellomminnet til sida - Vanleg - Nettserie - Rutenettstorleik - Slett mangaen - Slett «%s» ifrå eininga\? - Leseinnstillingar - Bla med - Hald fram - Feil - Tøm mellomminnet for småbilete - Tøm søkehistorikken - Tømt - Berre handrørsler - Hent - Varsel - %1$d av %2$d - Hent - Varselinnstillingar - Varselljod - Varselljos - Dirring - Hopar til leiting - Hent ifrå nettkjelder eller før inn filer. - Hylla - Nytt - Legg henta mangaar i: - Gjort - Alt du likar - Tom hop - Les seinare - Oppdateringar - Søkesvar - Ny utgåve: %s - Tømt - Snu skjermen - Leit etter oppdateringar - Nei - Om - Leit etter oppdateringar - Høgre-til-venstre - Lesevising - Høv til høgda - Høv til breidda - Svart - Tryggleikskopiering og gjenoppretting - Lag ein tryggleikskopi - Gjenoppretta - Fann ikkje fila - Gjenoppretta all data - Gjenoppretta dataa, men med feil - Trykk for å røyna att - Listeslag - Henta - Likar - Historikk - Nettverksfeil - Liste - Hentar fram … - Steng - Røyn att - Fann ikkje noko - Del - Henta - Namn - Oppdatert - Vising - Lyd systemet - Mørk - Historikken og mellomminnet - Hent noko først - Ikkje tilgjengeleg - Oppdater - Storleik: %s - Brukar mindre straum på AMOLED-skjermar - Utgåve %s - Ingen tilgjengelege oppdateringar - Ny hop - Midtstill - Auk byrjinga av sida - Gjenopprett ifrå ein tryggleikskopi - Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting - Førebur … - Forval - No - I dag - I går - Lenge sida - Lesing - Randetrykk - Ljodstyrkeknappar - Ei ny utgåve av appen er tilgjengeleg - Opne i ein nettlesar - Denne mangaen har %s. Hent alle\? - Det du les vert vist her - Rit inn lykelordet - Gjentak lykelordet - Lykelorda er ulike - Brigde av oppsettet vedkjem berre denne mangaen - Stille - Krev CAPTCHA - Løys - Slett infokapslane - Sletta infokapslane - Tøm oppdateringshistorikken\? - Logg inn - Neste - Stadfest - Lykelordet må vera lengre enn fire teikn - Tryggleikskopi laga - Les meir - I kø - Omset denne appen - Omsetjing - Godkjend - Slag - Fullgjort - I gang - Utelèt mangaar med vakse innhald ifrå historikken - Sidetal - Nytta kjelder - Tilgjengelege kjelder - Skjermbilete - Hindre alltid - Råd - Slå på råd - Rå om mangaar ut ifrå det du har lese - Byrja å lesa nokre mangaar for å få personlege råd - Ikkje rå mangaar med vakse innhald - Påslegen - Kunne ikkje hente inn slaglista - Finn slag - Ulike mål - %1$s%% - Innhald - Oppdaterer råd - Utelat slag - Sletta - Avgrens hentesnøggleiken - Lægjer vona for at IP-adressa di vert blokkert - Handsamar henta manga - Avbroten - Kontoen finst alt - Attende - Synkroniser dataet ditt - Rit inn e-postadressa di for å halda fram - Skjul - Namn - Brigd - Brigd hopen - Sporing - Ingen likte hopar - Logg ut - Bokmerk - Tak bort bokmerket - Bokmerke - Teken bort ifrå historikken - DNS over HTTPS - Forvald lesing - Finn sjølvverkande ut av lesing - Finn sjølvverkande ut av om mangaen er ein nettserie - Slå av batterilenging - Send - Les - Skal lesa - Les att - Lesen - På vent - Gjeven opp - Slå av alle - Mangaar du har nyleg lese - Sletting av data - Vis % lesen i historikken og likerlista - Kan løysa nokre feil. Alle godkjenningar vert ugilde - Vis alle - Ugildt domene - Vel område - Tøm heile historikken - Tømte historikken - Ingen bokmerke endå - Du kan lage bokmerke medan du les - Tok bort bokmerka - Ingen mangakjelder - Slå på minst ei mangakjelde for å lesa mangaar på nett - Tilfeldig - Flytt - Tom - Trykk Attende att for å gå or appen - Utgåingsstadfesting - Mellominnet for sider - Mellomminnet for anna - Tilgjengeleg - %s - %s - Teken or likerlista - Fann ikkje innhaldet - Bla sjølvverkande - Teikneseriearkiv - Mappe med bilete - Fører inn manga - Brigd letar - Ljosstyrk - Still attende - Spar eller avvis dei usparte brigda\? - Avvis - Eininga er fylt - Vis ei rulleline til blading - Auk/mink nettseriar - Ulike mål - Nettverk ikkje tilgjengeleg - Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett - Tjenarfeil (%1$d). Røyn att seinare - Kjelde avslegen - Hent inn innhald på forhand - Merk som aktuelt - Mål - Del loggføringar - Slå på loggføring - Tak opp nokre gjerder til bruk i istandsetjing. - Skiftande - Letar - Vis som rutenett - Rikka - Asuka - Sakura - Mamimi - Kanade - Ingenting her - Tenester - Har byrja å hente - Tøm søkehistorikken\? - Velkomen - Du vert logga ut ifrå alle kjeldane - Hindre ved vakse innhald - Slett - Her var det tomt … - Spør om lykelordet ved byrjing av appen - Feil lykelord - Vern appen - Logg inn for å sjå dette innhaldet - Vern appen med eit lykelord - All data vert handsama på eininga di og vert ikkje førte over til noka teneste - Avslegen - Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. - Aldri - Berre på Wi-Fi - 18+ - Alltid - Hent sider på forhand - Utsjånad - Slett valde ting ifrå eininga di\? - Logga inn som %s - Opplys om kva slags slag du ikkje vil få råd om - Synkronisering - Nye mangakjelder tilgjengelege - Du kjem til å få varsel når mangaar du les vert oppdaterte - Slå på varsel - La til eit bokmerke - Tok bort bokmerket - Angre - Nytt fingermerke om tilgjengeleg - Vis leseframgang - Mangaar du likar - Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart - Slett dei valde hopane\? + Det hende ein feil + Rutenett + Innstillingar + Mangakjelder + Tøm historikken + Historikken er tom + Les + Lik + Ny hop + Legg til + Hent + Lag ein snarveg … + Del %s + Søk + Søk manga + Hentar … + Handsamar … + Henta + Nyaste + Omdøme + Sil ut + Ljos + Sider + Tøm + Tøm lesehistorikken for godt\? + Tak bort + Hent sida + Henta + Del biletet + Før inn + Slett + Vel ei ZIP- eller CBZ-fil. + Ingen utgreiing + Tøm mellomminnet til sida + Vanleg + Nettserie + Rutenettstorleik + Slett mangaen + Slett «%s» ifrå eininga\? + Leseinnstillingar + Bla med + Hald fram + Feil + Tøm mellomminnet for småbilete + Tøm søkehistorikken + Tømt + Berre handvendingar + Hent + Varsel + %1$d av %2$d + Hent + Varselinnstillingar + Varselljod + Varselljos + Dirring + Hopar til leiting + Hent ifrå nettkjelder eller før inn filer. + Hylla + Nytt + Legg henta mangaar i: + Ferdig + Alt du likar + Tom hop + Les seinare + Oppdateringar + Søkesvar + Ny utgåve: %s + Tømt + Snu skjermen + Leit etter oppdateringar + Nei + Om + Leit etter oppdateringar + Høgre-til-venstre + Lesevising + Høv til høgda + Høv til breidda + Svart + Tryggleikskopiering og gjenoppretting + Lag ein tryggleikskopi + Gjenoppretta + Fann ikkje fila + Gjenoppretta all data + Gjenoppretta dataa, men med feil + Trykk for å røyna att + Listeslag + Henta + Likar + Historikk + Nettverksfeil + Liste + Hentar fram … + Steng + Røyn att + Fann ikkje noko + Del + Henta + Namn + Oppdatert + Vising + Lyd systemet + Mørk + Historikken og mellomminnet + Hent noko først + Ikkje tilgjengeleg + Oppdater + Storleik: %s + Brukar mindre straum på AMOLED-skjermar + Utgåve %s + Ingen tilgjengelege oppdateringar + Ny hop + Midtstill + Auk byrjinga av sida + Gjenopprett ifrå ein tryggleikskopi + Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting + Førebur … + Forval + No + I dag + I går + Lenge sida + Lesing + Randetrykk + Ljodstyrkeknappar + Ei ny utgåve av appen er tilgjengeleg + Opne i ein nettlesar + Denne mangaen har %s. Hent alle\? + Det du les vert vist her + Rit inn lykelordet + Gjentak lykelordet + Lykelorda er ulike + Brigde av oppsettet vedkjem berre denne mangaen + Stille + Krev CAPTCHA + Løys + Slett infokapslane + Sletta infokapslane + Tøm oppdateringshistorikken\? + Logg inn + Neste + Stadfest + Lykelordet må vera lengre enn fire teikn + Tryggleikskopi laga + Les meir + I kø + Omset denne appen + Omsetjing + Godkjend + Slag + Fullgjort + I gang + Utelèt mangaar med vakse innhald ifrå historikken + Sidetal + Nytta kjelder + Tilgjengelege kjelder + Skjermbilete + Hindre alltid + Råd + Slå på råd + Rå om mangaar ut ifrå det du har lese + Byrja å lesa nokre mangaar for å få personlege råd + Ikkje rå mangaar med vakse innhald + Påslegen + Kunne ikkje hente inn slaglista + Finn slag + Ulike mål + %1$s%% + Innhald + Oppdaterer råd + Utelat slag + Sletta + Avgrens hentesnøggleiken + Lægjer vona for at IP-adressa di vert blokkert + Handsamar henta manga + Avbroten + Kontoen finst alt + Attende + Synkroniser dataet ditt + Rit inn e-postadressa di for å halda fram + Skjul + Namn + Brigd + Brigd hopen + Sporing + Ingen likte hopar + Logg ut + Bokmerk + Tak bort bokmerket + Bokmerke + Teken bort ifrå historikken + DNS over HTTPS + Forvald lesing + Finn sjølvverkande ut av lesing + Finn sjølvverkande ut av om mangaen er ein nettserie + Slå av batterilenging + Send + Les + Skal lesa + Les att + Lesen + På vent + Gjeven opp + Slå av alle + Mangaar du har nyleg lese + Sletting av data + Vis % lesen i historikken og likerlista + Kan løysa nokre feil. Alle godkjenningar vert ugilde + Vis alle + Ugildt domene + Vel område + Tøm heile historikken + Tømte historikken + Ingen bokmerke endå + Du kan lage bokmerke medan du les + Tok bort bokmerka + Ingen mangakjelder + Slå på minst ei mangakjelde for å lesa mangaar på nett + Tilfeldig + Flytt + Tom + Trykk Attende att for å gå or appen + Utgåingsstadfesting + Mellominnet for sider + Mellomminnet for anna + Tilgjengeleg + %s - %s + Teken or likerlista + Fann ikkje innhaldet + Bla sjølvverkande + Teikneseriearkiv + Mappe med bilete + Fører inn manga + Brigd letar + Ljosstyrk + Still attende + Spar eller avvis dei usparte brigda\? + Avvis + Eininga er fylt + Vis ei rulleline til blading + Auk/mink nettseriar + Ulike mål + Nettverk ikkje tilgjengeleg + Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett + Tjenarfeil (%1$d). Røyn att seinare + Kjelde avslegen + Hent inn innhald på forhand + Merk som aktuelt + Mål + Del loggføringar + Slå på loggføring + Tak opp nokre gjerder til bruk i istandsetjing. + Skiftande + Letar + Vis som rutenett + Rikka + Asuka + Sakura + Mamimi + Kanade + Ingenting her + Tenester + Har byrja å hente + Tøm søkehistorikken\? + Velkomen + Du vert logga ut ifrå alle kjeldane + Hindre ved vakse innhald + Slett + Her var det tomt … + Spør om lykelordet ved byrjing av appen + Feil lykelord + Vern appen + Logg inn for å sjå dette innhaldet + Vern appen med eit lykelord + All data vert handsama på eininga di og vert ikkje førte over til noka teneste + Avslegen + Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. + Aldri + Berre på Wi-Fi + 18+ + Alltid + Hent sider på forhand + Utsjånaden + Slett valde ting ifrå eininga di\? + Logga inn som %s + Opplys om kva slags slag du ikkje vil få råd om + Synkronisering + Nye mangakjelder tilgjengelege + Du kjem til å få varsel når mangaar du les vert oppdaterte + Slå på varsel + La til eit bokmerke + Tok bort bokmerket + Angre + Nytt fingermerke om tilgjengeleg + Vis leseframgang + Mangaar du likar + Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart + Slett dei valde hopane\? \nDu kan ikkje angre. Alle mangaane inni vert tekne ut av likerlista. - Innstillingar - Dei siste to timane - Handsam - Trykk Attende to gongar for å gå or appen - Henta mangaar - Privat modus - Førte inn - Slett den opphavlege fila for å frigjera rom - Byrjar å føra inn snart - Motsetjing - Brigde av letane vedkjem berre denne mangaen - Vis mistenksamt innhald - Mion - Miku - Byrja om appen for å nytta desse brigda - Kapittel - Utreknar… - Kapittel %1$d av %2$d - Ustødd gjerd - B|kB|MB|GB|TB - Domene - Nye kapittel - Mangaane dine vert viste her - Siderørsle - Nye kapittel av det du les vert viste her - Sjå etter nye kapittel - Siste øvst - Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. - Hent eller les dette saknande kapittelet på nettet. - Saknar kapittelet - Finn kapittel - Ingen kapittel i denne mangaen - Kapittel vert teken bort i bakgrunnen - Sjå etter og varsle om nye kapittel - Nye kapittel vert merkte i listene utan varsel - Gransk - Ingen kapittel - Ka. %1$d/%2$d Side %3$d/%4$d - Vis opplysingsområde i lesevisinga - Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side - Samantrengt - Vis i hylla - Før inn ei tryggleikskopi av brukardata - Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. - Snøggleik - Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. - Tøm au opplysingar om nye kapittel - Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. - Skjønar - Trykk og hald på eit element for å flytta på det - + Innstillingar + Dei siste to timane + Handsam + Trykk Attende to gongar for å gå or appen + Henta mangaar + Privat modus + Førte inn + Slett den opphavlege fila for å frigjera rom + Byrjar å føra inn snart + Motsetjing + Brigde av letane vedkjem berre denne mangaen + Vis mistenksamt innhald + Mion + Miku + Byrja om appen for å nytta desse brigda + Kapittel + Utreknar… + Kapittel %1$d av %2$d + Ustødd gjerd + B|kB|MB|GB|TB + Domene + Nye kapittel + Mangaane dine vert viste her + Siderørsle + Nye kapittel av det du les vert viste her + Sjå etter nye kapittel + Siste øvst + Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. + Hent eller les dette saknande kapittelet på nettet. + Saknar kapittelet + Finn kapittel + Ingen kapittel i denne mangaen + Kapittel vert teken bort i bakgrunnen + Sjå etter og varsle om nye kapittel + Nye kapittel vert merkte i listene utan varsel + Gransk + Ingen kapittel + Ka. %1$d/%2$d Side %3$d/%4$d + Vis opplysingsområde i lesevisinga + Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side + Samantrengt + Vis i hylla + Før inn ei tryggleikskopi av brukardata + Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. + Snøggleik + Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. + Tøm au opplysingar om nye kapittel + Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. + Skjønar + Trykk og hald på eit element for å flytta på det + Sletta «%s» ifrå eininga + Indre gøyme + Ytre gøyme + Ingen tilgjengelege gøyme + Anna gøyme + Røyn å skriva det om. + Ingen likte enno + Mest lest for tida + Søk på %s + Finn lesnadar i sidemenyen. + Finn lesnadar i «Gransk»-delen + \ No newline at end of file From 56bc0dbf075c6029e7c02ea3c41c90f4712d3dd0 Mon Sep 17 00:00:00 2001 From: Subham Jena Date: Sun, 4 Jun 2023 12:57:04 +0200 Subject: [PATCH 62/90] Translated using Weblate (Odia) Currently translated at 7.3% (31 of 421 strings) Translated using Weblate (Odia) Currently translated at 5.5% (23 of 416 strings) Co-authored-by: Subham Jena Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/or/ Translation: Kotatsu/Strings --- app/src/main/res/values-or/strings.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index d8db4f084..b55162b4b 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -11,4 +11,19 @@ ଥିମ୍ ଵେଗ ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା + ପାଠକ ସେଟିଂ + ଵିଜ୍ଞପ୍ତି + ଥାକ + ସର୍ଵଦା + ଵିଷୟଵସ୍ତୁ + ଵିଜ୍ଞପ୍ତି ସେଟିଂ + ରୂପ + ଯାଞ୍ଚ କରନି + ଅଦ୍ୟତନ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଗତକାଲି + ଆଜି + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରି ଏହା ଵିଷୟରେ ସୂଚିତ କରିବା + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଫାଇଲ ମିଳୁନାହିଁ + ବ୍ୟାକଅପ୍ ଓ ପୁନରୁଦ୍ଧାର \ No newline at end of file From 6dc81468d2dbab80223a69030386005b8646d1d2 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Sun, 4 Jun 2023 12:57:05 +0200 Subject: [PATCH 63/90] Translated using Weblate (Spanish) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (422 of 422 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (7 of 7 strings) Translated using Weblate (Spanish) Currently translated at 100.0% (417 of 417 strings) Co-authored-by: gallegonovato Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/es/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/es/ Translation: Kotatsu/Strings Translation: Kotatsu/plurals --- app/src/main/res/values-es/plurals.xml | 6 +++--- app/src/main/res/values-es/strings.xml | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-es/plurals.xml b/app/src/main/res/values-es/plurals.xml index 3deb92806..f5f4a4cbb 100644 --- a/app/src/main/res/values-es/plurals.xml +++ b/app/src/main/res/values-es/plurals.xml @@ -1,9 +1,9 @@ - Total de %1$d página - Total de %1$d páginas - Total de %1$d páginas + Página total %1$d + Páginas totales %1$d + Página totales %1$d %1$d elemento diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 613c1c1f1..ae1169138 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -412,4 +412,18 @@ ¿Quieres recibir sugerencias sobre mangas personalizadas\? Traducciones WebView no está disponible: comprueba si el proveedor de WebView está instalado + Borrar la caché de la red + Tipo + Dirección + Puerto + Proxy + Valor no válido + %1$s (%2$s) + Optimización de imágenes proxy + Nombre de usuario + Descargado + Autorización (opcional) + Utiliza el servicio wsrv.nl para reducir el uso del tráfico y acelerar la carga de imágenes si es posible + Contraseña + Invertir los colores \ No newline at end of file From 3e46b3957c932de67c5a6535b286db67a541d6e3 Mon Sep 17 00:00:00 2001 From: Bai Date: Sun, 4 Jun 2023 12:57:05 +0200 Subject: [PATCH 64/90] Translated using Weblate (Turkish) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Turkish) Currently translated at 99.7% (416 of 417 strings) Co-authored-by: Bai Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/ Translation: Kotatsu/Strings --- app/src/main/res/values-tr/strings.xml | 794 +++++++++++++------------ 1 file changed, 419 insertions(+), 375 deletions(-) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index e5685c1b8..d8eae7df3 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,378 +1,422 @@ - Ağ hatası - Dahili Depolama - Favoriler - Geçmiş - Bölümler - Liste - Detaylı liste - Izgara - Liste modu - Yükleniyor… - Kapat - Tekrar dene - Geçmişi temizle - Hiçbir şey bulunamadı - Geçmiş yok - Oku - Henüz favorileriniz yok - Favoriniz - Yeni kategori - Ekle - Kaydet - Paylaş - %s Paylaş - Ara - Manga ara - İndiriliyor… - İşleniyor… - İndirildi - İndirilenler - Ad - Güncellenme - Yeniler - Puanlama - Litre - Tema - Açık - Koyu - Takip sistemi - Sayfalar - Temizle - Tüm okuma geçmişi kalıcı olarak silinsin mi\? - Kaldır - “%s” yerel depolama alanından sil - Sayfayı kaydet - Resmi paylaş - Popüler - Detaylar - Ayarlar - Kaydet - Bir hata oluştu - Uzak kaynaklar - Geçmiş ve önbellek - Temizlendi - Devam - Müsait değil - Boş kategori - Kaldır - Sil - Bölüm %1$d / %2$d - Bir ZIP veya CBZ dosyası seçin. - Okuma modu - Izgara boyutu - Webtoon - B|kB|MB|GB|TB - Okuyucu ayarları - Ses butonları - Hata - Küçük resim önbelleğini temizle - Yalnızca hareketler - Alan adi - Web tarayıcısında aç - Yeni bölümler - Bildirim ayarları - Bildirim sesi - LED göstergesi - Titreşim - Diğer depolama - Güncellemeler - Kısayol oluştur… - İçe aktar - Mangayı sil - Bilgi işleniyor… - Sıralama düzeni - Açıklama yok - Bu işlem desteklenmiyor - Standart - Sayfa önbelleğini temizle - %s üzerinde ara - Dahili depolama - Bildirimler - Sayfaları değiştir - Kaydet - İndir - İndirilenler klasörü - Harici depolama - Uygulamanın yeni bir sürümü mevcut - Favori kategoriler - Bitti - Sonra oku - Sayfa animasyonu - Kullanılabilir depolama alanı yok - “%s” cihazdan kalıcı olarak silinsin mi\? - Arama geçmişini temizle - Burası biraz boş… - Ekranı döndür - Ölçek modu - Yüksekliğe sığdır - Siyah - Başlangıçta tut - Akışı temizle - Bu eksik bölümü çevrim içi olarak indirin veya okuyun. - Yedekten geri yükle - Güncelle - Oturum aç - Bitti - Hakkında - Bu içeriği görüntülemek için oturum açın - Onayla - Yetkilendirildi - Az önce - Kenar dokunuşları - Bu mangada %s var. Hepsi kaydedilsin mi\? - %1$d / %2$d açık - Sorguyu yeniden biçimlendirmeyi deneyin. - Okuduklarınız burada görüntülenecek - Yan menüde ne okuyacağınızı bulun. - Önce bir şey kaydedin - Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. - Raf - Son - Boyut: %s - Temizlendi - Parola gir - Kotatsu başlatılırken parola sor - Güncellemeleri ara - Güncelleme akışını temizle - Akış güncellemesi yakında başlayacak - Sürüm %s - Güncellemeleri denetle - Merkeze sığdır - Genişliğe sığdır - AMOLED ekranlarda daha az güç kullanır - Yedekle ve geri yükle - Veri yedeği oluştur - Geri yüklendi - Hazırlanıyor… - Dün - Grup - Sessiz - Çöz - Çerezleri temizle - Öntanımlı: %s - Ters - Parola 4 veya daha fazla karakterden oluşmalıdır - Hoş geldiniz - Sıraya alındı - Bölüm eksik - Bu uygulamayı çevirin - Çeviri - Devam ediyor - Tüm kaynaklardaki oturumunuz kapatılacak - Kullanılan kaynaklar - Kullanılabilir kaynaklar - Uygunsuz mangayı geçmişten hariç tut - Numaralı sayfalar - Arama sonuçları - Parolayı tekrarla - Denetleme - Yanlış parola - Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz - Uzun zaman önce - Bugün - Güncelleme yok - Tüm favoriler - Okuduklarınızın yeni bölümleri burada gösterilir - Yeni sürüm: %s - Uygulamayı koru - Parolalar eşleşmiyor - Sağdan-sola - Yeni kategori - Dosya bulunamadı - Tüm veriler geri yüklendi - Veriler geri yüklendi, ancak hatalar var - Tekrar denemek için dokunun - İleri - CAPTCHA gerekli - Tüm çerezler kaldırıldı - Seçilen yapılandırma bu manga için hatırlanacak - Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? - Uygulamayı başlatmak için bir parola girin - Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? - Yedek kaydedildi - Türler - Öntanımlı - %s üzerinde oturum açma desteklenmiyor - Daha fazla oku - Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. - Ekran görüntüsü politikası - Uygunsuzlarda engelle - Her zaman engelle - İzin ver - Yeni bölümleri denetle - Öneriler - Önerileri etkinleştir - Tercihlerinize göre manga önerileri alın - Tüm veriler aygıt üzerinde yerel olarak işlenir. Kişisel verilerinizin herhangi bir hizmete aktarılması söz konusu değildir - Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız - Uygunsuz manga önerme - Etkin - Devre dışı - Türler listesi yüklenemiyor - Filtreyi sıfırla - Tür bul - Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. - Her zaman - Hiçbir zaman - Yalnızca Wi-Fi\'de - Sayfaları önceden yükle - %s olarak oturum açıldı - 18+ - Çeşitli diller - Bölüm bul - Bu mangada bölüm yok - %%%1$s - İçerik - Öneriler güncelleniyor - Görünüm - Türleri hariç tut - Önerilerde görmek istemediğiniz türleri belirtin - Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? - Kaldırma tamamlandı - Bölümler arka planda kaldırılacaktır. Bu biraz zaman alabilir - İndirmeyi yavaşlat - IP adresinizin engellenmesinden kaçınmanıza yardımcı olur - Kaydedilen manga işleme - Gizle - Yeni manga kaynakları var - Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak - Bildirimleri etkinleştir - Yeni bölümleri denetle ve bildirim gönder - Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız - Favori kategori yok - Ad - Düzenle - Kategoriyi düzenle - Yer imi ekle - Yer imini kaldır - Yer imleri - Yer imi kaldırıldı - Yer imi eklendi - Geri al - Geçmişten kaldırıldı - HTTPS üzerinden DNS - Okuyucu modunu otomatik algıla - Manganın webtoon olup olmadığını otomatik olarak algıla - Öntanımlı mod - Pil iyileştirmesini devre dışı bırak - Arka planda güncelleme denetimlerine yardımcı olur - Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. - Gönder - Tümünü devre dışı bırak - Varsa parmak izi kullan - Favorilerinizden mangalar - Son okuduğunuz mangalar - Bildir - İzleme - Oturumu kapat - Okunuyor - Tamamlandı - Okuma ilerleme göstergelerini göster - Verileri sil - Geçmişte ve favorilerde okunma yüzdesini göster - Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir - Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır - Beklemede - Bırakıldı - Planlandı - Yeniden okunuyor - Tümünü göster - Geçersiz etki alanı - Aralık seç - İçerik bulunamadı veya kaldırıldı - Manganız burada görüntülenecek - İptal edilmiş - Hesap zaten var - Geri - Senkronizasyon - Verini yedekle - Devam etmek için E-Postanızı girin - Tüm gecmişi temizle - Son 2 saat - Geçmiş temizlendi - Yönet - Yer işareti yok - Manga okurken yer işareti oluşturabilirsiniz - Yer işaretleri kaldırıldı - Manga kaynağı yok - Çevrimiçi manga okumak için manga kaynaklarını aktif edin - Rastgele - Boş - Keşfet - Çıkmak için tekrar Geri tıkla - Çıkmak için iki defa Geri tıkla - Favorilerden kaldırıldı - Çıkış doğrulaması - Çizgi roman arşivi - Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. Mevcutsa, geliştiricilere bir hata reporu gönderin. - «Keşfet» kısmında neler okuyacağınızı bulun - Seçilen favori kategorileri silmek istediğinizden emin misiniz\? + Ağ hatası + Dahili Depolama + Favoriler + Geçmiş + Bölümler + Liste + Detaylı liste + Izgara + Liste modu + Yükleniyor… + Kapat + Tekrar dene + Geçmişi temizle + Hiçbir şey bulunamadı + Geçmiş yok + Oku + Henüz favorileriniz yok + Favoriniz + Yeni kategori + Ekle + Kaydet + Paylaş + %s Paylaş + Ara + Manga ara + İndiriliyor… + İşleniyor… + İndirildi + İndirilenler + Ad + Güncellenme + Yeniler + Puanlama + Litre + Tema + Açık + Koyu + Takip sistemi + Sayfalar + Temizle + Tüm okuma geçmişi kalıcı olarak silinsin mi\? + Kaldır + “%s” yerel depolama alanından sil + Sayfayı kaydet + Resmi paylaş + Popüler + Detaylar + Ayarlar + Kaydet + Bir hata oluştu + Manga kaynakları + Geçmiş ve önbellek + Temizlendi + Devam + Müsait değil + Boş kategori + Kaldır + Sil + Bölüm %1$d / %2$d + Bir ZIP veya CBZ dosyası seçin. + Okuma modu + Izgara boyutu + Webtoon + B|kB|MB|GB|TB + Okuyucu ayarları + Ses butonları + Hata + Küçük resim önbelleğini temizle + Yalnızca hareketler + Alan adi + Web tarayıcısında aç + Yeni bölümler + Bildirim ayarları + Bildirim sesi + LED göstergesi + Titreşim + Diğer depolama + Güncellemeler + Kısayol oluştur… + İçe aktar + Mangayı sil + Bilgi işleniyor… + Sıralama düzeni + Açıklama yok + Bu işlem desteklenmiyor + Standart + Sayfa önbelleğini temizle + %s üzerinde ara + Dahili depolama + Bildirimler + Sayfaları değiştir + Kaydet + İndir + İndirilenler klasörü + Harici depolama + Uygulamanın yeni bir sürümü mevcut + Favori kategoriler + Bitti + Sonra oku + Sayfa animasyonu + Kullanılabilir depolama alanı yok + “%s” cihazdan kalıcı olarak silinsin mi\? + Arama geçmişini temizle + Burası biraz boş… + Ekranı döndür + Ölçek modu + Yüksekliğe sığdır + Siyah + Başlangıçta tut + Akışı temizle + Bu eksik bölümü çevrim içi olarak indirin veya okuyun. + Yedekten geri yükle + Güncelle + Oturum aç + Bitti + Hakkında + Bu içeriği görüntülemek için oturum açın + Onayla + Yetkilendirildi + Az önce + Kenar dokunuşları + Bu mangada %s var. Hepsi kaydedilsin mi\? + %1$d / %2$d açık + Sorguyu yeniden biçimlendirmeyi deneyin. + Okuduklarınız burada görüntülenecek + Yan menüde ne okuyacağınızı bulun. + Önce bir şey kaydedin + Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. + Raf + Son + Boyut: %s + Temizlendi + Parola gir + Kotatsu başlatılırken parola sor + Güncellemeleri ara + Güncelleme akışını temizle + Akış güncellemesi yakında başlayacak + Sürüm %s + Güncellemeleri denetle + Merkeze sığdır + Genişliğe sığdır + AMOLED ekranlarda daha az güç kullanır + Yedekle ve geri yükle + Veri yedeği oluştur + Geri yüklendi + Hazırlanıyor… + Dün + Grup + Sessiz + Çöz + Çerezleri temizle + Öntanımlı: %s + Ters + Parola 4 veya daha fazla karakterden oluşmalıdır + Hoş geldiniz + Sıraya alındı + Bölüm eksik + Bu uygulamayı çevirin + Çeviri + Devam ediyor + Tüm kaynaklardaki oturumunuz kapatılacak + Kullanılan kaynaklar + Kullanılabilir kaynaklar + Uygunsuz mangayı geçmişten hariç tut + Numaralı sayfalar + Arama sonuçları + Parolayı tekrarla + Denetleme + Yanlış parola + Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz + Uzun zaman önce + Bugün + Güncelleme yok + Tüm favoriler + Okuduklarınızın yeni bölümleri burada gösterilir + Yeni sürüm: %s + Uygulamayı koru + Parolalar eşleşmiyor + Sağdan-sola + Yeni kategori + Dosya bulunamadı + Tüm veriler geri yüklendi + Veriler geri yüklendi, ancak hatalar var + Tekrar denemek için dokunun + İleri + CAPTCHA gerekli + Tüm çerezler kaldırıldı + Seçilen yapılandırma bu manga için hatırlanacak + Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? + Uygulamayı başlatmak için bir parola girin + Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? + Yedek kaydedildi + Türler + Öntanımlı + %s üzerinde oturum açma desteklenmiyor + Daha fazla oku + Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. + Ekran görüntüsü politikası + Uygunsuzlarda engelle + Her zaman engelle + İzin ver + Yeni bölümleri denetle + Öneriler + Önerileri etkinleştir + Tercihlerinize göre manga önerileri alın + Tüm veriler sadece bu cihaz üzerinde yerel olarak işlenir ve asla herhangi bir yere satılmaz. + Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız + Uygunsuz manga önerme + Etkin + Devre dışı + Türler listesi yüklenemiyor + Filtreyi sıfırla + Tür bul + Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. + Her zaman + Hiçbir zaman + Yalnızca Wi-Fi\'de + Sayfaları önceden yükle + %s olarak oturum açıldı + 18+ + Çeşitli diller + Bölüm bul + Bu mangada bölüm yok + %%%1$s + İçerik + Öneriler güncelleniyor + Görünüm + Türleri hariç tut + Önerilerde görmek istemediğiniz türleri belirtin + Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? + Kaldırma tamamlandı + Bölümler arka planda kaldırılacak. + İndirmeyi yavaşlat + IP adresinizin engellenmesinden kaçınmanıza yardımcı olur + Kaydedilen manga işleme + Gizle + Yeni manga kaynakları var + Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak + Bildirimleri etkinleştir + Yeni bölümleri denetle ve bildirim gönder + Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız + Favori kategori yok + Ad + Düzenle + Kategoriyi düzenle + Yer imi ekle + Yer imini kaldır + Yer imleri + Yer imi kaldırıldı + Yer imi eklendi + Geri al + Geçmişten kaldırıldı + HTTPS üzerinden DNS + Okuyucu modunu otomatik algıla + Manganın webtoon olup olmadığını otomatik olarak algıla + Öntanımlı mod + Pil iyileştirmesini devre dışı bırak + Arka planda güncelleme denetimlerine yardımcı olur + Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. + Gönder + Tümünü devre dışı bırak + Varsa parmak izi kullan + Favorilerinizden mangalar + Son okuduğunuz mangalar + Bildir + İzleme + Oturumu kapat + Okunuyor + Tamamlandı + Okuma ilerleme göstergelerini göster + Verileri sil + Geçmişte ve favorilerde okunma yüzdesini göster + Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir + Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır + Beklemede + Bırakıldı + Planlandı + Yeniden okunuyor + Tümünü göster + Geçersiz etki alanı + Aralık seç + İçerik bulunamadı veya kaldırıldı + Manganız burada görüntülenecek + İptal edilmiş + Hesap zaten var + Geri + Senkronizasyon + Verini yedekle + Devam etmek için E-Postanızı girin + Tüm gecmişi temizle + Son 2 saat + Geçmiş temizlendi + Yönet + Yer işareti yok + Manga okurken yer işareti oluşturabilirsiniz + Yer işaretleri kaldırıldı + Manga kaynağı yok + Çevrimiçi manga okumak için manga kaynaklarını aktif edin + Rastgele + Boş + Keşfet + Çıkmak için tekrar Geri tıkla + Çıkmak için iki defa Geri tıkla + Favorilerden kaldırıldı + Çıkış doğrulaması + Çizgi roman arşivi + Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. <a href=kotatsu://about> Kotatsunun son sürümünü kullandığnızdan emin olun.</a>/br> 3. Mevcutsa, geliştiricilere bir hata reporu gönderin. + «Keşfet» kısmında neler okuyacağınızı bulun + Seçilen favori kategorileri silmek istediğinizden emin misiniz\? \nİçindeki tüm mangalar kaybolur ve bu işlem geri alınamaz. - Yeniden sırala - Sayfa önbelleği - Diğer önbellekler - Depolama kullanımı - Mevcut - %s - %s - Seçenekler - Gizli mod - Bölüm yok - Otomatik kaydır - Böl. %1$d/%2$d Sayf. %3$d/%4$d - Okuyucuda bilgi çubuğu göster - Resimlerle klasör - Manga içe aktarılıyor - İçe aktarım tamamlandı - Yer açmak için orijinal dosyayı depolamadan silebilirsiniz - İçe aktarım birazdan başlayacak - Akış - En son manga kısayollarını göster - Ergonomik okuyucu kontrol - Renk düzeltme - Parlaklık - Kontrast - Sıfırla - Seçilen renk ayarları bu manga için hatırlanacaktır - Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? - Yoksay - Cihazda yer yok - Webtoon yakınlaştırma - Sayfa değiştirme kaydırıcısını göster - Ayrıca yeni bölümler hakkındaki bilgileri temizle - Sıkı - Farklı diller - Ağ kullanılamıyor - Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın - Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin - Kaydedilen mangalar - Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin - Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir - Kaynak devre dışı - İçerik ön yüklemesi - Geçerli olarak işaretle - Dil - Günlükleri paylaş - Günlük kaydını etkinleştir - Hata ayıklama amacıyla bazı eylemleri kaydedin - Şüpheli içeriği göster - Hizmetler - Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. - burada hiçbir şey yok - Dinamik - renk vurgusu - Izgara görünümünde göster - Mamimi - Kanade - UserAgent başlığı - Uygulamanın beta sürümleri için güncellemeler öner - Kararsız güncellemelere izin ver - İndirme başladı - Miku - Asuka - Mion - Rikka - Sakura - Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın - + Yeniden sırala + Sayfa önbelleği + Diğer önbellekler + Depolama kullanımı + Mevcut + %s - %s + Seçenekler + Gizli mod + Bölüm yok + Otomatik kaydır + Böl. %1$d/%2$d Sayf. %3$d/%4$d + Okuyucuda bilgi çubuğu göster + Resimlerle klasör + Manga içe aktarılıyor + İçe aktarım tamamlandı + Yer açmak için orijinal dosyayı depolamadan silebilirsiniz + İçe aktarım birazdan başlayacak + Akış + En son manga kısayollarını göster + Ergonomik okuyucu kontrol + Renk düzeltme + Parlaklık + Kontrast + Sıfırla + Seçilen renk ayarları bu manga için hatırlanacaktır + Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? + Yoksay + Cihazda yer yok + Webtoon yakınlaştırma + Sayfa değiştirme kaydırıcısını göster + Ayrıca yeni bölümler hakkındaki bilgileri temizle + Sıkı + Farklı diller + Ağ kullanılamıyor + Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın + Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin + Kaydedilen mangalar + Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin + Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir + Kaynak devre dışı + İçerik ön yüklemesi + Geçerli olarak işaretle + Dil + Günlükleri paylaş + Günlük kaydını etkinleştir + Hata ayıklama amacıyla bazı eylemleri kaydedin + Şüpheli içeriği göster + Hizmetler + Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. + burada hiçbir şey yok + Dinamik + renk vurgusu + Izgara görünümünde göster + Mamimi + Kanade + UserAgent başlığı + Uygulamanın beta sürümleri için güncellemeler öner + Kararsız güncellemelere izin ver + İndirme başladı + Miku + Asuka + Mion + Rikka + Sakura + Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın + Benzerini bul + Çeviriler + WebView kullanılamıyor: WebView sağlayıcısının kurulu olup olmadığını kontrol edin + Etkinleştir + Hayır teşekkürler + İnternet geçmişini temizle + Eşitleme seçenekleri + Sunucu adresi + "Şirket içinde barındırılan bir eşitleme sunucusu veya varsayılan bir sunucu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin." + Yansıtmalar varsa, hatalarda uzak kaynaklar için etki alanlarını otomatik olarak değiştir + Mobil ağa geçerken indirmeyi durdur + Bitirilenleri kaldır + Hepsini iptal et + Sadece Wi-Fi ile indir + Anladım + Yeniden sıralamak için bir öğeye dokunun ve basılı tutun + Bir veya daha fazla .cbz veya .zip dosyası seçebilirsiniz, her dosya ayrı bir manga olarak tanınacaktır. + Arşivler veya resimler içeren bir dizin seçebilirsiniz. Her arşiv (veya alt dizin) bir bölüm olarak tanınacaktır. + Hız + Kullanıcı verilerinin önceden oluşturulmuş bir yedeğini içe aktarın + Rafta Göster + Mevcut bir hesapta oturum açabilir veya yeni bir hesap oluşturabilirsiniz. + SSL hatalarını görmezden gel + Durdur + Devam et + Durduruldu + Öneri:%s + Bazen manga öneri bildirimlerilerini göster + Daha fazla + Tüm aktif indirmeler iptal edilecek, kısmen indirilen veriler kaybolacak + İndirme geçmişin tamamen silinecek + Hiçbir indirmeniz yok + İndirmeler devam ettirildi + İndirmeler durduruldu + İndirmeler silindi + Aynayı otomatik olarak seç + İndirmeler iptal edildi + Kişiselleştirilmiş manga önerileri almak istiyor musunuz\? + Adres + Tür + %1$s (%2$s) + Menü + Proxy + Geçersiz değer + \ No newline at end of file From 315870abcbeb0ae842ba986e38039546f5641686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D0=B0=D1=80=20=D0=A0=D0=B0=D0=B7=D0=B8?= =?UTF-8?q?=D0=BD?= Date: Sun, 4 Jun 2023 12:57:06 +0200 Subject: [PATCH 65/90] Translated using Weblate (Ukrainian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Russian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Polish) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (Russian) Currently translated at 100.0% (421 of 421 strings) Translated using Weblate (French) Currently translated at 100.0% (421 of 421 strings) Co-authored-by: Макар Разин Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/be/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pl/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ru/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/ Translation: Kotatsu/Strings --- app/src/main/res/values-be/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 5 + app/src/main/res/values-pl/strings.xml | 768 ++++++++++++++----------- app/src/main/res/values-ru/strings.xml | 7 + app/src/main/res/values-uk/strings.xml | 7 + 5 files changed, 439 insertions(+), 350 deletions(-) diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 8c17722f5..63229ce62 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -417,4 +417,6 @@ Порт Проксі Ачысціць сеткавы кэш + %1$s (%2$s) + Няправільнае значэнне \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 758eedf94..cd7193ee6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -412,4 +412,9 @@ Voulez-vous recevoir des suggestions de mangas personnalisées \? WebView non disponible : vérifier si le fournisseur WebView est installé Traductions + Effacer le cache réseau + Taper + Adresse + Port + Proxy \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c42b524c2..9dc982b98 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,352 +1,420 @@ - Ulubione - Historia - Napotkano błąd - Szczegółowy - Rozdziały - Lista - Lista szczegółowa - Siatka - Tryb listy - Ustawienia - Ładowanie… - Rozdział %1$d z %2$d - Zamknij - Wyczyść historię - Dodaj - Zapisz - Udostępnij - Szukaj - Szukaj mang - Pobieranie… - Pobrano - Pobrane - Nazwa - Popularność - Najnowsze - Ocena - Filtry - Jasny - Ciemny - Strony - Wyczyść - Usuń - Udostępnij zdjęcie - Usuń - Brak opisu - Tryb czytania - Błąd sieci - Obliczanie… - Spróbuj ponownie - Nic nie znaleziono - Brak historii - Czytaj - Brak ulubionych - Dodaj do ulubionych - Nowa kategoria - Stwórz skrót - Udostępnij %s - Przetwarzanie… - Zaktualizowane - Zapisz stronę - Zapisano - Wibracje - Biblioteka - Ostatnie - Tryb czarny - Przygotowywanie… - Plik nieznaleziony - Wczoraj - Dawno temu - Grupa - Dzisiaj - Zaloguj - Dalej - Potwierdź - Witaj - Skończone - W trakcie - Zezwól - Proponowane - Włącz propozycje - Włączone - Wyłączone - Nigdy - Zawsze - Znajdź rozdział - %1$s%% - Wygląd - Schowaj - Synchronizacja - Synchronizuj swoje dane - Nazwa - Edytuj - Wyloguj - Cofnij - Wyślij - Planowane - Czytane - Czytane ponownie - Skończone - Pokaż wszystkie - Wybierz zakres - Wyczyść całą historię - Ostatnie 2 godziny - Historia wyczyszczona - Zarządzaj - Losowe - Puste - Przeglądaj - Dostępne - Ustawienia - Źródło wyłączone - Kompaktowy - Błąd po stronie serwera (%1$d). Sprónuj ponownie później - Sieć niedostępna - Inne języki - Odrzuć - Jasność - Kontrast - Korekcja kolorów - Automatyczne przewijanie - Brak rozdziałów - Tryb incognito - Usunięto z ulubionych - Wykorzystana pamięć - Zapisane mangi - Brak zakładek - Możesz tworzyć zakładki w trakcie czytania mangi - Zakładki usunięte - Twoje ostatnio czytane mangi - Wyłącz wszystkie - Wyłącz optymalizację baterii - Autowykrywanie trybu czytania - Usunięte z historii - Dodano zakładkę - Usunięto zakładkę - Zakładki - Usuń zakładkę - Dodaj zakładkę - Brak ulubionych kategorii - Edytuj kategorię - Włącz powiadomienia - Wróć - Konto już istnieje - Anulowano - Zwolnienie pobierania - Brak rozdziałów w tej mandze - Różne języki - Tylko na Wi-Fi - Zawsze blokuj - Gatunki - Znajdź gatunek - Czytaj więcej - Rozwiąż - Wymagane CAPTCHA - Cichy - Dotknij aby spróbować ponownie - Teraz - Przywrócone - Dopasuj do szerokości - Dopasuj do wysokości - Dopasuj do środka - Nowa kategoria - Brak nowych aktualizacji - Sprawdź dostępność aktualizacji - Wersja %s - O aplikacji - Usuń - Jest tu dosyć pusto… - Ulubione kategorie - Powiadomienie LED - Nowe rozdziały - Pamięć wewnętrzna - Tutaj będą wyświetlane Twoje mangi - Znajdź materiały do czytania w zakładce „Przeglądaj” - W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz - Strony w pamięci podręcznej - Animacja przewracania strony - Inne rzeczy w pamięci podręcznej - Otwórz w przeglądarce - Numerowane strony - Powiadomienia - Dźwięk powiadomień - Ustawienia powiadomień - Zewnętrzne źródła - Motyw - Systemowy - Historia i pamięć podręczna - Wyczyść pamięć podręczną stron - B|kB|MB|GB|TB - Wielkość siatki - Szukaj na %s - Usuń mangę - Dalej - Błąd - Wyczyszczone - Pamięć wewnętrzna - Pamięć zewnętrzna - Domena - Nowa wersja aplikacji jest dostępna - Ta manga ma %s. Zapisać wszystko? - Zapisz - Pobierz - Najpierw coś zapisz - Niedostępne - Zapisz - Wszystkie ulubione - Pusta kategoria - Czytaj później - Aktualizacje - Nowa wersja: %s - Wielkość: %s - Obróć ekran - Odśwież - Szukaj aktualizacji - Nie sprawdzaj - Wprowadź hasło - Złe hasło - Chroń aplikację - Pytaj o hasło przy starcie Kotatsu - Wprowadź ponownie hasło - Zużywa mniej prądu na ekranach AMOLED - Kopia zapasowa i przywracanie - Utwórz kopię zapasową danych - Przywróć z kopii zapasowej - 18+ - %1$d na %2$d włączone - Standardowy - Webtoon - Ustawienia czytnika - Zmiana strony - Przyciski głośności - Dotknięcie krawędzi - Wyczyszczone - Tryb skalowania - Wyczyść ciasteczka - Wszystkie ciasteczka wyczyszczone - Przetłumacz tą aplikację - Tłumaczenie - Dostępne źródła - Tylko gesty - Brak dostępnej pamięci - Inny - Wyniki wyszukiwania - Wszystkie dane zostały przywrócone - Dane zostały przywrócone, ale z błędami - Od tyłu - Domyślny - Polityka zrzutów ekranu - Wyklucz gatunki - Określ gatunki, których nie chcesz widzieć w sugestiach - Zalogowano jako %s - Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. - Zgłoś - Usuwanie danych - Nieważna domena - Zmień kolejność - Potwierdzenie wyjścia - %s - %s - Rozdz. %1$d/%2$d Str. %3$d/%4$d - Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online - Importuj - Wybierz plik ZIP lub CBZ. - Wyczyść historię wyszukiwania - Ta operacja nie jest obsługiwana - Tryb sortowania - Treści - Nie można załadować listy gatunków - Wstrzymane - Porzucone - Użyj odcisku palca, jeśli jest dostępny - Mangi z Twoich ulubionych - Pokaż wskaźniki postępu czytania - Pokaż procent przeczytania w historii i ulubionych - Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane - DNS przez HTTPS - Tryb domyślny - Trwale wyczyścić całą historię czytania? - „%s” usunięte z pamięci lokalnej - Wyczyść tablicę aktualizacji - Tablica - Usunąć trwale „%s” z urządzenia? - Wyczyść pamięć podręczną miniatur - Spróbuj przeformułować zapytanie. - To co czytasz będzie wyświetlane tutaj - Znajdź to, co warto przeczytać, w menu bocznym. - Zapisz ze źródeł online lub zaimportuj pliki. - Folder pobranych - Aktualizacja tablicy rozpocznie się wkrótce - Niezgodne hasła - Od prawej do lewej - Trzymaj na starcie - Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją - Wybrana konfiguracja zostanie zapamiętana dla tej mangi - Wyczyść tablicę - Wyczyścić trwale całą historię aktualizacji? - Szukanie nowych rozdziałów - Zaloguj się, aby wyświetlić tę zawartość - Domyślnie: %s - Wprowadź hasło, aby uruchomić aplikację - Hasło musi mieć co najmniej 4 znaki - Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? - Zapisano kopię zapasową - Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. - W kolejce - Pobierz lub przeczytaj ten brakujący rozdział online. - Brak rozdziału - Uprawniony - Logowanie na %s nie jest obsługiwane - Zostaniesz wylogowany ze wszystkich źródeł - Wyklucz mangi NSFW z historii - Wykorzystane źródła - Zablokuj na NSFW - Proponuj mangi na podstawie Twoich preferencji - Wszystkie dane są analizowane lokalnie na tym urządzeniu. Twoje dane osobowe nie są przekazywane do żadnych usług - Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie - Nie proponuj mang NSFW - Zresetuj filtr - Ładuj wstępnie strony - Aktualizowanie sugestii - Trwale usunąć wybrane elementy z urządzenia? - Usuwanie zakończone - Pomaga uniknąć blokowania Twojego adresu IP - Przetwarzanie zapisanej mangi - Rozdziały zostaną usunięte w tle. Może to zająć trochę czasu - Wpisz swój adres e-mail, aby kontynuować - Dostępne są nowe źródła mang - Sprawdzaj dostępność nowych rozdziałów i informuj o nich - Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz - Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach - Śledzenie - Automatycznie wykryj, czy manga to webtoon - Pomaga w sprawdzaniu aktualizacji w tle - Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. - Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione - Brak źródeł mang - Włącz źródła mang do czytania mang online - Czy na pewno chcesz usunąć wybrane ulubione kategorie? Wszystkie w nich mangi zostaną usunięte i nie będzie można tego cofnąć. - Naciśnij ponownie Wstecz, aby wyjść - Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji - Treść nie została znaleziona lub została usunięta - Pokaż pasek informacji w czytniku - Archiwum komiksów - Folder z obrazami - Importowanie mangi - Importowanie zakończone - Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce - Import rozpocznie się wkrótce - Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi - Pokaż ostatnie skróty do mang - Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji - Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony - Ergonomiczne sterowanie czytnikiem - Zapisać czy odrzucić niezapisane zmiany? - Brak miejsca w urządzeniu - Pokaż suwak przełączania stron - Powiększanie webtoon - Wyczyść też informacje o nowych rozdziałach - Resetuj - Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a> aby upewnić się, że jest dostępna w źródle<br>2. Jeśli jest dostępna, wyślij raport o błędzie do programistów. - + Ulubione + Historia + Napotkano błąd + Szczegółowy + Rozdziały + Lista + Lista szczegółowa + Siatka + Tryb listy + Ustawienia + Ładowanie… + Rozdział %1$d z %2$d + Zamknij + Wyczyść historię + Dodaj + Zapisz + Udostępnij + Szukaj + Szukaj mang + Pobieranie… + Pobrano + Pobrane + Nazwa + Popularność + Najnowsze + Ocena + Filtry + Jasny + Ciemny + Strony + Wyczyść + Usuń + Udostępnij zdjęcie + Usuń + Brak opisu + Tryb czytania + Błąd sieci + Obliczanie… + Spróbuj ponownie + Nic nie znaleziono + Brak historii + Czytaj + Brak ulubionych + Dodaj do ulubionych + Nowa kategoria + Stwórz skrót… + Udostępnij %s + Przetwarzanie… + Zaktualizowane + Zapisz stronę + Zapisano + Wibracje + Biblioteka + Ostatnie + Tryb czarny + Przygotowywanie… + Plik nieznaleziony + Wczoraj + Dawno temu + Grupa + Dzisiaj + Zaloguj + Dalej + Potwierdź + Witaj + Skończone + W trakcie + Zezwól + Proponowane + Włącz propozycje + Włączone + Wyłączone + Nigdy + Zawsze + Znajdź rozdział + %1$s%% + Wygląd + Schowaj + Synchronizacja + Synchronizuj swoje dane + Nazwa + Edytuj + Wyloguj + Cofnij + Wyślij + Planowane + Czytane + Czytane ponownie + Skończone + Pokaż wszystkie + Wybierz zakres + Wyczyść całą historię + Ostatnie 2 godziny + Historia wyczyszczona + Zarządzaj + Losowe + Puste + Przeglądaj + Dostępne + Ustawienia + Źródło wyłączone + Kompaktowy + Błąd po stronie serwera (%1$d). Sprónuj ponownie później + Sieć niedostępna + Inne języki + Odrzuć + Jasność + Kontrast + Korekcja kolorów + Automatyczne przewijanie + Brak rozdziałów + Tryb incognito + Usunięto z ulubionych + Wykorzystana pamięć + Zapisane mangi + Brak zakładek + Możesz tworzyć zakładki w trakcie czytania mangi + Zakładki usunięte + Twoje ostatnio czytane mangi + Wyłącz wszystkie + Wyłącz optymalizację baterii + Autowykrywanie trybu czytania + Usunięte z historii + Dodano zakładkę + Usunięto zakładkę + Zakładki + Usuń zakładkę + Dodaj zakładkę + Brak ulubionych kategorii + Edytuj kategorię + Włącz powiadomienia + Wróć + Konto już istnieje + Anulowano + Zwolnienie pobierania + Brak rozdziałów w tej mandze + Różne języki + Tylko na Wi-Fi + Zawsze blokuj + Gatunki + Znajdź gatunek + Czytaj więcej + Rozwiąż + Wymagane CAPTCHA + Cichy + Dotknij aby spróbować ponownie + Teraz + Przywrócone + Dopasuj do szerokości + Dopasuj do wysokości + Dopasuj do środka + Nowa kategoria + Brak nowych aktualizacji + Sprawdź dostępność aktualizacji + Wersja %s + O aplikacji + Usuń + Jest tu dosyć pusto… + Ulubione kategorie + Powiadomienie LED + Nowe rozdziały + Pamięć wewnętrzna + Tutaj będą wyświetlane Twoje mangi + Znajdź materiały do czytania w zakładce „Przeglądaj” + W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz + Strony w pamięci podręcznej + Animacja przewracania strony + Inne rzeczy w pamięci podręcznej + Otwórz w przeglądarce + Numerowane strony + Powiadomienia + Dźwięk powiadomień + Ustawienia powiadomień + Zewnętrzne źródła + Motyw + Systemowy + Historia i pamięć podręczna + Wyczyść pamięć podręczną stron + B|kB|MB|GB|TB + Wielkość siatki + Szukaj na %s + Usuń mangę + Dalej + Błąd + Wyczyszczone + Pamięć wewnętrzna + Pamięć zewnętrzna + Domena + Nowa wersja aplikacji jest dostępna + Ta manga ma %s. Zapisać wszystko? + Zapisz + Pobierz + Najpierw coś zapisz + Niedostępne + Zapisz + Wszystkie ulubione + Pusta kategoria + Czytaj później + Aktualizacje + Nowa wersja: %s + Wielkość: %s + Obróć ekran + Odśwież + Szukaj aktualizacji + Nie sprawdzaj + Wprowadź hasło + Złe hasło + Chroń aplikację + Pytaj o hasło przy starcie Kotatsu + Wprowadź ponownie hasło + Zużywa mniej prądu na ekranach AMOLED + Kopia zapasowa i przywracanie + Utwórz kopię zapasową danych + Przywróć z kopii zapasowej + 18+ + %1$d na %2$d włączone + Standardowy + Webtoon + Ustawienia czytnika + Zmiana strony + Przyciski głośności + Dotknięcie krawędzi + Wyczyszczone + Tryb skalowania + Wyczyść ciasteczka + Wszystkie ciasteczka wyczyszczone + Przetłumacz tą aplikację + Tłumaczenie + Dostępne źródła + Tylko gesty + Brak dostępnej pamięci + Inny + Wyniki wyszukiwania + Wszystkie dane zostały przywrócone + Dane zostały przywrócone, ale z błędami + Od tyłu + Domyślny + Polityka zrzutów ekranu + Wyklucz gatunki + Określ gatunki, których nie chcesz widzieć w sugestiach + Zalogowano jako %s + Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. + Zgłoś + Usuwanie danych + Nieważna domena + Zmień kolejność + Potwierdzenie wyjścia + %s - %s + Rozdz. %1$d/%2$d Str. %3$d/%4$d + Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online + Importuj + Wybierz plik ZIP lub CBZ. + Wyczyść historię wyszukiwania + Ta operacja nie jest obsługiwana + Tryb sortowania + Treści + Nie można załadować listy gatunków + Wstrzymane + Porzucone + Użyj odcisku palca, jeśli jest dostępny + Mangi z Twoich ulubionych + Pokaż wskaźniki postępu czytania + Pokaż procent przeczytania w historii i ulubionych + Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane + DNS przez HTTPS + Tryb domyślny + Trwale wyczyścić całą historię czytania? + „%s” usunięte z pamięci lokalnej + Wyczyść tablicę aktualizacji + Tablica + Usunąć trwale „%s” z urządzenia? + Wyczyść pamięć podręczną miniatur + Spróbuj przeformułować zapytanie. + To co czytasz będzie wyświetlane tutaj + Znajdź to, co warto przeczytać, w menu bocznym. + Zapisz ze źródeł online lub zaimportuj pliki. + Folder pobranych + Aktualizacja tablicy rozpocznie się wkrótce + Niezgodne hasła + Od prawej do lewej + Trzymaj na starcie + Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją + Wybrana konfiguracja zostanie zapamiętana dla tej mangi + Wyczyść tablicę + Wyczyścić trwale całą historię aktualizacji? + Szukanie nowych rozdziałów + Zaloguj się, aby wyświetlić tę zawartość + Domyślnie: %s + Wprowadź hasło, aby uruchomić aplikację + Hasło musi mieć co najmniej 4 znaki + Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? + Zapisano kopię zapasową + Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. + W kolejce + Pobierz lub przeczytaj ten brakujący rozdział online. + Brak rozdziału + Uprawniony + Logowanie na %s nie jest obsługiwane + Zostaniesz wylogowany ze wszystkich źródeł + Wyklucz mangi NSFW z historii + Wykorzystane źródła + Zablokuj na NSFW + Proponuj mangi na podstawie Twoich preferencji + Wszystkie dane są analizowane tylko lokalnie na tym urządzeniu i nigdy nie są nigdzie wysyłane. + Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie + Nie proponuj mang NSFW + Zresetuj filtr + Ładuj wstępnie strony + Aktualizowanie sugestii + Trwale usunąć wybrane elementy z urządzenia? + Usuwanie zakończone + Pomaga uniknąć blokowania Twojego adresu IP + Przetwarzanie zapisanej mangi + Rozdziały zostaną usunięte w tle + Wpisz swój adres e-mail, aby kontynuować + Dostępne są nowe źródła mang + Sprawdzaj dostępność nowych rozdziałów i informuj o nich + Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz + Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach + Śledzenie + Automatycznie wykryj, czy manga to webtoon + Pomaga w sprawdzaniu aktualizacji w tle + Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. + Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione + Brak źródeł mang + Włącz źródła mang do czytania mang online + Czy na pewno chcesz usunąć wybrane ulubione kategorie\? +\nWszystkie w nich mangi zostaną usunięte i nie będzie można tego cofnąć. + Naciśnij ponownie Wstecz, aby wyjść + Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji + Treść nie została znaleziona lub została usunięta + Pokaż pasek informacji w czytniku + Archiwum komiksów + Folder z obrazami + Importowanie mangi + Importowanie zakończone + Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce + Import rozpocznie się wkrótce + Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi + Pokaż ostatnie skróty do mang + Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji + Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony + Ergonomiczne sterowanie czytnikiem + Zapisać czy odrzucić niezapisane zmiany? + Brak miejsca w urządzeniu + Pokaż suwak przełączania stron + Powiększanie webtoon + Wyczyść też informacje o nowych rozdziałach + Resetuj + Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a>, aby upewnić się, że jest dostępna w swoim źródle<br>2. Upewnij się, że używasz <a href=kotatsu://about>najnowszej wersji Kotatsu</a><br>3. Jeśli jest dostępny, wyślij raport o błędzie do programistów. + Mamimi + Kanade + Usługi + Tutaj nic nie ma + By śledzić postęp w czytaniu, wybierz Menu → Śledź na ekranie detali mangi. + Znajdź podobne + Nagłówek UserAgent + Tłumaczenia + Udostępnij dzienniki + Zapisz niektóre działania do celów debugowania + Zezwól na niestabilne altualizacje + Rozumiem + Uruchom ponownie aplikację by wprowadzić te zmiany + Prędkość + Stuknij i przytrzymaj element, aby zmienić jego kolejność + Możesz wybrać jeden lub więcej plików .cbz lub .zip, każdy plik zostanie rozpoznany jako osobna manga. + Możesz wybrać katalog z archiwami lub obrazami. Każde archiwum (lub podkatalog) zostanie rozpoznane jako rozdział. + Włączać + Wstępne ładowanie treści + Oznacz jako aktualne + Włącz logowanie + Pokaż podejrzane treści + Schemat kolorów + Pokaż w widoku siatki + Miku + Dynamiczne + Asuka + Rikka + Sakura + Mion + Ignoruj błędy SSL + Wybierz lustro automatycznie + Zaimportuj utworzoną wcześniej kopię zapasową danych użytkownika + Pokaż na półce + Automatycznie przełączaj domeny dla zdalnych źródeł w przypadku błędów, jeśli dostępne są kopie lustrzane + Pauza + Wznawiać + Wstrzymane + Anulować całość + Pobieraj tylko przez Wi-Fi + Zatrzymaj pobieranie po przełączeniu na sieć komórkową + Sugestia: %s + Czasami wyświetlaj powiadomienia z sugerowaną mangą + Więcej + Nie, dziękuję + Wszystkie aktywne pobrania zostaną anulowane, częściowo pobrane dane zostaną utracone + Usuwanie zakończone + Język + Zaproponuj aktualizacje do wersji beta aplikacji + Pobieranie rozpoczęte + Ustawienia synchronizacji + Adres serwera + Możesz użyć samoobsługowego serwera synchronizacji lub serwera domyślnego. Nie zmieniaj tego, jeśli nie jesteś pewien, co robisz. + Twoja historia pobrań zostanie trwale usunięta + Nie masz żadnych pobrań + Pobieranie zostało wstrzymane + Pobieranie zostało wznowione + Pobieranie zostało anulowane + Pliki do pobrania zostały usunięte + Czy chcesz otrzymywać spersonalizowane sugestie dotyczące mangi\? + WebView niedostępny: sprawdź, czy dostawca WebView jest zainstalowany + Wyczyść pamięć podręczną sieci + Typ + Adres + Port + Proxy + Możesz zalogować się na istniejące konto lub utworzyć nowe + \ 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 3ce28e5c0..ff3015e29 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -412,4 +412,11 @@ Хотите ли Вы получать персонализированные рекомендации манги\? Переводы WebView недоступен: проверьте, установлен ли провайдер WebView + Очистить сетевой кеш + Адрес + Тип + Прокси + Порт + %1$s (%2$s) + Неверное значение \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0304f772b..c9ab878da 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -412,4 +412,11 @@ Хочете отримувати персоналізовані пропозиції щодо манги\? WebView недоступний: перевірте, чи встановлено провайдер WebView Переклади + Очистити мережевий кеш + Порт + Проксі + Тип + Адреса + %1$s (%2$s) + Недійсне значення \ No newline at end of file From f44db3dbff0a24bf97fb3fc193f1f45eadaf50ae Mon Sep 17 00:00:00 2001 From: Reza Almanda Date: Sun, 4 Jun 2023 12:57:06 +0200 Subject: [PATCH 66/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (421 of 421 strings) Co-authored-by: Reza Almanda Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index bd3346c8a..7cda7bcce 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1,6 +1,6 @@ - Lokal + Penyimpanan lokal Favorit Riwayat Terjadi kesalahan @@ -160,7 +160,7 @@ Selalu blokir Saran Aktifkan saran - Sarankan komik berdasarkan preferensi Anda + Sarankan manga berdasarkan preferensi Anda Semua data hanya dianalisis secara lokal pada perangkat ini dan tidak pernah dikirim ke mana pun. Mulai membaca komik dan Anda akan mendapatkan saran yang dipersonalisasi Jangan menyarankan komik NSFW @@ -296,7 +296,7 @@ Folder dengan gambar Anda bisa menghapus berkas asli dari penyimpanan untuk menghemat ruang Umpan - Detail kesalahan:<br><tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka komik di browser</a> untuk memastikan komik tersedia di sumbernya<br>2. Pastikan Anda menggunakan <a href=kotatsu://about>Kotatsu versi terbaru</a><br>3. Jika tersedia, kirim laporan kesalahan ke pengembang. + Rincian error:<tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka manga di peramban web</a> untuk memastikan manga tersebut tersedia di sumbernya</a>2. Pastikan Anda menggunakan <a href= >manga versi terbaru</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Pastikan Anda menggunakan <a href=kotatsu://about>versi terbaru Kotatsu</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Kecerahan Kontras Atur Ulang @@ -375,12 +375,12 @@ Zoom webtoon Berbagai bahasa Jaringan tidak tersedia - Mengerti + Oke Ketuk dan tahan item untuk menyusun ulang Anda dapat memilih satu atau beberapa file .cbz atau .zip, setiap file akan dikenali sebagai komik terpisah. Anda dapat memilih direktori yang berisi arsip atau gambar. Setiap arsip (atau subdirektori) akan dikenali sebagai sebuah bab. Kecepatan - Impor cadangan data pengguna yang dibuat sebelumnya + Impor cadangan data pengguna yang telah dibuat sebelumnya Tampilkan di Rak Anda dapat masuk ke akun yang sudah ada atau membuat akun baru Temukan serupa @@ -401,7 +401,7 @@ Batalkan semua Berhenti mengunduh saat beralih ke jaringan seluler Saran: %s - Terkadang menampilkan notifikasi dengan komik yang disarankan + Terkadang menampilkan notifikasi dengan manga yang disarankan Lebih Semua pengunduhan yang aktif akan dibatalkan, data yang sudah terunduh sebagian akan hilang Riwayat unduhan Anda akan dihapus secara permanen @@ -410,4 +410,11 @@ Unduhan telah dijeda Unduhan telah dihapus Apakah Anda ingin menerima saran manga yang dipersonalisasi\? + Terjemahan + WebView tidak tersedia: periksa apakah penyedia WebView telah diinstal + Hapus cache jaringan + Tipe + Alamat + Port + Proksi \ No newline at end of file From 466e35fffa282ba1f93e44c3344017296f5235e6 Mon Sep 17 00:00:00 2001 From: Clxff H3r4ld0 <123844876+clxf12@users.noreply.github.com> Date: Sun, 4 Jun 2023 12:57:07 +0200 Subject: [PATCH 67/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (430 of 430 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (423 of 423 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (422 of 422 strings) Co-authored-by: Clxff H3r4ld0 <123844876+clxf12@users.noreply.github.com> Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 7cda7bcce..cd8f8db8a 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -148,7 +148,7 @@ Anda akan keluar dari semua sumber Genre Selesai - Berlanjut + Sedang berlangsung Standar Kecualikan komik NSFW dari riwayat Nomor halaman @@ -187,7 +187,7 @@ Hapus yang dipilih dari perangkat secara permanen\? Selesai menghapus Perlambat unduhan - Pembaruan saran + Memperbarui saran Membantu menghidari pemblokiran alamat IP Anda Bab akan dihapus di latar belakang Sembunyikan @@ -216,7 +216,7 @@ Kategori favorit Hapus Bersihkan umpan pembaruan - Kanan ke kiri + Kanan-ke-kiri Putar layar Pembaruan umpan akan dimulai Masukkan kata sandi @@ -248,8 +248,8 @@ Pas tinggi Pas lebar Balik - Antri - Diotorisasi + Mengantri + Resmi Simpan dari sumber daring atau berkas impor. Komik Anda akan ditampilkan di sini Cari apa untuk dibaca di bagian «Jelajah» @@ -354,7 +354,7 @@ Tampilkan indikator kemajuan membaca Tampilkan persentase baca dalam riwayat dan favorit Bahasa - Cobalah untuk merubah kueri. + Cobalah untuk memformulasi ulang kueri. Tetap di awal Bab. %1$d/%2$d Hal. %3$d/%4$d Aktifkan pencatatan @@ -417,4 +417,13 @@ Alamat Port Proksi + Nilai tidak valid + %1$s (%2$s) + Gunakan layanan wsrv.nl untuk mengurangi penggunaan lalu lintas dan mempercepat pemuatan gambar jika memungkinkan + Proksi pengoptimalan gambar + NamaUser + Diunduh + Balikkan warna + Kata sandi + Otorisasi (opsional) \ No newline at end of file From 759df969c9ac5f58c1f6831602c8fd1d7917a46e Mon Sep 17 00:00:00 2001 From: wr131 Date: Sun, 4 Jun 2023 12:57:07 +0200 Subject: [PATCH 68/90] Translated using Weblate (Chinese (Traditional)) Currently translated at 23.4% (99 of 422 strings) Translated using Weblate (Chinese (Simplified)) Currently translated at 99.2% (419 of 422 strings) Co-authored-by: wr131 Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/zh_Hant/ Translation: Kotatsu/Strings --- app/src/main/res/values-zh-rCN/strings.xml | 7 +- app/src/main/res/values-zh-rTW/strings.xml | 191 +++++++++++---------- 2 files changed, 108 insertions(+), 90 deletions(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5b20c9e2a..6ca5165d3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -407,9 +407,14 @@ 下载被取消 你想要接收个人漫画推荐吗? 推荐:%s - 偶尔对建议的漫画显示通知 + 偶尔显示建议漫画通知 更多 所有进行中的下载都将被取消,未下载完成的数据将丢失 你的下载历史将会永久删除 你可以登陆一个已有账号或创建新账号 + 地址 + 清除网络缓存 + 代理 + 类型 + 无效值 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 9d6ec4c85..830fe30b2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,91 +1,104 @@ - 你将不会收到通知,但新的章节将在列表中突出显示 - 计算… - 再试一次 - 尚无历史记录 - 不支持这种操作 - 在 \"探索 \"部分找到要读的内容 - 从在线来源保存或导入文件。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容。 - 你的漫画将显示在这里 - 这里有点空… - 饲料更新将很快开始 - 所选择的配置将因这部漫画而被记住 - 数据被恢复了,但有错误 - 在AMOLED屏幕上使用更少的电力 - 登录后可查看此内容 - 永久地删除所有最近的搜索查询? - 永久地清除所有的更新历史? - 你将从所有来源中注销 - 從歷史中排除NSFW漫畫 - 开始阅读漫画,你会得到个性化的建议 - 根据你的喜好推荐漫画 - 指定您不希望在建议中看到的体裁 - 从设备中永久删除选定的项目? - 无法加载流派列表 - 章节将在后台被删除。这可能需要一些时间 - 检查新的章节并通知有关情况 - 有助于避免阻断你的IP地址 - 输入你的电子邮件以继续 - 有了新的漫画来源 - 自动检测漫画是否为网络漫画 - 在历史和收藏夹中显示阅读百分比 - 再次按 \"返回 \"键退出 - 本地存储 - 轻敲右边缘或按右键总是切换到下一页 - 你有未保存的修改,你想保存还是丢弃它们? - 您可以從儲存中刪除原始檔案以節省空間 - 最爱 - 章节 - 列表 - 栅格 - 设置 - 没有发现 - 选择你想看的漫画的语言。你可以在以后的设置中改变它。 - 可以在出现一些问题时提供帮助。所有授权将被视为无效 - 历史 - 发生了一个错误 - 无法连接到互联网 - 详情 - 第%1$d 。%2$d - 详细列表 - 列表模式 - 远程资源 - 正在加载… - 关闭 - 清除历史 - 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 - 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 - 你可以创建你的历史和收藏的备份并恢复它 - 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 - 所选择的颜色设置将被铭记在这部漫画中 - 要么选择ZIP或CBZ文件。 - 你可以在阅读漫画时创建书签 - 你会收到你正在阅读的漫画的更新通知 - 一些设备有不同的系统行为,这可能会破坏后台任务。 - 输入密码以启动应用程序 - 下载或在线阅读这缺失的章节。 - 在启动Kotatsu时要求输入密码 - 这部漫画中没有章节 - 你正在阅读的新章节显示在这里 - 通过长按应用程序图标来提供最近的漫画 - 这部漫画有%s 。全部保存? - 新版本的应用程序已经推出 - 密码必须是4个字符或以上 - 不支持在%s 上登录 - \"%s\" 从本地存储中删除 - 按两次 \"返回 \"键,退出应用程序 - 启用漫画来源,在线阅读漫画 - 永久清除所有阅读历史? - 从设备中永久删除 \"%s\"? - 尝试重新表述查询。 - 帮助进行背景更新检查 - 请勿推荐NSFW漫画 - 新类别 - 阅读 - 暂时没有喜欢的人 - 最喜欢这个 - 添加 - + 你将不会收到通知,但新的章节将在列表中突出显示 + 计算… + 再试一次 + 尚无历史记录 + 不支持这种操作 + 在 \"探索 \"部分找到要读的内容 + 从在线来源保存或导入文件。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容。 + 你的漫画将显示在这里 + 这里有点空… + 饲料更新将很快开始 + 所选择的配置将因这部漫画而被记住 + 数据被恢复了,但有错误 + 在AMOLED屏幕上使用更少的电力 + 登录后可查看此内容 + 永久地删除所有最近的搜索查询? + 永久地清除所有的更新历史? + 你将从所有来源中注销 + 從歷史中排除NSFW漫畫 + 开始阅读漫画,你会得到个性化的建议 + 根据你的喜好推荐漫画 + 指定您不希望在建议中看到的体裁 + 从设备中永久删除选定的项目? + 无法加载流派列表 + 章节将在后台被删除。这可能需要一些时间 + 检查新的章节并通知有关情况 + 有助于避免阻断你的IP地址 + 输入你的电子邮件以继续 + 有了新的漫画来源 + 自动检测漫画是否为网络漫画 + 在历史和收藏夹中显示阅读百分比 + 再次按 \"返回 \"键退出 + 本地存储 + 轻敲右边缘或按右键总是切换到下一页 + 你有未保存的修改,你想保存还是丢弃它们? + 您可以從儲存中刪除原始檔案以節省空間 + 最爱 + 章节 + 列表 + 栅格 + 设置 + 没有发现 + 选择你想看的漫画的语言。你可以在以后的设置中改变它。 + 可以在出现一些问题时提供帮助。所有授权将被视为无效 + 历史 + 发生了一个错误 + 无法连接到互联网 + 详情 + 第%1$d 。%2$d + 详细列表 + 列表模式 + 远程资源 + 正在加载… + 关闭 + 清除历史 + 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 + 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 + 你可以创建你的历史和收藏的备份并恢复它 + 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 + 所选择的颜色设置将被铭记在这部漫画中 + 要么选择ZIP或CBZ文件。 + 你可以在阅读漫画时创建书签 + 你会收到你正在阅读的漫画的更新通知 + 一些设备有不同的系统行为,这可能会破坏后台任务。 + 输入密码以启动应用程序 + 下载或在线阅读这缺失的章节。 + 在启动Kotatsu时要求输入密码 + 这部漫画中没有章节 + 你正在阅读的新章节显示在这里 + 通过长按应用程序图标来提供最近的漫画 + 这部漫画有%s 。全部保存? + 新版本的应用程序已经推出 + 密码必须是4个字符或以上 + 不支持在%s 上登录 + \"%s\" 从本地存储中删除 + 按两次 \"返回 \"键,退出应用程序 + 启用漫画来源,在线阅读漫画 + 永久清除所有阅读历史? + 从设备中永久删除 \"%s\"? + 尝试重新表述查询。 + 帮助进行背景更新检查 + 请勿推荐NSFW漫画 + 新类别 + 阅读 + 暂时没有喜欢的人 + 最喜欢这个 + 添加 + 存儲 + 分享 %s + 搜尋 + 下載中…… + 已下載 + 過濾器 + 主題 + 淺色 + 清除 + 刪除 + 分享圖片 + 刪除 + 清除頁面快取 + \ No newline at end of file From 73217b8e11b6968145298ddf0b6905ee1d70b8c5 Mon Sep 17 00:00:00 2001 From: FateXBlood Date: Sun, 4 Jun 2023 12:57:08 +0200 Subject: [PATCH 69/90] Translated using Weblate (Nepali) Currently translated at 34.1% (144 of 422 strings) Co-authored-by: FateXBlood Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/ne/ Translation: Kotatsu/Strings --- app/src/main/res/values-ne/strings.xml | 193 ++++++++++++++++++------- 1 file changed, 141 insertions(+), 52 deletions(-) diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 9d72ad6df..446981da9 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1,53 +1,142 @@ - - डाउनलोड गर्दै… - डाउनलोड गरेको - फिल्टर - अँध्यारो - खाली गर्नुहोस् - पृष्ठहरू - एउटा त्रुटि भयो - सूची मोड - सूची - पुनः प्रयास गर्नुहोस् - केही पनि फेला परेन - पढ्नुहोस् - लोकल भण्डारण - इतिहास - नेटवर्क त्रुटि - अध्यायहरू - सेटिङहरू - रिमोट स्रोतहरू - लोड हुँदै… - इतिहास खाली गर्नुहोस् - अहिले कुनै मनपर्ने छैन - मनपर्ने मा राख्नुहोस् - नयाँ वर्ग - %s साझा गर्नुहोस् - खोज्नुहोस् - माङ्गा खोज्नुहोस् - प्रक्रिया गर्दैछ… - डाउनलोडहरू - नाम - अपडेट गरियो - नवीनतम - क्रमबद्ध क्रम - थीम - उज्यालो - सिस्टम पालना गर्नुहोस् - कम्प्युटिङ… - मनपर्नेहरू - विवरणहरू - विस्तृत सूची - ग्रिड - %2$d को अध्याय %1$d - बन्द गर्नुहोस् - अहिलेसम्म इतिहास छैन - थप्नुहोस् - बचत गर्नुहोस् - साझा गर्नुहोस् - सर्टकट सिर्जना गर्नुहोस्… - लोकप्रिय - मूल्याङ्कन - नयाँ अध्यायहरू - + + डाउनलोड गर्दै… + डाउनलोड गरेको + फिल्टर + अँध्यारो + खाली गर्नुहोस् + पृष्ठहरू + एउटा त्रुटि भयो + सूची मोड + सूची + पुनः प्रयास गर्नुहोस् + केही पनि फेला परेन + पढ्नुहोस् + लोकल भण्डारण + इतिहास + नेटवर्क त्रुटि + अध्यायहरू + सेटिङहरू + माङ्गा स्रोतहरू + लोड हुँदै… + इतिहास खाली गर्नुहोस् + अहिले कुनै मनपर्ने छैन + मनपर्ने मा राख्नुहोस् + नयाँ वर्ग + %s साझा गर्नुहोस् + खोज्नुहोस् + माङ्गा खोज्नुहोस् + प्रक्रिया गर्दैछ… + डाउनलोडहरू + नाम + अपडेट गरिएको + नवीनतम + क्रमबद्ध क्रम + थीम + उज्यालो + सिस्टम पालना गर्नुहोस् + कम्प्युटिङ… + मनपर्नेहरू + विवरणहरू + विस्तृत सूची + ग्रिड + %2$d को अध्याय %1$d + बन्द गर्नुहोस् + अहिलेसम्म इतिहास छैन + थप्नुहोस् + बचत गर्नुहोस् + साझा गर्नुहोस् + सर्टकट सिर्जना गर्नुहोस्… + लोकप्रिय + मूल्याङ्कन + नयाँ अध्यायहरू + सबै पढेको इतिहास स्थायी रूपमा खाली गर्ने हो\? + हटाउनुहोस् + लोकल भण्डारणबाट %s हटाइयो + सेभ गरियो + पृष्ठ सेभ गर्नुहोस् + छवि साझा गर्नुहोस् + आयात गर्नुहोस् + स्ट्यानडर्ड + वेबटून + पढ्ने मोड + ग्रिड साइज + यन्त्रबाट %s स्थायी रूपमा हटाउने हो\? + रिडर सेटिङहरू + %s मा खोज्नुहोस् + माङ्गा हटाउनुहोस् + पृष्ठ स्विच गर्नुहोस् + किनारा ट्यापहरू + भोल्युम बटन + जारी राख्नुहोस् + त्रुटि + खाली गरियो + जेस्चर मात्र + थम्बनेल क्यास खाली गर्नुहोस् + खोज इतिहास खाली गर्नुहोस् + डोमेन + यो माङ्गामा %s छ। यो सबै सेभ गर्ने\? + आन्तरिक भण्डारण + एपको नयाँ संस्करण उपलब्ध छ + बाह्य भण्डारण + वेब ब्राउजरमा खोल्नुहोस् + डाउनलोड + सूचना सेटिङ + LED सूचक + भाईब्रेशन + मनपर्ने वर्गहरू + हटाउनुहोस् + यहाँ अलि खाली जस्तो छ… + सोधपुछ सुधार गर्ने प्रयास गर्नुहोस्। + तपाईँले पढेको कुरा यहाँ देखाइनेछ + साइड मेनुमा के पढ्ने फेला पार्नुहोस्। + पृष्ठ एनिमेसन + डाउनलोडका लागि फोल्डर + हालैका + उपलब्ध छैन + तपाईंले पढिरहनु भएको माङ्गाको नयाँ अध्यायहरू यहाँ देखाइएको छ + खोज परिणामहरू + अपडेट फिड खाली गर्नुहोस् + स्क्रिन घुमाउनुहोस् + अपडेट + पासवर्डहरू म्याच गरेनन् + बारेमा + संस्करण %s + यो अपरेशन समर्थित छैन + कुनै विवरण छैन + इतिहास र क्यास + पृष्ठ क्यास खाली गर्नुहोस् + सूचना आवाज + पहिले केही सेभ गर्नुहोस् + यसलाई अनलाइन स्रोतहरूबाट सेभ गर्नुहोस् वा फाइलहरू आयात गर्नुहोस्। + खाली गरियो + एप सुरक्षित गर्नुहोस् + Kotatsu सुरु गर्दा पासवर्ड माग्नुहोस् + पासवर्ड दोहोर्याउनुहोस् + हटाउनुहोस् + या त ZIP वा CBZ फाइल छान्नुहोस्। + B|kB|MB|GB|TB + सेभ + सूचनाहरू + %2$d को %1$d अन + तपाईंको माङ्गा यहाँ देखाउनेछ + «अन्वेषण» भागमा के पढ्ने फेला पार्नुहोस् + दराज + भण्डारण उपलब्ध छैन + अन्य भण्डारण + सकियो + सबै मनपर्नेहरू + खाली वर्ग + पछि पढ्ने + अपडेटहरू + नयाँ संस्करण: %s + साइज: %s + फिड अपडेट चाँडै सुरु हुनेछ + अपडेटहरू खोज्नुहोस् + जाँच नगर्नुहोस् + गलत पासवर्ड + अपडेटका लागि जाँच गर्नुहोस् + कुनै अपडेट उपलब्ध छैन + अन्वेषण + पासवर्ड एन्टर गर्नुहोस् + \ No newline at end of file From 2f1b74e45a876b5cf54eba250c06bff6193ca0fb Mon Sep 17 00:00:00 2001 From: frablock Date: Sun, 4 Jun 2023 12:57:08 +0200 Subject: [PATCH 70/90] Translated using Weblate (French) Currently translated at 100.0% (7 of 7 strings) Translated using Weblate (French) Currently translated at 100.0% (430 of 430 strings) Co-authored-by: frablock Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/fr/ Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/ Translation: Kotatsu/Strings Translation: Kotatsu/plurals --- app/src/main/res/values-fr/plurals.xml | 65 ++++++++++++++------------ app/src/main/res/values-fr/strings.xml | 9 ++++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/app/src/main/res/values-fr/plurals.xml b/app/src/main/res/values-fr/plurals.xml index 31a0ce3e8..c0da2ac13 100644 --- a/app/src/main/res/values-fr/plurals.xml +++ b/app/src/main/res/values-fr/plurals.xml @@ -1,31 +1,38 @@ - - Il y a %1$d minute - Il y a %1$d minutes - - - %1$d page au total - %1$d pages au total - - - %1$d élément - %1$d éléments - - - %1$d nouveau chapitre - %1$d nouveaux chapitres - - - %1$d chapitre - %1$d chapitres - - - Il y a %1$d heure - Il y a %1$d heures - - - Il y a %1$d jour - Il y a %1$d jours - - + + Il y a %1$d minute + Il y a %1$d minutes + Il y a %1$d minutes + + + %1$d page au total + %1$d pages au total + %1$d pages au total + + + %1$d élément + %1$d éléments + %1$d éléments + + + %1$d nouveau chapitre + %1$d nouveaux chapitres + %1$d nouveaux chapitres + + + %1$d chapitre + %1$d chapitres + %1$d chapitres + + + Il y a %1$d heure + Il y a %1$d heures + Il y a %1$d heures + + + Il y a %1$d jour + Il y a %1$d jours + Il y a %1$d jours + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index cd7193ee6..04f0ee800 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -417,4 +417,13 @@ Adresse Port Proxy + Téléchargé + Pseudonyme + Proxy d\'optimisation des images + Inverser les couleurs + Utilisez le service wsrv.nl pour réduire le trafic et augmenter la vitesse de chargement des images si possible + %1$s (%2$s) + Mot de passe + Valeur invalide + Autorisation (optionnel) \ No newline at end of file From bd8b2519345c1f3a22654e4094fea6851aaca61e Mon Sep 17 00:00:00 2001 From: GpixeL Date: Sun, 4 Jun 2023 12:57:08 +0200 Subject: [PATCH 71/90] Translated using Weblate (Indonesian) Currently translated at 100.0% (430 of 430 strings) Co-authored-by: GpixeL Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/id/ Translation: Kotatsu/Strings --- app/src/main/res/values-in/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index cd8f8db8a..de4eb06bd 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -131,7 +131,7 @@ Selesaikan Bersihkan kuki Semua kuki telah dihapus - Bersihkan umpan + Bersihkan aliran Periksa bab baru Masuk untuk melihat konten ini Selanjutnya @@ -215,10 +215,10 @@ Getaran Kategori favorit Hapus - Bersihkan umpan pembaruan + Bersihkan aliran pembaruan Kanan-ke-kiri Putar layar - Pembaruan umpan akan dimulai + Pembaruan aliran akan dimulai Masukkan kata sandi Tanya kata sandi ketika memulai Kotatsu Tentang From 8d15691e17dc0e31c68122ea1c58013450d9cc0e Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 5 Jun 2023 13:04:26 +0300 Subject: [PATCH 72/90] Remove unused resources --- .weblate | 3 + app/src/main/res/drawable/ic_list_create.xml | 12 - .../res/layout/layout_synchronization.xml | 59 -- app/src/main/res/menu/opt_categories_bs.xml | 12 - app/src/main/res/values-ar/plurals.xml | 42 +- app/src/main/res/values-ar/strings.xml | 151 ++-- app/src/main/res/values-be/plurals.xml | 5 - app/src/main/res/values-be/strings.xml | 834 +++++++++-------- app/src/main/res/values-bn/plurals.xml | 22 +- app/src/main/res/values-de/plurals.xml | 54 +- app/src/main/res/values-de/strings.xml | 820 +++++++++-------- app/src/main/res/values-el/plurals.xml | 4 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-es/plurals.xml | 67 +- app/src/main/res/values-es/strings.xml | 848 +++++++++--------- app/src/main/res/values-fi/strings.xml | 4 - app/src/main/res/values-fil/plurals.xml | 4 - app/src/main/res/values-fil/strings.xml | 820 +++++++++-------- app/src/main/res/values-fr/plurals.xml | 67 +- app/src/main/res/values-fr/strings.xml | 848 +++++++++--------- app/src/main/res/values-hi/plurals.xml | 4 - app/src/main/res/values-in/plurals.xml | 3 - app/src/main/res/values-in/strings.xml | 848 +++++++++--------- app/src/main/res/values-it/plurals.xml | 4 - app/src/main/res/values-it/strings.xml | 4 - app/src/main/res/values-ja/plurals.xml | 3 - app/src/main/res/values-ja/strings.xml | 848 +++++++++--------- app/src/main/res/values-kk/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 4 - app/src/main/res/values-nb-rNO/plurals.xml | 4 - app/src/main/res/values-nb-rNO/strings.xml | 4 - app/src/main/res/values-ne/plurals.xml | 4 - app/src/main/res/values-ne/strings.xml | 279 +++--- app/src/main/res/values-nn/plurals.xml | 4 - app/src/main/res/values-nn/strings.xml | 714 ++++++++------- app/src/main/res/values-or/plurals.xml | 46 +- app/src/main/res/values-or/strings.xml | 53 +- app/src/main/res/values-pl/plurals.xml | 5 - app/src/main/res/values-pl/strings.xml | 830 +++++++++-------- app/src/main/res/values-pt-rBR/plurals.xml | 4 - app/src/main/res/values-pt-rBR/strings.xml | 4 - app/src/main/res/values-pt/strings.xml | 4 - app/src/main/res/values-ru/plurals.xml | 5 - app/src/main/res/values-ru/strings.xml | 834 +++++++++-------- app/src/main/res/values-sr/plurals.xml | 5 - app/src/main/res/values-sv/plurals.xml | 4 - app/src/main/res/values-sv/strings.xml | 4 - app/src/main/res/values-tr/plurals.xml | 4 - app/src/main/res/values-tr/strings.xml | 834 +++++++++-------- app/src/main/res/values-uk/plurals.xml | 6 - app/src/main/res/values-uk/strings.xml | 834 +++++++++-------- app/src/main/res/values-vi/plurals.xml | 3 - app/src/main/res/values-zh-rCN/plurals.xml | 3 - app/src/main/res/values-zh-rCN/strings.xml | 830 +++++++++-------- app/src/main/res/values-zh-rTW/strings.xml | 203 +++-- app/src/main/res/values/plurals.xml | 4 - app/src/main/res/values/strings.xml | 4 - app/src/main/res/values/styles.xml | 4 - app/src/main/res/values/themes.xml | 8 - 59 files changed, 5823 insertions(+), 6117 deletions(-) create mode 100644 .weblate delete mode 100644 app/src/main/res/drawable/ic_list_create.xml delete mode 100644 app/src/main/res/layout/layout_synchronization.xml delete mode 100644 app/src/main/res/menu/opt_categories_bs.xml diff --git a/.weblate b/.weblate new file mode 100644 index 000000000..4a120e1a3 --- /dev/null +++ b/.weblate @@ -0,0 +1,3 @@ +[weblate] +url = https://hosted.weblate.org/api/ +translation = kotatsu/strings diff --git a/app/src/main/res/drawable/ic_list_create.xml b/app/src/main/res/drawable/ic_list_create.xml deleted file mode 100644 index dce66429c..000000000 --- a/app/src/main/res/drawable/ic_list_create.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/layout_synchronization.xml b/app/src/main/res/layout/layout_synchronization.xml deleted file mode 100644 index d9d728fbe..000000000 --- a/app/src/main/res/layout/layout_synchronization.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/menu/opt_categories_bs.xml b/app/src/main/res/menu/opt_categories_bs.xml deleted file mode 100644 index 2e5f4ad73..000000000 --- a/app/src/main/res/menu/opt_categories_bs.xml +++ /dev/null @@ -1,12 +0,0 @@ - -

- - - - diff --git a/app/src/main/res/values-ar/plurals.xml b/app/src/main/res/values-ar/plurals.xml index 46a1c60eb..0145329ea 100644 --- a/app/src/main/res/values-ar/plurals.xml +++ b/app/src/main/res/values-ar/plurals.xml @@ -1,27 +1,19 @@ - - %1$d فصل جديد - - - - %1$d فصول جديدة - - - - - %1$d فصل - %1$d فصلين - %1$d بعض فصول - %1$d عدة فصول - - - - - مجموع %1$d فصل - مجموع %1$d فصلين - مجموع %1$d بعض فصول - مجموع %1$d عدة فصول - مجموع %1$d فصول اخرى - - \ No newline at end of file + + %1$d فصل جديد + + + + %1$d فصول جديدة + + + + + %1$d فصل + %1$d فصلين + %1$d بعض فصول + %1$d عدة فصول + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 63bfe975b..829137c78 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1,78 +1,77 @@ - تفاصيل القائمة - حدث خطأ - تفاصيل - شبكة - وضع القائمة - إعدادات - المصادر البعيدة - فصول - المفضلة - ‌خطاء في الشبكة - جار التحميل… - فصل %1$d في %2$d - غلق - حاول مجدداً - جاري الحوسبة … - التخزين المحلي - سجل - قائمة - محو سجل - ضع هذا في المفضلة - أضف - حفظ - لا سجل بعد - التحميلات - اسم - الأحدث - تقييم - صفحات - اقرأ - شارك - لم يتم عثور على اي شيء - لا مفضلة بعد - بحث - البحث في المانجا - جاري التنزيل… - انشاء اختصار… - مظهر - حسب النظام - شارك %s - في طور معالجة… - محدث - فلتر - ترتيب الفرز - ضوء - داكن - أزل - ازالة - شائع - قائمة جديدة - تم التنزيل - هل تريد محو سجل القراءة بالكامل بشكل دائم؟ - احفظ الصفحة - حفظت - اساسي - لا يوجد وصف - التاريخ وذاكرة التخزين المؤقت - مسح ذاكرة التخزين المؤقت للصفحة - ويبتون - وضع القراءة - بحث على %s - حذف المانغا - حذف \"%s\" من الجهاز نهائيا؟ - إعدادات القراءة - تغییر صفحات - حذف - شارك الصورة - إما أن تختار ملف ZIP أو CBZ. - استورد - هذا خيار غير مدعم - حجم الشبكة - أزرار الصوت - النقر على حواف الشاشة - يكمل - خطاء - مسح تاريخ البحث - \ No newline at end of file + تفاصيل القائمة + حدث خطأ + تفاصيل + شبكة + وضع القائمة + إعدادات + المصادر البعيدة + فصول + المفضلة + ‌خطاء في الشبكة + جار التحميل… + فصل %1$d في %2$d + غلق + حاول مجدداً + جاري الحوسبة … + التخزين المحلي + سجل + قائمة + محو سجل + ضع هذا في المفضلة + أضف + حفظ + لا سجل بعد + التحميلات + اسم + الأحدث + تقييم + صفحات + اقرأ + شارك + لم يتم عثور على اي شيء + لا مفضلة بعد + بحث + البحث في المانجا + جاري التنزيل… + انشاء اختصار… + مظهر + حسب النظام + شارك %s + في طور معالجة… + محدث + فلتر + ترتيب الفرز + ضوء + داكن + أزل + ازالة + شائع + قائمة جديدة + تم التنزيل + هل تريد محو سجل القراءة بالكامل بشكل دائم؟ + احفظ الصفحة + حفظت + اساسي + لا يوجد وصف + مسح ذاكرة التخزين المؤقت للصفحة + ويبتون + وضع القراءة + بحث على %s + حذف المانغا + حذف \"%s\" من الجهاز نهائيا؟ + إعدادات القراءة + تغییر صفحات + حذف + شارك الصورة + إما أن تختار ملف ZIP أو CBZ. + استورد + هذا خيار غير مدعم + حجم الشبكة + أزرار الصوت + النقر على حواف الشاشة + يكمل + خطاء + مسح تاريخ البحث + diff --git a/app/src/main/res/values-be/plurals.xml b/app/src/main/res/values-be/plurals.xml index 79edd9584..e27eb524b 100644 --- a/app/src/main/res/values-be/plurals.xml +++ b/app/src/main/res/values-be/plurals.xml @@ -1,10 +1,5 @@ - - Усяго %1$d старонка - Усяго %1$d старонкі - Усяго %1$d старонак - %1$d элемент %1$d элементы diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 63229ce62..c6f21aae2 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -1,422 +1,418 @@ - На прыладзе - Абраныя - Гісторыя - Адбылася памылка - Памылка сеткі - Падрабязнасцi - Раздзелы - Спіс - Падрабязны спіс - Табліца - Выгляд спісу - Налады - Крыніцы мангі - Загрузка… - Глава %1$d з %2$d - Закрыць - Паўтарыць - Ачысціць гісторыю - Нічога не знойдзена - Гісторыя пустая - Чытаць - Дадайце цікавую для вас мангу ў абранае, каб не страціць яе - Дадаць у абраныя - Стварыць катэгорыю - Дадаць - Захаваць - Падзяліцца - Стварыць ярлык… - Падзялiцца %s - Пошук - Пошук мангі - Спампоўванне мангі… - Апрацоўка… - Спампоўванне завершана - Спампоўкі - Па імю - Папулярная - Абноўленая - Новая - Па рэйтынгу - Сартаванне - Фільтр - Тэма - Светлая - Цёмная - Як у сістэме - Старонкi - Ачысціць - Вы ўпэўненыя, што жадаеце ачысціць гісторыю\? - Выдаліць - «%s» выдалена з прылады - Захаваць старонку - Старонка захавана - Падзяліцца выявай - Імпарт - Выдаліць - Аперацыя не падтрымліваецца - Файл не падтрымліваецца. Падтрымліваюцца толькі ZIP і CBZ. - Няма апісання - Гісторыя і кэш - Ачысціць кэш старонак - Б|кБ|МБ|ГБ|ТБ - Стандартны - Манхва - Рэжым чытання - Памер табліцы - Пошук па %s - Выдаліць мангу - Налады чытання - Гартанне старонак - Вы ўпэўненыя, што жадаеце выдаліць «%s» з прылады\? - Націск па краях - Кнопкі гучнасці - Працягнцуць - Памылка - Ачысціць кэш мініяцюр - Гісторыя пошуку ачышчана - Ачысціць гісторыю пошуку - Толькі жэсты - Унутранае сховішча - Знешняе сховішча - Дамен - Даступна абнаўленне праграмы - Адкрыць у браўзеры - У гэтай манге %s. Вы ўпэўненыя, што хочаце захаваць іх усё\? - Захаваць мангу - Паведамленні - Уключана %1$d з %2$d - Новыя раздзелы - Спампаваць - Налады апавяшчэнняў - Гук апавяшчэння - Светлавая iндыкацыя - Вібрацыя - Катэгорыі абранага - Выдаліць катэгорыю - Паліца з мангай - Нядаўняя манга - Анімацыя гартання - Месца спампоўвання мангі - Недаступна - Не атрымалася знайсці ніводнага даступнага сховішча - Іншае сховішча - Гатова - Усе абраныя - У гэтай катэгорыі нічога няма - Прачытаць пазней - Абнаўленні - Тут будуць паказвацца абнаўлення мангі, якую вы чытаеце - Вынікі пошуку - Новая версія: %s - Памер: %s - Ачысціць стужку абнаўленняў - Стужка абнаўленняў ачышчана - Павярнуць экран - Абнавіць - Абнаўленне хутка пачнецца - Правяраць абнаўленні мангі - Не правяраць - Увядзіце пароль - Няверны пароль - Абараніць праграму - Запытваць пароль пры запуску праграмы - Паўтарыце пароль - Паролі не супадаюць - Аб праграме - Версія %s - Праверыць абнаўленні - Няма даступных абнаўленняў - Справа налева - Стварыць катэгорыю - Маштабаванне - Умясціць у экран - Падагнаць па вышыні - Падагнаць па шырыні - Зыходны памер - Чорная - Спажывае менш энергіі на экранах AMOLED - Рэзервовае капіяванне і аднаўленне - Стварыць рэзервовую копію - Аднавіць данныя - Данныя адноўлены - Падрыхтоўка… - Файл не знойдзены - Усе данныя паспяхова адноўлены - Данныя адноўлены, але ўзніклі некаторыя памылкі - Вы можаце стварыць рэзервовую копію абранага і гісторыі і потым аднавіць іх - Толькі што - Учора - Даўно - Групаваць - Сёння - Паспрабаваць яшчэ раз - Абраны рэжым будзе захаваны для бягучай мангі - Без гуку - Неабходна прайсці CAPTCHA - Прайсці - Ачысціць кукi - Усе кукi выдалены - Ачысціць стужку - Уся гісторыя абнаўленняў будзе ачышчана і яе нельга будзе вярнуць. Вы ўпэўненыя\? - Праверка новых глаў - У адваротным парадку - Увайсці - Для прагляду гэтага кантэнту патрабуецца аўтарызацыя - Прадвызначаны: %s - Далей - Калі ласка, увядзіце пароль, які спатрэбіцца пры запуску праграмы - Пацвердзіць - Пароль павінен змяшчаць не менш за 4 сімвалы - Вы сапраўды хочаце выдаліць усе апошнія пошукавыя запыты\? - Падрабязна - Некаторыя вытворцы могуць змяняць паводзіны сістэмы, што можа парушаць выкананне фонавых задач. - Рэзервовая копія паспяхова захавана - Вітаю - Вы можаце захаваць мангу з анлайн-крыніц або імпартаваць з файла. - У вас яшчэ няма ніводнай захаванай мангі - Вы можаце знайсці, што пачытаць, у бакавым меню. - Тут будзе паказана манга, якую вы чытаеце - Паспрабуйце перафармуляваць запыт. - Тут неяк пуста… - Глава адсутнічае - Гэтая глава адсутнічае на вашай прыладзе. Спампуйце ціпрачытайце яе онлайн. - У чарзе - Дапамагчы з перакладам праграмы - Пераклад - Вы выйдзеце з усіх крыніц, у якіх вы аўтарызаваны - Аўтарызацыя на %s не падтрымліваецца - Аўтарызацыя выканана - Жанры - Завершана - Ангоінг - Па змаўчанні - Не паказваць NSFW мангу з гісторыі - Паказваць нумары старонак - Уключаныя крыніцы - Даступныя крыніцы - Вылічэнні… - Дазваляць - Палітыка скрыншотаў - Заўсёды блакуйце - Блок на NSFW - Немагчыма загрузіць спіс жанраў - Непрацаздольны - Уключаны - Не прапануйце мангу NSFW - Пачніце чытаць мангу, і вы атрымаеце персаналізаваныя прапановы - Усе даныя аналізуюцца толькі лакальна на гэтай прыладзе і нікуды не адпраўляюцца. - Прапануеце мангу, заснаваную на вашых перавагах - Уключыць прапановы - Прапанова - Выберыце мову, на якой вы хочаце чытаць мангу. Вы зможаце змяніць гэта пазней. - Скінуць фільтр - Знайсці жанр - Заўсёды - 18+ - Ніколі - Толькі праз Wi-Fi - Вы аўтарызаваны як %s - Папярэдняя загрузка старонак - Розныя мовы - Знайсці главу - %1$s%% - У гэтай манзе няма глаў - Схаваць - Знешні выгляд - Змесціва - Выключыць усё - Выкарыстоўваць адбітак пальца, калі даступна - Манга з абраных - Манга, якую вы нядаўна чыталі - Абнаўленне рэкамендацый - Апрацоўка захаванай мангі - Раздзелы будуць выдалены ў фонавым рэжыме - Правяраць новыя главы і паведамляць пра іх - Вы будзеце атрымліваць апавяшчэнні пра абнаўленні мангі, якую вы чытаеце - Вы не будзеце атрымліваць паведамленні, але новыя главы будуць паказаны ў спісе - Уключыць апавяшчэнні - Закладкі - Закладка выдалена - Закладка дадазена - Выдалена з гісторыі - DNS праз HTTPS - Аўтавызначэнне рэжыму чытання - Аўтаматычна вызначае, ці з’яўляецца манга вэбтунам - Даступныя новыя крыніцы мангі - Запавольванне спампоўкі - Выключыць жанры - Укажыце жанры, якія вы не хочаце бачыць у рэкамендацыях - Выдаліць выбраныя элементы з прылады назаўжды\? - Выдаленне завершана - Дапамагае пазбегнуць блакіроўкі па IP-адрасе - Выдаліць закладку - Рэжым па змаўчанні - Няма абраных катэгорый - Назва - Змяніць - Змяніць катэгорыю - Дадаць закладку - Адмяніць - Адключыць аптымізацыю акумулятара - Дапамагае з фонавай праверкай абнаўленняў - Штосьці пайшло не так. Калі ласка, адпраўце справаздачу пра памылку распрацоўшчыкам, каб дапамагчы нам яе выправіць. - Адправіць - Памылковы дамен - Справаздача - Адсочванне - Завершана - Адкладзена - Кінута - Паказваць індыкатары прагрэсу чытання - Запланавана - Чытаю - Выйсці - Паказваць працэнт прачытанага ў гісторыі і абраных - Выдаленне даных - Паказаць усе - Манга, пазначаная як NSFW, ніколі не будзе дададзеная ў гісторыю і ваш прагрэс не будзе захаваны - Можа дапамагчы з некаторымі праблемам. Усе аўтарызацыі будуць ануляваныя - Змесціва не знойдзена ці выдалена - Перачытваю - Выберыце дыяпазон - Тут нічога няма - Службы - Канадзе - Ачысціць усю гісторыю - Гісторыя ачышчана - Рэжым інкогніта - Вы ўпэўнены, што хочаце выдаліць выбраныя абраныя катэгорыі\? + На прыладзе + Абраныя + Гісторыя + Адбылася памылка + Памылка сеткі + Падрабязнасцi + Раздзелы + Спіс + Падрабязны спіс + Табліца + Выгляд спісу + Налады + Крыніцы мангі + Загрузка… + Глава %1$d з %2$d + Закрыць + Паўтарыць + Ачысціць гісторыю + Нічога не знойдзена + Гісторыя пустая + Чытаць + Дадайце цікавую для вас мангу ў абранае, каб не страціць яе + Дадаць у абраныя + Стварыць катэгорыю + Дадаць + Захаваць + Падзяліцца + Стварыць ярлык… + Падзялiцца %s + Пошук + Пошук мангі + Спампоўванне мангі… + Апрацоўка… + Спампоўванне завершана + Спампоўкі + Па імю + Папулярная + Абноўленая + Новая + Па рэйтынгу + Сартаванне + Фільтр + Тэма + Светлая + Цёмная + Як у сістэме + Старонкi + Ачысціць + Вы ўпэўненыя, што жадаеце ачысціць гісторыю\? + Выдаліць + «%s» выдалена з прылады + Захаваць старонку + Старонка захавана + Падзяліцца выявай + Імпарт + Выдаліць + Аперацыя не падтрымліваецца + Файл не падтрымліваецца. Падтрымліваюцца толькі ZIP і CBZ. + Няма апісання + Ачысціць кэш старонак + Б|кБ|МБ|ГБ|ТБ + Стандартны + Манхва + Рэжым чытання + Памер табліцы + Пошук па %s + Выдаліць мангу + Налады чытання + Гартанне старонак + Вы ўпэўненыя, што жадаеце выдаліць «%s» з прылады\? + Націск па краях + Кнопкі гучнасці + Працягнцуць + Памылка + Ачысціць кэш мініяцюр + Гісторыя пошуку ачышчана + Ачысціць гісторыю пошуку + Толькі жэсты + Унутранае сховішча + Знешняе сховішча + Дамен + Даступна абнаўленне праграмы + Адкрыць у браўзеры + У гэтай манге %s. Вы ўпэўненыя, што хочаце захаваць іх усё\? + Захаваць мангу + Паведамленні + Уключана %1$d з %2$d + Новыя раздзелы + Спампаваць + Налады апавяшчэнняў + Гук апавяшчэння + Светлавая iндыкацыя + Вібрацыя + Катэгорыі абранага + Выдаліць катэгорыю + Паліца з мангай + Нядаўняя манга + Анімацыя гартання + Месца спампоўвання мангі + Недаступна + Не атрымалася знайсці ніводнага даступнага сховішча + Іншае сховішча + Гатова + Усе абраныя + У гэтай катэгорыі нічога няма + Прачытаць пазней + Абнаўленні + Тут будуць паказвацца абнаўлення мангі, якую вы чытаеце + Вынікі пошуку + Новая версія: %s + Памер: %s + Ачысціць стужку абнаўленняў + Стужка абнаўленняў ачышчана + Павярнуць экран + Абнавіць + Абнаўленне хутка пачнецца + Правяраць абнаўленні мангі + Не правяраць + Увядзіце пароль + Няверны пароль + Абараніць праграму + Запытваць пароль пры запуску праграмы + Паўтарыце пароль + Паролі не супадаюць + Аб праграме + Версія %s + Праверыць абнаўленні + Няма даступных абнаўленняў + Справа налева + Стварыць катэгорыю + Маштабаванне + Умясціць у экран + Падагнаць па вышыні + Падагнаць па шырыні + Зыходны памер + Чорная + Спажывае менш энергіі на экранах AMOLED + Рэзервовае капіяванне і аднаўленне + Стварыць рэзервовую копію + Аднавіць данныя + Данныя адноўлены + Падрыхтоўка… + Файл не знойдзены + Усе данныя паспяхова адноўлены + Данныя адноўлены, але ўзніклі некаторыя памылкі + Вы можаце стварыць рэзервовую копію абранага і гісторыі і потым аднавіць іх + Толькі што + Учора + Даўно + Групаваць + Сёння + Паспрабаваць яшчэ раз + Абраны рэжым будзе захаваны для бягучай мангі + Без гуку + Неабходна прайсці CAPTCHA + Прайсці + Ачысціць кукi + Усе кукi выдалены + Ачысціць стужку + Уся гісторыя абнаўленняў будзе ачышчана і яе нельга будзе вярнуць. Вы ўпэўненыя\? + Праверка новых глаў + У адваротным парадку + Увайсці + Для прагляду гэтага кантэнту патрабуецца аўтарызацыя + Прадвызначаны: %s + Далей + Калі ласка, увядзіце пароль, які спатрэбіцца пры запуску праграмы + Пацвердзіць + Пароль павінен змяшчаць не менш за 4 сімвалы + Вы сапраўды хочаце выдаліць усе апошнія пошукавыя запыты\? + Падрабязна + Некаторыя вытворцы могуць змяняць паводзіны сістэмы, што можа парушаць выкананне фонавых задач. + Рэзервовая копія паспяхова захавана + Вітаю + Вы можаце захаваць мангу з анлайн-крыніц або імпартаваць з файла. + У вас яшчэ няма ніводнай захаванай мангі + Вы можаце знайсці, што пачытаць, у бакавым меню. + Тут будзе паказана манга, якую вы чытаеце + Паспрабуйце перафармуляваць запыт. + Тут неяк пуста… + Глава адсутнічае + У чарзе + Дапамагчы з перакладам праграмы + Пераклад + Вы выйдзеце з усіх крыніц, у якіх вы аўтарызаваны + Аўтарызацыя на %s не падтрымліваецца + Аўтарызацыя выканана + Жанры + Завершана + Ангоінг + Па змаўчанні + Не паказваць NSFW мангу з гісторыі + Паказваць нумары старонак + Уключаныя крыніцы + Даступныя крыніцы + Вылічэнні… + Дазваляць + Палітыка скрыншотаў + Заўсёды блакуйце + Блок на NSFW + Немагчыма загрузіць спіс жанраў + Непрацаздольны + Уключаны + Не прапануйце мангу NSFW + Пачніце чытаць мангу, і вы атрымаеце персаналізаваныя прапановы + Усе даныя аналізуюцца толькі лакальна на гэтай прыладзе і нікуды не адпраўляюцца. + Прапануеце мангу, заснаваную на вашых перавагах + Уключыць прапановы + Прапанова + Выберыце мову, на якой вы хочаце чытаць мангу. Вы зможаце змяніць гэта пазней. + Скінуць фільтр + Заўсёды + 18+ + Ніколі + Толькі праз Wi-Fi + Вы аўтарызаваны як %s + Папярэдняя загрузка старонак + Розныя мовы + Знайсці главу + %1$s%% + У гэтай манзе няма глаў + Схаваць + Знешні выгляд + Выключыць усё + Выкарыстоўваць адбітак пальца, калі даступна + Манга з абраных + Манга, якую вы нядаўна чыталі + Абнаўленне рэкамендацый + Апрацоўка захаванай мангі + Раздзелы будуць выдалены ў фонавым рэжыме + Правяраць новыя главы і паведамляць пра іх + Вы будзеце атрымліваць апавяшчэнні пра абнаўленні мангі, якую вы чытаеце + Вы не будзеце атрымліваць паведамленні, але новыя главы будуць паказаны ў спісе + Уключыць апавяшчэнні + Закладкі + Закладка выдалена + Закладка дадазена + Выдалена з гісторыі + DNS праз HTTPS + Аўтавызначэнне рэжыму чытання + Аўтаматычна вызначае, ці з’яўляецца манга вэбтунам + Даступныя новыя крыніцы мангі + Запавольванне спампоўкі + Выключыць жанры + Укажыце жанры, якія вы не хочаце бачыць у рэкамендацыях + Выдаліць выбраныя элементы з прылады назаўжды\? + Выдаленне завершана + Дапамагае пазбегнуць блакіроўкі па IP-адрасе + Выдаліць закладку + Рэжым па змаўчанні + Няма абраных катэгорый + Назва + Змяніць + Змяніць катэгорыю + Дадаць закладку + Адмяніць + Адключыць аптымізацыю акумулятара + Дапамагае з фонавай праверкай абнаўленняў + Штосьці пайшло не так. Калі ласка, адпраўце справаздачу пра памылку распрацоўшчыкам, каб дапамагчы нам яе выправіць. + Адправіць + Памылковы дамен + Справаздача + Адсочванне + Завершана + Адкладзена + Кінута + Паказваць індыкатары прагрэсу чытання + Запланавана + Чытаю + Выйсці + Паказваць працэнт прачытанага ў гісторыі і абраных + Выдаленне даных + Паказаць усе + Манга, пазначаная як NSFW, ніколі не будзе дададзеная ў гісторыю і ваш прагрэс не будзе захаваны + Можа дапамагчы з некаторымі праблемам. Усе аўтарызацыі будуць ануляваныя + Змесціва не знойдзена ці выдалена + Перачытваю + Выберыце дыяпазон + Тут нічога няма + Службы + Канадзе + Ачысціць усю гісторыю + Гісторыя ачышчана + Рэжым інкогніта + Вы ўпэўнены, што хочаце выдаліць выбраныя абраныя катэгорыі\? \nУся манга ў ім будзе страчана, і гэта нельга будзе адрабіць. - Вы можаце стварыць закладку падчас чытання мангі - Захаваная манга - Мамімі - Каб адсочваць ход чытання, выберыце Меню → Адсочваць на экране падрабязнасцей мангі. - Памылка сервера (%1$d). Калі ласка паспрабуйце зноў пазней - Таксама ачысціць інфармацыю аб новых раздзелах - Кампактны - Папярэдняя загрузка кантэнту - Пазначыць як бягучы - На прыладзе не засталося месца - Розныя мовы - Сетка недаступная - Каб чытаць мангу онлайн, уключыце Wi-Fi або мабільную сетку - Webtoon зум - Дынамічны - Каляровая гама - Мова - Уліковы запіс ужо існуе - Назад - Сінхранізацыя - Сінхранізацыя вашых дадзеных - Каб працягнуць, увядзіце свой адрас электроннай пошты - Вы можаце выдаліць зыходны файл са сховішча, каб зэканоміць месца - Хутка пачнецца імпарт - Дэталі памылкі:<br><tt>%1$s</tt><br><br>1. Паспрабуйце <a href=%2$s>адкрыць мангу ў вэб-браўзеры</a>, каб пераканацца, што яна даступная ў крыніцы<br>2. Упэўніцеся, што вы выкарыстоўваеце <a href=kotatsu://about>апошнюю версію Kotatsu</a><br>3. Калі ён даступны, адпраўце распрацоўнікам справаздачу аб памылцы. - Паказаць апошнія ярлыкі мангі - Зрабіце нядаўнюю мангу даступнай, доўга націскаючы на значок праграмы - Дакрананне да правага краю або націсканне правай клавішы заўсёды пераключае на наступную старонку - Эрганамічны упраўленне чытаннем - Карэкцыя колеру - Яркасць - Кантраст - Скінуць - Выбраныя налады колеру будуць запомнены для гэтай мангі - Захаваць ці адхіліць незахаваныя змены\? - Адмяніць - Уключыць запіс - Падзяліцца логамі - Запішыце некаторыя дзеянні для адладкі - Паказаць падазроны кантэнт - Ваша манга будзе адлюстроўвацца тут - Знайдзіце, што пачытаць, у раздзеле «Даследаваць» - Адменена - Кіраваць - Даступны - Стужка - Паказаць паўзунок пераключэння старонак - Крыніца адключана - Паказаць у выглядзе сеткі - Міку - Аска - Міён - Рыка - Сакура - Няма раздзелаў - Аўтаматычная пракрутка - Разд. %1$d/%2$d Стар. %3$d/%4$d - Паказаць інфармацыйную панэль у праграме чытання - Архіў коміксаў - Тэчка з малюнкамі - Імпарт мангі - Імпарт завершаны - Апошнія 2 гадзіны - Закладак пакуль няма - Закладкі выдалены - Няма крыніц мангі - Каб чытаць мангу онлайн, уключыце крыніцы мангі - Выпадковы - Змяніць парадак - Пуста - Дасьледуйце - Націсніце \"Назад\" яшчэ раз, каб выйсці - Двойчы націсніце \"Назад\", каб выйсці з праграмы - Пацверджанне выхаду - Кэш старонак - Іншы кэш - Выкарыстанне памяці - %s - %s - Выдалена з абраных - Параметры - Загаловак UserAgent - Дазволіць нестабільныя абнаўленні - Прапануйце абнаўленні да бэта-версій праграмы - Спампоўка пачалася - Калі ласка, перазапусціце праграму каб прымяніць змены - Зразумеў - Націсніце і ўтрымлівайце элемент, каб змяніць іх парадак - Вы можаце выбраць адзін або некалькі файлаў .cbz або .zip, кожны файл будзе распазнаны як асобная манга. - Вы можаце выбраць каталог з архівамі або выявамі. Кожны архіў (ці падкаталог) будзе прызнаны раздзелам. - Хуткасць - Імпарт раней створанай рэзервовай копіі дадзеных карыстальніка - Паказаць на паліцы - Знайсці падобныя - Вы можаце ўвайсці ў існуючы ўліковы запіс або стварыць новы - Налады сінхранізацыі - Адрас сервера - Выберыце люстэрка аўтаматычна - Аўтаматычна пераключаць дамены для аддаленых крыніц у выпадку памылак, калі даступныя люстэркі - Ігнараваць памылкі SSL - Аднавіць - Прыпынена - Адмяніць усё - Спампаваць толькі праз Wi-Fi - Вы можаце выкарыстоўваць уласны сервер сінхранізацыі або сервер па змаўчанні. Не змяняйце гэта, калі вы не ўпэўненыя, што робіце. - Паўза - Выдаліць завершаныя - Спыніць загрузку пры пераключэнні на мабільную сетку - Часам паказваць апавяшчэнні з прапанаванай мангай - Больш - Уключыць - Усе актыўныя спампоўкі будуць адменены, часткова спампаваныя даныя будуць страчаны - Хочаце атрымліваць персаналізаваныя прапановы мангі\? - Прапанова: %s - Не, дзякуй - Ваша гісторыя спамповак будзе выдалена назаўсёды - У вас няма загрузак - Спампоўкі аднавіліся - Спампоўкі прыпыненыя - Спампоўкі выдалены - Спампоўкі былі адменены - Пераклады - WebView недаступны: праверце, ці ўсталяваны пастаўшчык WebView - Тып - Адрас - Порт - Проксі - Ачысціць сеткавы кэш - %1$s (%2$s) - Няправільнае значэнне - \ No newline at end of file + Вы можаце стварыць закладку падчас чытання мангі + Захаваная манга + Мамімі + Каб адсочваць ход чытання, выберыце Меню → Адсочваць на экране падрабязнасцей мангі. + Памылка сервера (%1$d). Калі ласка паспрабуйце зноў пазней + Таксама ачысціць інфармацыю аб новых раздзелах + Кампактны + Папярэдняя загрузка кантэнту + Пазначыць як бягучы + На прыладзе не засталося месца + Розныя мовы + Сетка недаступная + Каб чытаць мангу онлайн, уключыце Wi-Fi або мабільную сетку + Webtoon зум + Дынамічны + Каляровая гама + Мова + Уліковы запіс ужо існуе + Назад + Сінхранізацыя + Сінхранізацыя вашых дадзеных + Каб працягнуць, увядзіце свой адрас электроннай пошты + Вы можаце выдаліць зыходны файл са сховішча, каб зэканоміць месца + Хутка пачнецца імпарт + Дэталі памылкі:<br><tt>%1$s</tt><br><br>1. Паспрабуйце <a href=%2$s>адкрыць мангу ў вэб-браўзеры</a>, каб пераканацца, што яна даступная ў крыніцы<br>2. Упэўніцеся, што вы выкарыстоўваеце <a href=kotatsu://about>апошнюю версію Kotatsu</a><br>3. Калі ён даступны, адпраўце распрацоўнікам справаздачу аб памылцы. + Паказаць апошнія ярлыкі мангі + Зрабіце нядаўнюю мангу даступнай, доўга націскаючы на значок праграмы + Дакрананне да правага краю або націсканне правай клавішы заўсёды пераключае на наступную старонку + Эрганамічны упраўленне чытаннем + Карэкцыя колеру + Яркасць + Кантраст + Скінуць + Выбраныя налады колеру будуць запомнены для гэтай мангі + Захаваць ці адхіліць незахаваныя змены\? + Адмяніць + Уключыць запіс + Падзяліцца логамі + Запішыце некаторыя дзеянні для адладкі + Паказаць падазроны кантэнт + Ваша манга будзе адлюстроўвацца тут + Знайдзіце, што пачытаць, у раздзеле «Даследаваць» + Адменена + Кіраваць + Даступны + Стужка + Паказаць паўзунок пераключэння старонак + Крыніца адключана + Паказаць у выглядзе сеткі + Міку + Аска + Міён + Рыка + Сакура + Няма раздзелаў + Аўтаматычная пракрутка + Разд. %1$d/%2$d Стар. %3$d/%4$d + Паказаць інфармацыйную панэль у праграме чытання + Архіў коміксаў + Тэчка з малюнкамі + Імпарт мангі + Імпарт завершаны + Апошнія 2 гадзіны + Закладак пакуль няма + Закладкі выдалены + Няма крыніц мангі + Каб чытаць мангу онлайн, уключыце крыніцы мангі + Выпадковы + Змяніць парадак + Пуста + Дасьледуйце + Націсніце \"Назад\" яшчэ раз, каб выйсці + Двойчы націсніце \"Назад\", каб выйсці з праграмы + Пацверджанне выхаду + Кэш старонак + Іншы кэш + Выкарыстанне памяці + %s - %s + Выдалена з абраных + Параметры + Загаловак UserAgent + Дазволіць нестабільныя абнаўленні + Прапануйце абнаўленні да бэта-версій праграмы + Спампоўка пачалася + Калі ласка, перазапусціце праграму каб прымяніць змены + Зразумеў + Націсніце і ўтрымлівайце элемент, каб змяніць іх парадак + Вы можаце выбраць адзін або некалькі файлаў .cbz або .zip, кожны файл будзе распазнаны як асобная манга. + Вы можаце выбраць каталог з архівамі або выявамі. Кожны архіў (ці падкаталог) будзе прызнаны раздзелам. + Хуткасць + Імпарт раней створанай рэзервовай копіі дадзеных карыстальніка + Паказаць на паліцы + Знайсці падобныя + Вы можаце ўвайсці ў існуючы ўліковы запіс або стварыць новы + Налады сінхранізацыі + Адрас сервера + Выберыце люстэрка аўтаматычна + Аўтаматычна пераключаць дамены для аддаленых крыніц у выпадку памылак, калі даступныя люстэркі + Ігнараваць памылкі SSL + Аднавіць + Прыпынена + Адмяніць усё + Спампаваць толькі праз Wi-Fi + Вы можаце выкарыстоўваць уласны сервер сінхранізацыі або сервер па змаўчанні. Не змяняйце гэта, калі вы не ўпэўненыя, што робіце. + Паўза + Выдаліць завершаныя + Спыніць загрузку пры пераключэнні на мабільную сетку + Часам паказваць апавяшчэнні з прапанаванай мангай + Больш + Уключыць + Усе актыўныя спампоўкі будуць адменены, часткова спампаваныя даныя будуць страчаны + Хочаце атрымліваць персаналізаваныя прапановы мангі\? + Прапанова: %s + Не, дзякуй + Ваша гісторыя спамповак будзе выдалена назаўсёды + У вас няма загрузак + Спампоўкі аднавіліся + Спампоўкі прыпыненыя + Спампоўкі выдалены + Спампоўкі былі адменены + Пераклады + WebView недаступны: праверце, ці ўсталяваны пастаўшчык WebView + Тып + Адрас + Порт + Проксі + Ачысціць сеткавы кэш + %1$s (%2$s) + Няправільнае значэнне + diff --git a/app/src/main/res/values-bn/plurals.xml b/app/src/main/res/values-bn/plurals.xml index d836ecb56..a90d74e48 100644 --- a/app/src/main/res/values-bn/plurals.xml +++ b/app/src/main/res/values-bn/plurals.xml @@ -1,15 +1,11 @@ - - %1$dটি আইটেম - %1$dটি আইটেম - - - সর্বমোট %1$dটি পেজ - সর্বমোট %1$dটি পেজ - - - %1$dটি নতুন চ্যাপ্টার - %1$dটি নতুন চ্যাপ্টার - - \ No newline at end of file + + %1$dটি আইটেম + %1$dটি আইটেম + + + %1$dটি নতুন চ্যাপ্টার + %1$dটি নতুন চ্যাপ্টার + + diff --git a/app/src/main/res/values-de/plurals.xml b/app/src/main/res/values-de/plurals.xml index c68adaa7b..57ba4ecdf 100644 --- a/app/src/main/res/values-de/plurals.xml +++ b/app/src/main/res/values-de/plurals.xml @@ -1,31 +1,27 @@ - - Insgesamt %1$d Seite - Insgesamt %1$d Seiten - - - %1$d Element - %1$d Elemente - - - %1$d neues Kapitel - %1$d neue Kapitel - - - %1$d Kapitel - %1$d Kapitel - - - Vor %1$d Minute - Vor %1$d Minuten - - - Vor %1$d Stunde - Vor %1$d Stunden - - - Vor %1$d Tag - Vor %1$d Tagen - - \ No newline at end of file + + %1$d Element + %1$d Elemente + + + %1$d neues Kapitel + %1$d neue Kapitel + + + %1$d Kapitel + %1$d Kapitel + + + Vor %1$d Minute + Vor %1$d Minuten + + + Vor %1$d Stunde + Vor %1$d Stunden + + + Vor %1$d Tag + Vor %1$d Tagen + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3198bc6bc..e7cb5fb89 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,415 +1,411 @@ - Entfernen - Gesamten Leseverlauf unwiderruflich löschen\? - Design - Seiten - Wie System - Dunkel - Hell - Filter - Sortierreihenfolge - Bewertung - Neuestes - Beliebt - Name - Downloads - Heruntergeladen - Manga suchen - Suchen - Teilen %s - Teilen - Speichern - Hinzufügen - Neue Kategorie - Zu Favoriten hinzufügen - Noch keine Favoriten - Lesen - Noch kein Verlauf - Nichts gefunden - Verlauf löschen - Erneut versuchen - Schließen - Kapitel %1$d von %2$d - Manga Quellen - Einstellungen - Listenmodus - Raster - Den gesamte Aktualisierungsverlauf unwiderruflich löschen\? - Keine Aktualisierungen verfügbar - Nach Aktualisierungen suchen - Suche nach Aktualisierungen - Die Feed-Aktualisierung beginnt gleich - Aktualisieren - Gelöscht - Aktualisierungsfeed löschen - Aktualisierungen - Eine neue Version der App ist verfügbar - Aktualisiert - Vorbereitung… - Hier ist es etwas leer… - Verarbeiten… - Herunterladen… - Verknüpfung erstellen… - Laden… - „%s“ unwiderruflich vom Gerät löschen\? - „%s“ aus lokalem Speicher gelöscht - Detaillierte Liste - Liste - Kapitel - Details - Netzwerkfehler - Ein Fehler ist aufgetreten - Verlauf - Favoriten - Lokaler Speicher - Ordner für Downloads - Die Manga, die du gerade liest, werden hier angezeigt - Am Anfang ausrichten - An Breite anpassen - An Höhe anpassen - Spart Energie auf AMOLED-Bildschirmen - Reines Schwarz - Von rechts nach links - Neue Kategorie - Backup und Wiederherstellung - Daten wiederhergestellt - Backup wiederherstellen - Backup erstellen - Datei nicht gefunden - Gerade jetzt - Gruppe - Alle Cookies wurden entfernt - Cookies löschen - Standard: %s - Melde dich an, um diesen Inhalt anzusehen - Umkehren - Nach neuen Kapiteln suchen - Feed löschen - Anmelden - Das Passwort muss mindestens 4 Zeichen lang sein - Bestätigen - Gib ein Passwort ein, mit dem die App gestartet werden soll - Weiter - Möchtest du alle letzten Suchanfragen unwiderruflich entfernen\? - Mehr erfahren - Einige Geräte haben ein anderes Systemverhalten, welches womöglich Hintergrundprozesse unterbricht. - Backup gespeichert - Willkommen - Entfernen - Bildschirm drehen - Größe: %s - Neue Version: %s - Suchergebnisse - Hier siehst du neue Kapitel der Mangas, die du liest - Später lesen - Diese Kategorie ist leer - Alle Favoriten - Fertig - Sonstiger Speicherort - Kein verfügbarer Speicher gefunden - Nicht verfügbar - Seitenanimation - Neueste Manga - Regal - Speicher Manga aus Online-Quellen oder importiere Dateien. - Speichere erst etwas - Was du lesen kannst, findest du im Seitenmenü. - Versuche, die Anfrage umzuformulieren. - Favoriten-Kategorien - Vibration - LED-Anzeige - Benachrichtigungston - Benachrichtigungseinstellungen - Herunterladen - Neue Kapitel - %1$d von %2$d aktiviert - Benachrichtigungen - Manga speichern - Dieser Manga hat %s. Alles davon speichern\? - Im Browser öffnen - Externer Speicher - Interner Speicher - Gelöscht - Suchverlauf löschen - Miniaturansichten Cache löschen - Fehler - Weiter - Lautstärketasten - Seiten wechseln - Leseeinstellungen - Manga löschen - Suche auf %s - Rastergröße - Lesemodus - Webtoon - Standard - B|kB|MB|GB|TB - Seitencache löschen - Verlauf und Cache - Keine Beschreibung - Wähle entweder eine ZIP- oder CBZ-Datei. - Dieser Vorgang wird nicht unterstützt - Löschen - Importieren - Bild teilen - Gespeichert - Seite speichern - Löschen - Rand antippen - Lösen - CAPTCHA erforderlich - Stumm - Die gewählte Konfiguration wird für diesen Manga gespeichert - Tippe, um es erneut zu versuchen - Heute - Vor langer Zeit - Gestern - Du kannst ein Backup deines Verlaufs und deiner Favoriten erstellen und wiederherstellen - Die Daten wurden wiederhergestellt, aber es gibt Fehler - Alle Daten wiederhergestellt - An Zentrum anpassen - Skalierungsmodus - Version %s - Über - Passwörter stimmen nicht überein - Wiederhole das Passwort - Beim Start von Kotatsu nach Passwort fragen - App schützen - Falsches Passwort - Passwort eingeben - Nicht prüfen - Domäne - Nur Gesten - Das Kapitel fehlt - Lade dieses fehlende Kapitel herunter oder lese es online. - In Warteschlange - Übersetzung - Übersetze die App - Du wirst von allen Quellen abgemeldet - Genres - Anmeldung bei %s wird nicht unterstützt - Autorisierung abgeschlossen - Beendet - Fortlaufend - Standard - NSFW-Manga vom Verlauf ausschließen - Nummerierte Seiten - Verwendete Quellen - Verfügbare Quellen - Berechnen… - Erlauben - Bildschirmfoto-Verhalten - Für NSFW blockieren - Immer blockieren - Vorschläge - Vorschläge einschalten - Schlage Manga basierend auf deinen Vorlieben vor - Alle Daten werden ausschließlich lokal auf diesem Gerät ausgewertet und nie weiter versendet. - Keine NSFW-Manga vorschlagen - Aktiviert - Beginne Manga zu lesen und du erhältst personalisierte Vorschläge - Deaktiviert - Liste der Genres kann nicht geladen werden - Nie - Immer - Seiten vorladen - Filter zurücksetzen - Genre finden - Nur über WLAN - Wähle die Sprachen aus, in denen du Mangas lesen möchten. Du kannst das später in den Einstellungen anpassen. - Angemeldet als %s - 18+ - Verschiedene Sprachen - Kapitel suchen - Keine Kapitel in diesem Manga - %1$s%% - Aussehen - Inhalt - Vorschläge werden aktualisiert - Genres ausschließen - Gebe Genres an, die du nicht in den Vorschlägen sehen möchtest - Ausgewählte Elemente unwiderruflich vom Gerät löschen\? - Entfernung abgeschlossen - Download-Verzögerung - Manga-Verarbeitung gespeichert - Hilft, das Blockieren deiner IP-Adresse zu vermeiden - Kapitel werden im Hintergrund entfernt - Ausblenden - Neue Manga-Quellen sind verfügbar - Nach neuen Kapiteln suchen und benachrichtigt werden - Erhalte Benachrichtigungen bei Aktualisierungen der Manga, die du liest - Benachrichtigungen einschalten - Keine bevorzugten Kategorien - Name - Bearbeiten - Du wirst keine Benachrichtigungen erhalten, aber neue Kapitel werden in den Listen hervorgehoben - Kategorie bearbeiten - Lesezeichen hinzufügen - Lesezeichen - Lesezeichen entfernt - Aus dem Verlauf entfernt - Lesezeichen entfernen - Lesezeichen hinzugefügt - Rückgängig - DNS über HTTPS - Standard-Modus - Automatische Erkennung des Modus - Automatisch erkennen, ob ein Manga ein Webtoon ist - Akkuoptimierung deaktivieren - Hilft bei der Hintergrundaktualisierung - Senden - Etwas ist schief gelaufen. Bitte sende einen Fehlerbericht an die Entwickler, um uns bei der Behebung zu helfen. - Alle deaktivieren - Fingerabdruck verwenden, falls verfügbar - Manga aus deinen Favoriten - Deine kürzlich gelesenen Manga - Melden - Nachverfolgung - Abmelden - Geplant - In der Warteschleife - Indikatoren für den Lesefortschritt anzeigen - Alle anzeigen - Zeige gelesenen Prozentsatz in Verlauf und Favoriten - Kann bei einigen Probleme helfen. Alle Anmeldungen werden ungültig - Abgeschlossen - Als NSFW markierte Manga werden nicht dem Verlauf beigefügt und dein Lesefortschritt wird nicht gespeichert - Datenlöschung - Ungültige Domain - Lese - Bereich auswählen - Inhalt nicht gefunden oder entfernt - Fehlerdetails:<br><tt>%1$s</tt><br><br>1. Versuche, <a href=%2$s>den Manga in einem Webbrowser zu öffnen</a>, um sicherzustellen, dass er bei seiner Quelle verfügbar ist<br>2. Stelle sicher, dass du die <a href=kotatsu://about>neueste Kotatsu-Version</a><br>3 benutzt. Wenn er verfügbar ist, sende einen Fehlerbericht an die Entwickler. - Noch keine Lesezeichen - Keine Manga-Quellen - Manga-Quellen aktivieren, um Manga online zu lesen - Beenden bestätigen - Gespeicherte Manga - Seiten-Cache - Anderer Cache - Speichernutzung - Verfügbar - %s - %s - Aus den Favoriten entfernt - Optionen - Automatisches Blättern - Comics-Archiv - Kap. %1$d/%2$d S. %3$d/%4$d - Deine Manga werden hier angezeigt - Finde etwas zu lesen in der Rubrik „Erkunden“ - Abgebrochen - Konto existiert bereits - Zurück - Synchronisierung - Synchronisiere deine Daten - Gib deine E-Mail-Adresse ein, um fortzufahren - Gesamten Verlauf löschen - Letzte 2 Stunden - Verlauf gelöscht - Verwalten - Du kannst beim Lesen von Mangas Lesezeichen erstellen - Lesezeichen entfernt - Zufällig - Bist du sicher, dass du die ausgewählten Lieblingskategorien löschen möchtest\? + Entfernen + Gesamten Leseverlauf unwiderruflich löschen\? + Design + Seiten + Wie System + Dunkel + Hell + Filter + Sortierreihenfolge + Bewertung + Neuestes + Beliebt + Name + Downloads + Heruntergeladen + Manga suchen + Suchen + Teilen %s + Teilen + Speichern + Hinzufügen + Neue Kategorie + Zu Favoriten hinzufügen + Noch keine Favoriten + Lesen + Noch kein Verlauf + Nichts gefunden + Verlauf löschen + Erneut versuchen + Schließen + Kapitel %1$d von %2$d + Manga Quellen + Einstellungen + Listenmodus + Raster + Den gesamte Aktualisierungsverlauf unwiderruflich löschen\? + Keine Aktualisierungen verfügbar + Nach Aktualisierungen suchen + Suche nach Aktualisierungen + Die Feed-Aktualisierung beginnt gleich + Aktualisieren + Gelöscht + Aktualisierungsfeed löschen + Aktualisierungen + Eine neue Version der App ist verfügbar + Aktualisiert + Vorbereitung… + Hier ist es etwas leer… + Verarbeiten… + Herunterladen… + Verknüpfung erstellen… + Laden… + „%s“ unwiderruflich vom Gerät löschen\? + „%s“ aus lokalem Speicher gelöscht + Detaillierte Liste + Liste + Kapitel + Details + Netzwerkfehler + Ein Fehler ist aufgetreten + Verlauf + Favoriten + Lokaler Speicher + Ordner für Downloads + Die Manga, die du gerade liest, werden hier angezeigt + Am Anfang ausrichten + An Breite anpassen + An Höhe anpassen + Spart Energie auf AMOLED-Bildschirmen + Reines Schwarz + Von rechts nach links + Neue Kategorie + Backup und Wiederherstellung + Daten wiederhergestellt + Backup wiederherstellen + Backup erstellen + Datei nicht gefunden + Gerade jetzt + Gruppe + Alle Cookies wurden entfernt + Cookies löschen + Standard: %s + Melde dich an, um diesen Inhalt anzusehen + Umkehren + Nach neuen Kapiteln suchen + Feed löschen + Anmelden + Das Passwort muss mindestens 4 Zeichen lang sein + Bestätigen + Gib ein Passwort ein, mit dem die App gestartet werden soll + Weiter + Möchtest du alle letzten Suchanfragen unwiderruflich entfernen\? + Mehr erfahren + Einige Geräte haben ein anderes Systemverhalten, welches womöglich Hintergrundprozesse unterbricht. + Backup gespeichert + Willkommen + Entfernen + Bildschirm drehen + Größe: %s + Neue Version: %s + Suchergebnisse + Hier siehst du neue Kapitel der Mangas, die du liest + Später lesen + Diese Kategorie ist leer + Alle Favoriten + Fertig + Sonstiger Speicherort + Kein verfügbarer Speicher gefunden + Nicht verfügbar + Seitenanimation + Neueste Manga + Regal + Speicher Manga aus Online-Quellen oder importiere Dateien. + Speichere erst etwas + Was du lesen kannst, findest du im Seitenmenü. + Versuche, die Anfrage umzuformulieren. + Favoriten-Kategorien + Vibration + LED-Anzeige + Benachrichtigungston + Benachrichtigungseinstellungen + Herunterladen + Neue Kapitel + %1$d von %2$d aktiviert + Benachrichtigungen + Manga speichern + Dieser Manga hat %s. Alles davon speichern\? + Im Browser öffnen + Externer Speicher + Interner Speicher + Gelöscht + Suchverlauf löschen + Miniaturansichten Cache löschen + Fehler + Weiter + Lautstärketasten + Seiten wechseln + Leseeinstellungen + Manga löschen + Suche auf %s + Rastergröße + Lesemodus + Webtoon + Standard + B|kB|MB|GB|TB + Seitencache löschen + Keine Beschreibung + Wähle entweder eine ZIP- oder CBZ-Datei. + Dieser Vorgang wird nicht unterstützt + Löschen + Importieren + Bild teilen + Gespeichert + Seite speichern + Löschen + Rand antippen + Lösen + CAPTCHA erforderlich + Stumm + Die gewählte Konfiguration wird für diesen Manga gespeichert + Tippe, um es erneut zu versuchen + Heute + Vor langer Zeit + Gestern + Du kannst ein Backup deines Verlaufs und deiner Favoriten erstellen und wiederherstellen + Die Daten wurden wiederhergestellt, aber es gibt Fehler + Alle Daten wiederhergestellt + An Zentrum anpassen + Skalierungsmodus + Version %s + Über + Passwörter stimmen nicht überein + Wiederhole das Passwort + Beim Start von Kotatsu nach Passwort fragen + App schützen + Falsches Passwort + Passwort eingeben + Nicht prüfen + Domäne + Nur Gesten + Das Kapitel fehlt + In Warteschlange + Übersetzung + Übersetze die App + Du wirst von allen Quellen abgemeldet + Genres + Anmeldung bei %s wird nicht unterstützt + Autorisierung abgeschlossen + Beendet + Fortlaufend + Standard + NSFW-Manga vom Verlauf ausschließen + Nummerierte Seiten + Verwendete Quellen + Verfügbare Quellen + Berechnen… + Erlauben + Bildschirmfoto-Verhalten + Für NSFW blockieren + Immer blockieren + Vorschläge + Vorschläge einschalten + Schlage Manga basierend auf deinen Vorlieben vor + Alle Daten werden ausschließlich lokal auf diesem Gerät ausgewertet und nie weiter versendet. + Keine NSFW-Manga vorschlagen + Aktiviert + Beginne Manga zu lesen und du erhältst personalisierte Vorschläge + Deaktiviert + Liste der Genres kann nicht geladen werden + Nie + Immer + Seiten vorladen + Filter zurücksetzen + Nur über WLAN + Wähle die Sprachen aus, in denen du Mangas lesen möchten. Du kannst das später in den Einstellungen anpassen. + Angemeldet als %s + 18+ + Verschiedene Sprachen + Kapitel suchen + Keine Kapitel in diesem Manga + %1$s%% + Aussehen + Vorschläge werden aktualisiert + Genres ausschließen + Gebe Genres an, die du nicht in den Vorschlägen sehen möchtest + Ausgewählte Elemente unwiderruflich vom Gerät löschen\? + Entfernung abgeschlossen + Download-Verzögerung + Manga-Verarbeitung gespeichert + Hilft, das Blockieren deiner IP-Adresse zu vermeiden + Kapitel werden im Hintergrund entfernt + Ausblenden + Neue Manga-Quellen sind verfügbar + Nach neuen Kapiteln suchen und benachrichtigt werden + Erhalte Benachrichtigungen bei Aktualisierungen der Manga, die du liest + Benachrichtigungen einschalten + Keine bevorzugten Kategorien + Name + Bearbeiten + Du wirst keine Benachrichtigungen erhalten, aber neue Kapitel werden in den Listen hervorgehoben + Kategorie bearbeiten + Lesezeichen hinzufügen + Lesezeichen + Lesezeichen entfernt + Aus dem Verlauf entfernt + Lesezeichen entfernen + Lesezeichen hinzugefügt + Rückgängig + DNS über HTTPS + Standard-Modus + Automatische Erkennung des Modus + Automatisch erkennen, ob ein Manga ein Webtoon ist + Akkuoptimierung deaktivieren + Hilft bei der Hintergrundaktualisierung + Senden + Etwas ist schief gelaufen. Bitte sende einen Fehlerbericht an die Entwickler, um uns bei der Behebung zu helfen. + Alle deaktivieren + Fingerabdruck verwenden, falls verfügbar + Manga aus deinen Favoriten + Deine kürzlich gelesenen Manga + Melden + Nachverfolgung + Abmelden + Geplant + In der Warteschleife + Indikatoren für den Lesefortschritt anzeigen + Alle anzeigen + Zeige gelesenen Prozentsatz in Verlauf und Favoriten + Kann bei einigen Probleme helfen. Alle Anmeldungen werden ungültig + Abgeschlossen + Als NSFW markierte Manga werden nicht dem Verlauf beigefügt und dein Lesefortschritt wird nicht gespeichert + Datenlöschung + Ungültige Domain + Lese + Bereich auswählen + Inhalt nicht gefunden oder entfernt + Fehlerdetails:<br><tt>%1$s</tt><br><br>1. Versuche, <a href=%2$s>den Manga in einem Webbrowser zu öffnen</a>, um sicherzustellen, dass er bei seiner Quelle verfügbar ist<br>2. Stelle sicher, dass du die <a href=kotatsu://about>neueste Kotatsu-Version</a><br>3 benutzt. Wenn er verfügbar ist, sende einen Fehlerbericht an die Entwickler. + Noch keine Lesezeichen + Keine Manga-Quellen + Manga-Quellen aktivieren, um Manga online zu lesen + Beenden bestätigen + Gespeicherte Manga + Seiten-Cache + Anderer Cache + Speichernutzung + Verfügbar + %s - %s + Aus den Favoriten entfernt + Optionen + Automatisches Blättern + Comics-Archiv + Kap. %1$d/%2$d S. %3$d/%4$d + Deine Manga werden hier angezeigt + Finde etwas zu lesen in der Rubrik „Erkunden“ + Abgebrochen + Konto existiert bereits + Zurück + Synchronisierung + Synchronisiere deine Daten + Gib deine E-Mail-Adresse ein, um fortzufahren + Gesamten Verlauf löschen + Letzte 2 Stunden + Verlauf gelöscht + Verwalten + Du kannst beim Lesen von Mangas Lesezeichen erstellen + Lesezeichen entfernt + Zufällig + Bist du sicher, dass du die ausgewählten Lieblingskategorien löschen möchtest\? \nAlle darin enthaltenen Manga gehen verloren und das kann nicht rückgängig gemacht werden. - Neu anordnen - Leer - Erkunden - Drücke zum Beenden erneut Zurück - Drücke zweimal Zurück, um die App zu beenden - Feed - Inkognito-Modus - Keine Kapitel - Zeige Informationsleiste beim Lesen - Ordner mit Bildern - Importiere Manga - Import abgeschlossen - Du kannst die Originaldatei aus dem Speicher löschen, um Platz zu sparen - Import wird bald beginnen - Serverseitiger Fehler (%1$d). Bitte versuche es später erneut - Kompakt - Kontrast - Schalte WLAN oder mobile Daten ein, um Manga online zu lesen - Auch Informationen über neue Kapitel löschen - Ungespeicherte Änderungen speichern oder verwerfen\? - Verwerfen - Zurücksetzen - Helligkeit - Die gewählten Farbeinstellungen werden für diesen Manga beibehalten - Farbkorrektur - Kein Platz übrig auf dem Gerät - Verschiedene Sprachen - Netzwerk ist nicht verfügbar - Ergonomische Lesekontrolle - Tippe auf den rechten Rand oder drücke die rechte Taste, um immer zur nächsten Seite zu wechseln - Zeige Seitenwechsel-Schieber - Quelle deaktiviert - Inhalte vorladen - Als aktuell markieren - Webtoon-Zoom - Protokolle teilen - Protokollierung aktivieren - Sprache - Einige Aktionen zu Debug-Zwecken aufzeichnen - Zeige Verknüpfungen zu aktuellen Manga - Neueste Manga durch langes Drücken auf das Anwendungssymbol verfügbar machen - Verdächtige Inhalte anzeigen - Abgebrochen - Farbschema - Dynamisch - Mamimi - Hier ist nichts - Dienste - Kanade - Um deinen Lesefortschritt nachzuverfolgen, wähle Menu → Track auf dem Manga Details Bildschirm. - Ähnliche finden - Sakura - Schlage Updates zu Beta-Versionen der App vor - Erlaube instabile Updates - Alles klar - Drücke und halte eine Quelle, um diese umzusortieren - Bitte starte die App neu, um die Änderungen anzuwenden - Du kannst eine oder mehrere .cbz oder .zip Dateien auswählen, jede Datei wird als einzelner Manga erkannt. - Du kannst einen Ordner mit Archiven oder Bildern auswählen. Jedes Archiv (oder Unterverzeichnis) wird als ein Kapitel erkannt. - Geschwindigkeit - Importiere ein zuvor erstelltes Nutzerdaten-Backup - Im Regal anzeigen - Miku - Asuka - Mion - Rikka - In Raster-Ansicht anzeigen - Serveradresse - Wähle Mirror automatisch - Download gestartet - Synchronisationseinstellungen - Du kannst einen Standard- oder einen selbst gehosteten Synchronisations-Server verwenden. Ändere diese Einstellungen nicht, wenn du dich nicht auskennst. - Ignoriere SSL Errors - Wechsel bei Fehlern automatisch die Domains für Manga-Quellen, falls Mirrors verfügbar sind - Lese erneut - Du kannst dich mit einem bestehenden Account anmelden oder einen neuen erstellen - UserAgent-Kopfzeile - Aktivieren - Nein danke - Pausieren - Fortsetzen - Pausiert - Entfernung abgeschlossen - Alle abbrechen - Nur über Wi-Fi herunterladen - Beende das Herunterladen beim Wechsel zu einem Mobilfunknetz - Zeige ab und zu Benachrichtigungen mit Manga-Vorschlägen - Downloads wurden entfernt - Vorschlag: %s - Mehr - Alle Downloads werden abgebrochen, teilweise heruntergeladene Dateien gehen verloren - Dein Downloads-Verlauf wird unwiderruflich gelöscht - Du hast keine Downloads - Downloads wurden fortgesetzt - Downloads wurden pausiert - Downloads wurden abgebrochen - Willst du personalisierte Manga-Vorschläge erhalten\? - Übersetzungen - WebView nicht verfügbar: überprüfe, ob WebView installiert ist - \ No newline at end of file + Neu anordnen + Leer + Erkunden + Drücke zum Beenden erneut Zurück + Drücke zweimal Zurück, um die App zu beenden + Feed + Inkognito-Modus + Keine Kapitel + Zeige Informationsleiste beim Lesen + Ordner mit Bildern + Importiere Manga + Import abgeschlossen + Du kannst die Originaldatei aus dem Speicher löschen, um Platz zu sparen + Import wird bald beginnen + Serverseitiger Fehler (%1$d). Bitte versuche es später erneut + Kompakt + Kontrast + Schalte WLAN oder mobile Daten ein, um Manga online zu lesen + Auch Informationen über neue Kapitel löschen + Ungespeicherte Änderungen speichern oder verwerfen\? + Verwerfen + Zurücksetzen + Helligkeit + Die gewählten Farbeinstellungen werden für diesen Manga beibehalten + Farbkorrektur + Kein Platz übrig auf dem Gerät + Verschiedene Sprachen + Netzwerk ist nicht verfügbar + Ergonomische Lesekontrolle + Tippe auf den rechten Rand oder drücke die rechte Taste, um immer zur nächsten Seite zu wechseln + Zeige Seitenwechsel-Schieber + Quelle deaktiviert + Inhalte vorladen + Als aktuell markieren + Webtoon-Zoom + Protokolle teilen + Protokollierung aktivieren + Sprache + Einige Aktionen zu Debug-Zwecken aufzeichnen + Zeige Verknüpfungen zu aktuellen Manga + Neueste Manga durch langes Drücken auf das Anwendungssymbol verfügbar machen + Verdächtige Inhalte anzeigen + Abgebrochen + Farbschema + Dynamisch + Mamimi + Hier ist nichts + Dienste + Kanade + Um deinen Lesefortschritt nachzuverfolgen, wähle Menu → Track auf dem Manga Details Bildschirm. + Ähnliche finden + Sakura + Schlage Updates zu Beta-Versionen der App vor + Erlaube instabile Updates + Alles klar + Drücke und halte eine Quelle, um diese umzusortieren + Bitte starte die App neu, um die Änderungen anzuwenden + Du kannst eine oder mehrere .cbz oder .zip Dateien auswählen, jede Datei wird als einzelner Manga erkannt. + Du kannst einen Ordner mit Archiven oder Bildern auswählen. Jedes Archiv (oder Unterverzeichnis) wird als ein Kapitel erkannt. + Geschwindigkeit + Importiere ein zuvor erstelltes Nutzerdaten-Backup + Im Regal anzeigen + Miku + Asuka + Mion + Rikka + In Raster-Ansicht anzeigen + Serveradresse + Wähle Mirror automatisch + Download gestartet + Synchronisationseinstellungen + Du kannst einen Standard- oder einen selbst gehosteten Synchronisations-Server verwenden. Ändere diese Einstellungen nicht, wenn du dich nicht auskennst. + Ignoriere SSL Errors + Wechsel bei Fehlern automatisch die Domains für Manga-Quellen, falls Mirrors verfügbar sind + Lese erneut + Du kannst dich mit einem bestehenden Account anmelden oder einen neuen erstellen + UserAgent-Kopfzeile + Aktivieren + Nein danke + Pausieren + Fortsetzen + Pausiert + Entfernung abgeschlossen + Alle abbrechen + Nur über Wi-Fi herunterladen + Beende das Herunterladen beim Wechsel zu einem Mobilfunknetz + Zeige ab und zu Benachrichtigungen mit Manga-Vorschlägen + Downloads wurden entfernt + Vorschlag: %s + Mehr + Alle Downloads werden abgebrochen, teilweise heruntergeladene Dateien gehen verloren + Dein Downloads-Verlauf wird unwiderruflich gelöscht + Du hast keine Downloads + Downloads wurden fortgesetzt + Downloads wurden pausiert + Downloads wurden abgebrochen + Willst du personalisierte Manga-Vorschläge erhalten\? + Übersetzungen + WebView nicht verfügbar: überprüfe, ob WebView installiert ist + diff --git a/app/src/main/res/values-el/plurals.xml b/app/src/main/res/values-el/plurals.xml index 08b7f5084..edbd58db0 100644 --- a/app/src/main/res/values-el/plurals.xml +++ b/app/src/main/res/values-el/plurals.xml @@ -20,10 +20,6 @@ %1$dκεφάλαιο %1$dκεφάλαια - - Σύνολο%1$dσελίδα - Σύνολο%1$dσελίδες - %1$dλεπτό πριν %1$d λεπτά πριν diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index d7bf6d6b4..0186123b3 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -42,7 +42,6 @@ Διαγραφή Επιλέξτε ένα αρχείο ZIP ή CBZ. Χωρίς περιγραφή - Ιστορικό και μνήμη cache Εκκαθάριση μνήμης cache της σελίδας B|kB|MB|GB|TB Τυπικό diff --git a/app/src/main/res/values-es/plurals.xml b/app/src/main/res/values-es/plurals.xml index f5f4a4cbb..10d2afcd6 100644 --- a/app/src/main/res/values-es/plurals.xml +++ b/app/src/main/res/values-es/plurals.xml @@ -1,38 +1,33 @@ - - Página total %1$d - Páginas totales %1$d - Página totales %1$d - - - %1$d elemento - %1$d elementos - %1$d elementos - - - %1$d nuevo capítulo - %1$d nuevos capítulos - %1$d nuevos capítulos - - - %1$d capítulo - %1$d capítulos - %1$d capítulos - - - hace %1$d minuto - hace %1$d minutos - hace %1$d minutos - - - hace %1$d hora - hace %1$d horas - hace %1$d horas - - - hace %1$d día - hace %1$d días - hace %1$d días - - \ No newline at end of file + + %1$d elemento + %1$d elementos + %1$d elementos + + + %1$d nuevo capítulo + %1$d nuevos capítulos + %1$d nuevos capítulos + + + %1$d capítulo + %1$d capítulos + %1$d capítulos + + + hace %1$d minuto + hace %1$d minutos + hace %1$d minutos + + + hace %1$d hora + hace %1$d horas + hace %1$d horas + + + hace %1$d día + hace %1$d días + hace %1$d días + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ae1169138..09dec10e3 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,429 +1,425 @@ - Dispositivo - Favoritos - Historial - Ocurrió un error - Error en la red - Detalles - Capítulos - Lista - Lista detallada - Cuadrículas - Vista de lista - Ajustes - Fuentes del manga - Cargando… - Capítulo %1$d de %2$d - Cerrar - Reintentar - Borrar historial - No se encontró nada - Aún sin historial - Leer - Aún no hay favoritos - Añadir a favoritos - Nueva categoría - Añadir - Guardar - Compartir - Crear acceso directo… - Compartir %s - Buscar - Buscar manga - Descargando… - Procesando… - Descargado - Descargas - Nombre - Popularidad - Actualización - Recientes - Calificación - Orden de clasificación - Filtrar - Tema - Claro - Oscuro - De acuerdo al sistema - Páginas - Borrar - Borrar todo el historial de lectura de forma permanente\? - Eliminar - «%s» borrado del almacenamiento local - Guardar página - Guardado - Compartir imagen - Importar - Borrar - Esta operación no está admitida - Elija un archivo ZIP o bien un archivo CBZ. - Sin descripción - Historial y caché - Borrar caché de página - B|kB|MB|GB|TB - Estándar - Sitio web - Modo de lectura - Tamaño de la cuadrícula - Buscar en %s - Borrar manga - ¿Borrar \"%s\" del dispositivo permanentemente\? - Ajustes del lector - Cambiar de página - Toques de borde - Botones de volumen - Continuar - Error - Borrar la caché de miniaturas - Borrar el historial de búsqueda - Historial de búsqueda borrado - Sólo gestos - Almacenamiento interno - Almacenamiento externo - Dominio - Una nueva versión de la aplicación está disponible - Abrir en navegador web - Este manga tiene %s. ¿Quieres guardarlo todo\? - Guardar - Notificaciones - Activado %1$d de %2$d - Nuevos capítulos - Descargar - Configuración de las notificaciones - Sonido de las notificaciones - Indicador LED - Vibración - Categorías favoritas - Remover - Estante - Reciente - Animación de página - Carpeta para descargas - No disponible - No hay almacenamiento disponible - Otro almacenamiento - Aceptar - Todos los favoritos - Categoría vacía - Leer más tarde - Actualizaciones - Aquí verás los nuevos episodios del manga que estás leyendo - Resultados de la búsqueda - Nueva versión: %s - Tamaño: %s - Borrar actualizaciones - Borrar el feed de actualizaciones - Girar pantalla - Actualizar - La actualización de la alimentación comenzará pronto - Comprueba las actualizaciones del manga - No comprobar - Introducir contraseña - Contraseña incorrecta - Proteger aplicación - Pedir una contraseña al iniciar Kotatsu - Repite la contraseña - Las contraseñas no coinciden - Acerca de - Versión %s - Comprobar actualizaciones - No hay actualizaciones disponibles - De derecha a izquierda - Nueva categoría - Modo de escala - Ajuste al centro - Ajuste a la altura - Ajuste a la anchura - Mantener al iniciar - Tema oscuro auténtico - Útil para pantallas AMOLED - Respaldo y restauración - Crear copia de seguridad de datos - Restaurar desde la copia de seguridad - Datos restaurados - Preparando… - Archivo no encontrado - Todos los datos fueron restaurados con éxito - Los datos fueron restaurados, pero hay errores - Puedes crear una copia de seguridad de tu historial y favoritos para restaurarla - Ahora mismo - Ayer - Hace mucho tiempo - Grupo - Hoy - Toca para volver a intentar - Se recordará la configuración elegida para este manga - Silenciar - El captcha es obligatorio - Resolver - Borrar cookies - Se han eliminado todas las cookies - Limpiar feed - Todo el historial de actualizaciones se borrará y esta acción no se puede deshacer. ¿Está seguro\? - Comprobación de nuevos capítulos - Invertir - Iniciar sesión - Debes autorizar para ver este contenido - Por defecto: %s - Siguiente - Introduce la contraseña que se requerirá cuando se inicie la aplicación - Confirmar - La contraseña debe tener al menos 4 caracteres - Puedes guardarlo desde fuentes in línea o importarlo desde un archivo. - Todavía no tienes ningún manga guardado - Encuentra qué leer en el menú lateral. - Lo que leas se mostrará aquí - Está un poco vacío aquí… - Falta un capítulo - Traducir esta aplicación - Traducción - En la cola - Leer más - Copia de seguridad guardada correctamente - Bienvenido/a - Géneros - Intenta reformular la consulta. - ¿Realmente quiere eliminar todas las consultas de búsqueda recientes\? - Terminado - En curso - Este capítulo no aparece en su dispositivo. Descárguelo o léalo en línea. - Autorizado - Por defecto - Algunos fabricantes pueden cambiar el comportamiento del sistema, lo que podría interrumpir las tareas en segundo plano. - No se admite iniciar sesión en %s - Serás desconectado de todas las fuentes - Excluye manga NSFW del historial - Mostrar los números de páginas - Fuentes activadas - Fuentes disponibles - Informática… - Política de capturas de pantalla - Permitir - Bloquear siempre - Sugerencias - Activar sugerencias - Sugiere mangas según tus preferencias - Todos los datos sólo se analizan localmente en este dispositivo y nunca se envían a ninguna parte. - Empieza a leer manga y recibirás sugerencias personalizadas - No sugerir manga NSFW - Activado - Desactivado - No se puede cargar la lista de géneros - Bloqueo en NSFW - Conectado como %s - Encontrar el género - Selecciona los idiomas en los que quieres leer mangas. Puedes cambiarlo más tarde en los ajustes. - Reiniciar el filtro - Nunca - 18+ - Siempre - Precargar las páginas - Sólo en Wi-Fi - Varios idiomas - Buscar capítulo - No hay capítulos en este manga - %1$s%% - Aspecto - Contenido - Actualización de las sugerencias - Excluir géneros - Especifica los géneros que no quieres ver en las sugerencias - Remoción completada - ¿Eliminar elementos seleccionados del dispositivo de forma permanente\? - Ocultar - Ralentización de la descarga - Nuevas fuentes de manga son disponibles - Ayuda a evitar el bloqueo de tu dirección IP - Procesamiento de manga guardado - Comprueba si hay nuevos capítulos y notifica sobre ellos - Recibirás notificaciones sobre las actualizaciones del manga que estés leyendo - Añadir marcador - Marcadores - Deshacer - Marcador eliminado - Eliminado del historial - Eliminar marcador - Añadido a favoritos - DNS mediante HTTPS - Modo predeterminado - Autodetectar modo de lectura - Detecta automáticamente si el manga es un webtoon - Los capítulos se eliminarán en segundo plano - No recibirás notificaciones, pero los nuevos capítulos aparecerán destacados en las listas - Activar las notificaciones - No hay categorías favoritas - Nombre - Editar - Editar categoría - Desactivar todo - Desactivar la optimización de la batería - Enviar - Algo ha ido mal. Por favor, envía un informe de errores a los desarrolladores para ayudarnos a solucionarlo. - Utilizar la huella dactilar si está disponible - Mangas de tus favoritos - Sus mangas recientemente leídos - Cerrar sesión - Planeado - Lectura - Abandonado - En espera - Informar - Seguimiento - Ayuda con las comprobaciones de las actualizaciones en segundo plano - Relectura - Completado - Mostrar indicadores de progreso en la lectura - Eliminación de datos - Mostrar porcentaje de lectura en el historial y en los favoritos - El manga marcado como NSFW nunca se añadirá al historial y no se guardará tu progreso - Puede ayudar en caso de algunos problemas. Todas las autorizaciones serán invalidadas - Mostrar todo - Dominio no válido - Encuentra qué leer en la sección «Explorar» - La cuenta ya existe - Sincronización - Introduce tu correo electrónico para continuar - Últimas 2 horas - Todavía no hay marcadores - Puedes crear marcadores mientras lees el manga - Marcadores eliminados - Habilitar las fuentes de manga para leer manga en línea - Aleatorio - Reordenar - Vacío - Otro caché - Uso del almacenamiento - Disponible - Eliminado de los favoritos - Opciones - Modo incógnito - No hay capítulos - Mostrar la barra de información en el lector - Importando el manga - Importación completada - La importación comenzará pronto - Cancelado - Atrás - Sincronizar tus datos - Tu manga se mostrará aquí - Borrar todo el historial - Sin fuentes de manga - Historial borrado - Gestionar - Pulsa de nuevo «Atrás» para salir - Carpeta con imágenes - ¿Estás seguro de que quieres eliminar las categorías favoritas seleccionadas\? + Dispositivo + Favoritos + Historial + Ocurrió un error + Error en la red + Detalles + Capítulos + Lista + Lista detallada + Cuadrículas + Vista de lista + Ajustes + Fuentes del manga + Cargando… + Capítulo %1$d de %2$d + Cerrar + Reintentar + Borrar historial + No se encontró nada + Aún sin historial + Leer + Aún no hay favoritos + Añadir a favoritos + Nueva categoría + Añadir + Guardar + Compartir + Crear acceso directo… + Compartir %s + Buscar + Buscar manga + Descargando… + Procesando… + Descargado + Descargas + Nombre + Popularidad + Actualización + Recientes + Calificación + Orden de clasificación + Filtrar + Tema + Claro + Oscuro + De acuerdo al sistema + Páginas + Borrar + Borrar todo el historial de lectura de forma permanente\? + Eliminar + «%s» borrado del almacenamiento local + Guardar página + Guardado + Compartir imagen + Importar + Borrar + Esta operación no está admitida + Elija un archivo ZIP o bien un archivo CBZ. + Sin descripción + Borrar caché de página + B|kB|MB|GB|TB + Estándar + Sitio web + Modo de lectura + Tamaño de la cuadrícula + Buscar en %s + Borrar manga + ¿Borrar \"%s\" del dispositivo permanentemente\? + Ajustes del lector + Cambiar de página + Toques de borde + Botones de volumen + Continuar + Error + Borrar la caché de miniaturas + Borrar el historial de búsqueda + Historial de búsqueda borrado + Sólo gestos + Almacenamiento interno + Almacenamiento externo + Dominio + Una nueva versión de la aplicación está disponible + Abrir en navegador web + Este manga tiene %s. ¿Quieres guardarlo todo\? + Guardar + Notificaciones + Activado %1$d de %2$d + Nuevos capítulos + Descargar + Configuración de las notificaciones + Sonido de las notificaciones + Indicador LED + Vibración + Categorías favoritas + Remover + Estante + Reciente + Animación de página + Carpeta para descargas + No disponible + No hay almacenamiento disponible + Otro almacenamiento + Aceptar + Todos los favoritos + Categoría vacía + Leer más tarde + Actualizaciones + Aquí verás los nuevos episodios del manga que estás leyendo + Resultados de la búsqueda + Nueva versión: %s + Tamaño: %s + Borrar actualizaciones + Borrar el feed de actualizaciones + Girar pantalla + Actualizar + La actualización de la alimentación comenzará pronto + Comprueba las actualizaciones del manga + No comprobar + Introducir contraseña + Contraseña incorrecta + Proteger aplicación + Pedir una contraseña al iniciar Kotatsu + Repite la contraseña + Las contraseñas no coinciden + Acerca de + Versión %s + Comprobar actualizaciones + No hay actualizaciones disponibles + De derecha a izquierda + Nueva categoría + Modo de escala + Ajuste al centro + Ajuste a la altura + Ajuste a la anchura + Mantener al iniciar + Tema oscuro auténtico + Útil para pantallas AMOLED + Respaldo y restauración + Crear copia de seguridad de datos + Restaurar desde la copia de seguridad + Datos restaurados + Preparando… + Archivo no encontrado + Todos los datos fueron restaurados con éxito + Los datos fueron restaurados, pero hay errores + Puedes crear una copia de seguridad de tu historial y favoritos para restaurarla + Ahora mismo + Ayer + Hace mucho tiempo + Grupo + Hoy + Toca para volver a intentar + Se recordará la configuración elegida para este manga + Silenciar + El captcha es obligatorio + Resolver + Borrar cookies + Se han eliminado todas las cookies + Limpiar feed + Todo el historial de actualizaciones se borrará y esta acción no se puede deshacer. ¿Está seguro\? + Comprobación de nuevos capítulos + Invertir + Iniciar sesión + Debes autorizar para ver este contenido + Por defecto: %s + Siguiente + Introduce la contraseña que se requerirá cuando se inicie la aplicación + Confirmar + La contraseña debe tener al menos 4 caracteres + Puedes guardarlo desde fuentes in línea o importarlo desde un archivo. + Todavía no tienes ningún manga guardado + Encuentra qué leer en el menú lateral. + Lo que leas se mostrará aquí + Está un poco vacío aquí… + Falta un capítulo + Traducir esta aplicación + Traducción + En la cola + Leer más + Copia de seguridad guardada correctamente + Bienvenido/a + Géneros + Intenta reformular la consulta. + ¿Realmente quiere eliminar todas las consultas de búsqueda recientes\? + Terminado + En curso + Autorizado + Por defecto + Algunos fabricantes pueden cambiar el comportamiento del sistema, lo que podría interrumpir las tareas en segundo plano. + No se admite iniciar sesión en %s + Serás desconectado de todas las fuentes + Excluye manga NSFW del historial + Mostrar los números de páginas + Fuentes activadas + Fuentes disponibles + Informática… + Política de capturas de pantalla + Permitir + Bloquear siempre + Sugerencias + Activar sugerencias + Sugiere mangas según tus preferencias + Todos los datos sólo se analizan localmente en este dispositivo y nunca se envían a ninguna parte. + Empieza a leer manga y recibirás sugerencias personalizadas + No sugerir manga NSFW + Activado + Desactivado + No se puede cargar la lista de géneros + Bloqueo en NSFW + Conectado como %s + Selecciona los idiomas en los que quieres leer mangas. Puedes cambiarlo más tarde en los ajustes. + Reiniciar el filtro + Nunca + 18+ + Siempre + Precargar las páginas + Sólo en Wi-Fi + Varios idiomas + Buscar capítulo + No hay capítulos en este manga + %1$s%% + Aspecto + Actualización de las sugerencias + Excluir géneros + Especifica los géneros que no quieres ver en las sugerencias + Remoción completada + ¿Eliminar elementos seleccionados del dispositivo de forma permanente\? + Ocultar + Ralentización de la descarga + Nuevas fuentes de manga son disponibles + Ayuda a evitar el bloqueo de tu dirección IP + Procesamiento de manga guardado + Comprueba si hay nuevos capítulos y notifica sobre ellos + Recibirás notificaciones sobre las actualizaciones del manga que estés leyendo + Añadir marcador + Marcadores + Deshacer + Marcador eliminado + Eliminado del historial + Eliminar marcador + Añadido a favoritos + DNS mediante HTTPS + Modo predeterminado + Autodetectar modo de lectura + Detecta automáticamente si el manga es un webtoon + Los capítulos se eliminarán en segundo plano + No recibirás notificaciones, pero los nuevos capítulos aparecerán destacados en las listas + Activar las notificaciones + No hay categorías favoritas + Nombre + Editar + Editar categoría + Desactivar todo + Desactivar la optimización de la batería + Enviar + Algo ha ido mal. Por favor, envía un informe de errores a los desarrolladores para ayudarnos a solucionarlo. + Utilizar la huella dactilar si está disponible + Mangas de tus favoritos + Sus mangas recientemente leídos + Cerrar sesión + Planeado + Lectura + Abandonado + En espera + Informar + Seguimiento + Ayuda con las comprobaciones de las actualizaciones en segundo plano + Relectura + Completado + Mostrar indicadores de progreso en la lectura + Eliminación de datos + Mostrar porcentaje de lectura en el historial y en los favoritos + El manga marcado como NSFW nunca se añadirá al historial y no se guardará tu progreso + Puede ayudar en caso de algunos problemas. Todas las autorizaciones serán invalidadas + Mostrar todo + Dominio no válido + Encuentra qué leer en la sección «Explorar» + La cuenta ya existe + Sincronización + Introduce tu correo electrónico para continuar + Últimas 2 horas + Todavía no hay marcadores + Puedes crear marcadores mientras lees el manga + Marcadores eliminados + Habilitar las fuentes de manga para leer manga en línea + Aleatorio + Reordenar + Vacío + Otro caché + Uso del almacenamiento + Disponible + Eliminado de los favoritos + Opciones + Modo incógnito + No hay capítulos + Mostrar la barra de información en el lector + Importando el manga + Importación completada + La importación comenzará pronto + Cancelado + Atrás + Sincronizar tus datos + Tu manga se mostrará aquí + Borrar todo el historial + Sin fuentes de manga + Historial borrado + Gestionar + Pulsa de nuevo «Atrás» para salir + Carpeta con imágenes + ¿Estás seguro de que quieres eliminar las categorías favoritas seleccionadas\? \nTodos los mangas en ella se perderán y esto no se puede deshacer. - Explorar - %s - %s - Pulse dos veces «Atrás» para salir de la aplicación - Confirmación de salida - Caché de páginas - Cap.%1$d/%2$d Pg.%3$d/%4$d - Manga guardado - Desplazamiento automático - Archivo de cómics - Puedes eliminar el archivo original del almacenamiento para ahorrar espacio - Selecciona el rango - Contenido no encontrado o eliminado - Detalles del error:<br><tt>%1$s</tt><br><br>1. Intenta <a href=%2$s>abrir el manga en un navegador web</a> para asegurarte de que esté disponible en tu fuente<br>2. Asegúrete de estar utilizando la <a href=kotatsu://about>última versión de Kotatsu</a><br>3. Si está disponible, envía un informe de error a los desarrolladores. - Hacer que los mangas recientes estén disponibles mediante una pulsación larga en el icono de la aplicación - Los ajustes de color elegidos serán recordados para este manga - Fuente - Mostrar los accesos directos a los mangas recientes - Tocando el borde derecho o pulsando la tecla derecha se pasa siempre a la página siguiente - Control ergonómico del lector - Corrección del color - Brillo - Contraste - Restablecer - ¿Guardar o descartar los cambios no guardados\? - Descartar - Sin espacio en dispositivo - Zoom de webtoon - Mostrar el deslizador de cambio de página - Error del servidor (%1$d). Vuelva a intentarlo más tarde - Información clara sobre los nuevos capítulos - Diferentes idiomas - La red no está disponible - Compacta - Enciende la Wi-Fi o la red móvil para leer los mangas en línea - Fuente desactivada - Precargar el contenido - Marcar como actual - Idioma - Compartir los registros - Grabar algunas acciones para depurar - Activar el registro - Mostrar contenido sospechoso - Dinámico - Esquema de colores - Mostrar en vista de cuadrícula - Asuka - Mion - Rikka - Sakura - Miku - No hay nada aquí - Mamimi - Canadé - Para realizar un seguimiento del progreso de la lectura, seleccione Menú → Seguimiento en la pantalla de detalles del manga. - Servicios - Actualizaciones propuestas para las versiones beta de la aplicación - Permitir actualizaciones inestables - Descarga iniciada - Encabezado del agente de usuario - Por favor, reinicie la aplicación para aplicar estos cambios - Mantén pulsado un elemento para reordenarlos - Puedes seleccionar uno o más archivos .cbz o .zip, cada archivo será reconocido como un manga independiente. - Puedes seleccionar un directorio con unos archivos o imágenes. Cada archivo (o subdirectorio) se reconocerá como un capítulo. - Velocidad - Importar una copia de seguridad de los datos del usuario creada previamente - Mostrar en la estantería - Entendido - Puedes acceder a una cuenta existente o crear una nueva - Buscar similares - Parámetros de sincronización - Dirección del servidor - Ignorar los errores SSL - Elige un espejo automáticamente - Cambio automático de dominios para las fuentes remotas en caso de error si hay réplicas disponibles - Pausar - Reanudar - Eliminación completa - Cancelar todo - Descargar solo por WiFi - Detener la descarga al cambiar a una red móvil - Puedes utilizar un servidor de sincronización propio o uno predeterminado. No cambies esto si no estás seguro de lo que haces. - Pausado - Activar - No, gracias - No tienes descargas - Sugerencia: %s - Algunas veces muestra las notificaciones con el manga sugerido - Las descargas se han reanudado - Más - Todas las descargas activas se cancelarán, los datos descargados parcialmente se perderán - Tu historial de descargas se borrará permanentemente - Se han pausado las descargas - Las descargas se han eliminado - Las descargas se han cancelado - ¿Quieres recibir sugerencias sobre mangas personalizadas\? - Traducciones - WebView no está disponible: comprueba si el proveedor de WebView está instalado - Borrar la caché de la red - Tipo - Dirección - Puerto - Proxy - Valor no válido - %1$s (%2$s) - Optimización de imágenes proxy - Nombre de usuario - Descargado - Autorización (opcional) - Utiliza el servicio wsrv.nl para reducir el uso del tráfico y acelerar la carga de imágenes si es posible - Contraseña - Invertir los colores - \ No newline at end of file + Explorar + %s - %s + Pulse dos veces «Atrás» para salir de la aplicación + Confirmación de salida + Caché de páginas + Cap.%1$d/%2$d Pg.%3$d/%4$d + Manga guardado + Desplazamiento automático + Archivo de cómics + Puedes eliminar el archivo original del almacenamiento para ahorrar espacio + Selecciona el rango + Contenido no encontrado o eliminado + Detalles del error:<br><tt>%1$s</tt><br><br>1. Intenta <a href=%2$s>abrir el manga en un navegador web</a> para asegurarte de que esté disponible en tu fuente<br>2. Asegúrete de estar utilizando la <a href=kotatsu://about>última versión de Kotatsu</a><br>3. Si está disponible, envía un informe de error a los desarrolladores. + Hacer que los mangas recientes estén disponibles mediante una pulsación larga en el icono de la aplicación + Los ajustes de color elegidos serán recordados para este manga + Fuente + Mostrar los accesos directos a los mangas recientes + Tocando el borde derecho o pulsando la tecla derecha se pasa siempre a la página siguiente + Control ergonómico del lector + Corrección del color + Brillo + Contraste + Restablecer + ¿Guardar o descartar los cambios no guardados\? + Descartar + Sin espacio en dispositivo + Zoom de webtoon + Mostrar el deslizador de cambio de página + Error del servidor (%1$d). Vuelva a intentarlo más tarde + Información clara sobre los nuevos capítulos + Diferentes idiomas + La red no está disponible + Compacta + Enciende la Wi-Fi o la red móvil para leer los mangas en línea + Fuente desactivada + Precargar el contenido + Marcar como actual + Idioma + Compartir los registros + Grabar algunas acciones para depurar + Activar el registro + Mostrar contenido sospechoso + Dinámico + Esquema de colores + Mostrar en vista de cuadrícula + Asuka + Mion + Rikka + Sakura + Miku + No hay nada aquí + Mamimi + Canadé + Para realizar un seguimiento del progreso de la lectura, seleccione Menú → Seguimiento en la pantalla de detalles del manga. + Servicios + Actualizaciones propuestas para las versiones beta de la aplicación + Permitir actualizaciones inestables + Descarga iniciada + Encabezado del agente de usuario + Por favor, reinicie la aplicación para aplicar estos cambios + Mantén pulsado un elemento para reordenarlos + Puedes seleccionar uno o más archivos .cbz o .zip, cada archivo será reconocido como un manga independiente. + Puedes seleccionar un directorio con unos archivos o imágenes. Cada archivo (o subdirectorio) se reconocerá como un capítulo. + Velocidad + Importar una copia de seguridad de los datos del usuario creada previamente + Mostrar en la estantería + Entendido + Puedes acceder a una cuenta existente o crear una nueva + Buscar similares + Parámetros de sincronización + Dirección del servidor + Ignorar los errores SSL + Elige un espejo automáticamente + Cambio automático de dominios para las fuentes remotas en caso de error si hay réplicas disponibles + Pausar + Reanudar + Eliminación completa + Cancelar todo + Descargar solo por WiFi + Detener la descarga al cambiar a una red móvil + Puedes utilizar un servidor de sincronización propio o uno predeterminado. No cambies esto si no estás seguro de lo que haces. + Pausado + Activar + No, gracias + No tienes descargas + Sugerencia: %s + Algunas veces muestra las notificaciones con el manga sugerido + Las descargas se han reanudado + Más + Todas las descargas activas se cancelarán, los datos descargados parcialmente se perderán + Tu historial de descargas se borrará permanentemente + Se han pausado las descargas + Las descargas se han eliminado + Las descargas se han cancelado + ¿Quieres recibir sugerencias sobre mangas personalizadas\? + Traducciones + WebView no está disponible: comprueba si el proveedor de WebView está instalado + Borrar la caché de la red + Tipo + Dirección + Puerto + Proxy + Valor no válido + %1$s (%2$s) + Optimización de imágenes proxy + Nombre de usuario + Descargado + Autorización (opcional) + Utiliza el servicio wsrv.nl para reducir el uso del tráfico y acelerar la carga de imágenes si es posible + Contraseña + Invertir los colores + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 5fbd3be45..9bf16d703 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -7,7 +7,6 @@ Käännös Käännä tämä sovellus Luku puuttuu - Tämä luku puuttuu laitteestasi. Lataa tai lue se verkossa. Jonossa Lue lisää Jotkin valmistajat voivat muuttaa järjestelmän käyttäytymistä, mikä voi keskeyttää taustatehtäviä. @@ -125,7 +124,6 @@ Vakio t|kt|Mt|Gt|Tt Tyhjennä sivujen välimuisti - Historia ja välimuisti Ei kuvausta Virheellinen tiedosto. Vain ZIP ja CBZ ovat tuettuja. Tätä toimintoa ei tueta @@ -216,7 +214,6 @@ Aina Ei koskaan Nollaa suodatin - Etsi genre Valitse kielet, joilla haluat lukea mangaa. Voit muuttaa sitä myöhemmin asetuksissa. Kirjautunut sisään nimellä %s 18+ @@ -225,7 +222,6 @@ Eri kieliä Ei lukuja tässä mangassa Ulkonäkö - Sisältö Ehdotukset päivitetään Määritä genret, joita et halua nähdä ehdotuksissa Sulje pois genrejä diff --git a/app/src/main/res/values-fil/plurals.xml b/app/src/main/res/values-fil/plurals.xml index a36324941..92ac9c5dc 100644 --- a/app/src/main/res/values-fil/plurals.xml +++ b/app/src/main/res/values-fil/plurals.xml @@ -4,10 +4,6 @@ %1$d aytem %1$d (na) aytem - - "Kabuuang %1$d pahina" - Kabuuang %1$d (na) pahina - %1$d minutong nakakalipas %1$d (na) minutong nakakalipas diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 75a3e1d2f..c139be816 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -1,415 +1,411 @@ - Na-update - Pinakabago - Maliwanag - Marka - Pansala - Tema - Madilim - Sundan ang sistema - May nangyaring error - Error sa network - Mga detalye - Mga kabanata - Listahan - Na-save - I-share ang larawan - Mag-angkat - Tanggalin - Hindi suportado ang operasyong ito - Pumili ng ZIP o CBZ file. - Kasaysayan at cache - Walang paglalarawan - Laki ng grid - Hanapin sa %s - Tanggalin ang manga - Permanenteng tanggalin ang \"%s\" sa device\? - Mga setting sa pagbasa - Magpalit ng (mga) pahina - Pindutan ng volume - Magpatuloy - I-clear ang cache ng mga thumbnail - Na-clear - Mga kilos lang - Available ang isang bagong bersyon ng app - Buksan sa web browser - Ang manga na ito ay may %s. I-save ang lahat ng ito\? - Mga abiso - %1$d ng %2$d sa - Mga bagong kabanata - Subukang i-reformulate ang query. - Ang iyong nabasa ay ipapakita dito - Ang iyong manga ay ipapakita dito - Mag-save muna ng isang bagay - I-save ito mula sa mga online na source o mag import ng mga file. - Istante - Animasyon ng pahina - Hindi magagamit - Walang available na storage - Iba pang storage - Tapos na - Lahat ng paborito - Walang laman ang kategorya - Basahin mamaya - Mga update - Mga resulta ng paghahanap - Laki: %s - I-clear ang feed ng mga update - Na-clear - Update - Ang pag update ng feed ay magsisimula sa lalong madaling panahon - Maghanap ng mga update - Ilagay ang password - Humingi ng password kapag sinimulan ang Kotatsu - Tungkol rito - Maghanap ng update - Kanan sa kaliwa - Bagong Kategorya - Pagkasyahin sa gitna - Panatilihin sa simula - Gumagamit ng mas kaunting power sa mga AMOLED na screen - I-backup at i-restore - Naibalik na - Naghahanda… - Hindi nahanap ang file - Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito - Ngayon lang - Kahapon - Matagal na ang nakalipas - Ngayong araw - I-tap para subukang muli - Lutasin - Inalis ang lahat ng mga cookie - I-clear ang feed - Suriin ang mga bagong kabanata - Mag-sign in - Mag-sign in upang tingnan ang nilalamang ito - Default: %s - Susunod - Kumpirmahin - Ang password ay dapat na 4 na character o higit pa - Maligayang pagdating - Na-save ang backup - Magbasa pa - Kulang ang kabanata - Ang pag-log in sa %s ay hindi suportado - Mga genre - Patuloy - Default - Hindi isali ang NSFW manga mula sa kasaysayan - Mga pahinang may bilang - Patakaran sa screenshot - Payagan - Palaging i-block - Mga mungkahi - Paganahin ang mga mungkahi - Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi - Huwag magmungkahi ng NSFW manga - Pinagana - Maghanap ng genre - Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. - Lokal na storage - Mga paborito - Kasaysayan - Mode na listahan - Detalyadong listahan - Grid - Mga setting - Mga source ng Manga - Naglo-load… - Isara - Walang nahanap - Tanggalin - Bagong Kategorya - Nabasa - Wala pang paborito - I-paborito ito - Idagdag - I-save - Ibahagi - Lumikha ng shortcut… - Ibahagi sa %s - Maghanap - Maghanap ng manga - Nagda-download… - Nagpoproseso… - Na-download - Mga download - Pangalan - Sikat - Mga pahina - I-clear ang kasaysayan - I-clear ang kasaysayan ng paghahanap - Bagong bersyon: %s - Hindi tumutugma sa mga password - I-clear ang mga cookie - I-clear ang page cache - I-save - I-download - Mga setting ng abiso - Tunog ng abiso - Mga paboritong kategorya - Tanggalin - Parang walang laman dito… - Hanapin kung ano ang babasahin sa side menu. - Hanapin kung ano ang babasahin sa seksyong «Mag-explore» - Kamakailan - Folder para sa mga download - I-save ang pahina - Natanggal ang \"%s\" sa lokal na storage - Wala pang kasaysayan - Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? - Huwag suriin - Ulitin ang password - Protektahan ang app - Maling password - Bersyon %s - Mode ng scale - Walang available na update - Baliktarin - Grupo - Tahimik - Pagkasyahin sa lapad - Itim - Lumikha ng data backup - Ibalik mula sa backup - Naibalik ang lahat ng data - Ang data ay naibalik, ngunit may mga error - Ang napiling pagsasaayos ay maaalala para sa manga na ito - Isalin ang app na ito - Awtorisado na - Kinakailangan ang CAPTCHA - I-clear nang permanente ang lahat ng update history\? - Maglagay ng password para simulan ang app - Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. - Nakapila na - I-download o basahin ang nawawalang kabanata online. - Mala-log out ka mula sa lahat ng source - Tapos na - Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? - Pagsasalin - I-block sa NSFW - Magmungkahi ng manga batay sa iyong mga kagustuhan - Ang lahat ng data ay lokal lamang na sinusuri sa device na ito at hindi kailanman ipinadala kahit saan. - Hindi pinagana - Hindi ma-load ang listahan ng mga genre - I-reset ang filter - Ang mga bagong kabanata ng iyong binabasa ay makikita dito - I-rotate ang screen - Pagkasyahin sa tangkad - Hindi kailanman - Sa Wi-Fi lang - Nagco-compute… - Kabanata %1$d ng %2$d - Subukan ulit - Pag-aayos ng order - I-clear - Mga taps ng gilid - Mga ginamit na source - Magagamit na mga source - Lagi na lang - I-preload ang mga pahina - Naka-log in bilang %s - Iba\'t ibang wika - Maghanap ng kabanata - %1$s%% - Hitsura - Hindi isali ang mga genre - Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi - Nakumpleto na ang pagtanggal - Tumutulong na maiwasan ang pag-block ng iyong IP address - Naka-save na pagproseso ng manga - Mayroon nang account - Bumalik - Pag-synchronize - Ilagay ang iyong email upang magpatuloy - Itago - May mga bagong source ng manga - Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan - Paganahin ang mga abiso - Ayusin ang kategorya - Tina-track - Walang mga paboritong kategorya - Mag-log out - Magdagdag ng bookmark - Tinanggal ang bookmark - Inalis sa kasaysayan - DNS sa HTTPS - Default na mode - Automatikong matukoy ang reader mode - May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. - Ipadala - Muling pagbabasa - Binitawan - Manga mula sa iyong mga paborito - Ang iyong kamakailang nabasa na manga - Pagtanggal ng data - Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito - Ipakita lahat - Pumili ng saklaw - I-clear ang lahat ng kasaysayan - Maaari kang lumikha ng bookmark habang nagbabasa ng manga - Tinanggal ang mga bookmark - Random - Walang mga source ng manga - Paganahin ang mga source ng manga upang basahin ang manga online - Ayusin muli - Walang laman - Pindutin muli ang Bumalik upang lumabas - Pindutin ang Bumalik nang dalawang beses upang lumabas sa app - Pagkumpirma ng paglabas - Na-save na manga - Mag-Explore - Iba pang cache - Paggamit ng storage - Magagamit na - %s - %s - Inalis sa mga paborito - Mga pagpipilian - Incognito mode - Walang mga kabanata - Awtomatikong pag-scroll - Ch. %1$d/%2$d Pg. %3$d/%4$d - Ipakita ang information bar sa pagbasa - Archive ng mga comics - Folder na may mga larawan - Nakumpleto na ang pag-import - Magsisimula na ang pag-import - Feed - Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application - Ipakita ang mga kamakailang manga shortcut - Ergonomic na kontrol sa mambabasa - Pagwawasto ng kulay - Liwanag - Kaibahan - I-save o kalimutan ang mga hindi na-save na pagbabago\? - Kalimutan - Walang natitirang espasyo sa device - Pag-zoom sa webtoon - Iba\'t ibang wika - Server side error (%1$d). Subukang muli mamaya - I-clear din ang impormasyon tungkol sa mga bagong kabanata - Preloading ng nilalaman - Markahan bilang kasalukuyan - Wika - Ibahagi ang mga log - Magpakita ng kahina-hinalang nilalaman - Dynamic - Ipakita sa grid view - Asuka - Mion - Rikka - Sakura - Mamimi - Kanade - Wala naman dito - Mga serbisyo - Payagan ang mga hindi stable na update - Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa - Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save - Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa - Imbalidong domain - Huling 2 oras - Nabura ang kasaysayan - Pamahalaan - Wala pang bookmark - 18+ - Hindi natagpuan o inalis ang nilalaman - Magtala ng ilang pagkilos para sa mga layunin ng pag-debug - Permanenteng tanggalin ang mga napiling item sa device\? - Walang mga kabanata sa manga na ito - Nag-a-update ang mga mungkahi - Nilalaman - Pagbagal ng pag-download - Tatanggalin ang mga kabanata sa background - Kinansela - I-sync ang iyong data - Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito - Pangalan - I-edit - Tanggalin ang bookmark - Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa - Mag-undo - Nagbabasa - Cache ng mga pahina - Mga bookmark - Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? + Na-update + Pinakabago + Maliwanag + Marka + Pansala + Tema + Madilim + Sundan ang sistema + May nangyaring error + Error sa network + Mga detalye + Mga kabanata + Listahan + Na-save + I-share ang larawan + Mag-angkat + Tanggalin + Hindi suportado ang operasyong ito + Pumili ng ZIP o CBZ file. + Walang paglalarawan + Laki ng grid + Hanapin sa %s + Tanggalin ang manga + Permanenteng tanggalin ang \"%s\" sa device\? + Mga setting sa pagbasa + Magpalit ng (mga) pahina + Pindutan ng volume + Magpatuloy + I-clear ang cache ng mga thumbnail + Na-clear + Mga kilos lang + Available ang isang bagong bersyon ng app + Buksan sa web browser + Ang manga na ito ay may %s. I-save ang lahat ng ito\? + Mga abiso + %1$d ng %2$d sa + Mga bagong kabanata + Subukang i-reformulate ang query. + Ang iyong nabasa ay ipapakita dito + Ang iyong manga ay ipapakita dito + Mag-save muna ng isang bagay + I-save ito mula sa mga online na source o mag import ng mga file. + Istante + Animasyon ng pahina + Hindi magagamit + Walang available na storage + Iba pang storage + Tapos na + Lahat ng paborito + Walang laman ang kategorya + Basahin mamaya + Mga update + Mga resulta ng paghahanap + Laki: %s + I-clear ang feed ng mga update + Na-clear + Update + Ang pag update ng feed ay magsisimula sa lalong madaling panahon + Maghanap ng mga update + Ilagay ang password + Humingi ng password kapag sinimulan ang Kotatsu + Tungkol rito + Maghanap ng update + Kanan sa kaliwa + Bagong Kategorya + Pagkasyahin sa gitna + Panatilihin sa simula + Gumagamit ng mas kaunting power sa mga AMOLED na screen + I-backup at i-restore + Naibalik na + Naghahanda… + Hindi nahanap ang file + Maaari kang lumikha ng backup ng iyong kasaysayan at mga paborito at ibalik ito + Ngayon lang + Kahapon + Matagal na ang nakalipas + Ngayong araw + I-tap para subukang muli + Lutasin + Inalis ang lahat ng mga cookie + I-clear ang feed + Suriin ang mga bagong kabanata + Mag-sign in + Mag-sign in upang tingnan ang nilalamang ito + Default: %s + Susunod + Kumpirmahin + Ang password ay dapat na 4 na character o higit pa + Maligayang pagdating + Na-save ang backup + Magbasa pa + Kulang ang kabanata + Ang pag-log in sa %s ay hindi suportado + Mga genre + Patuloy + Default + Hindi isali ang NSFW manga mula sa kasaysayan + Mga pahinang may bilang + Patakaran sa screenshot + Payagan + Palaging i-block + Mga mungkahi + Paganahin ang mga mungkahi + Simulan ang pagbabasa ng manga at makakakuha ka ng mga personalized na mungkahi + Huwag magmungkahi ng NSFW manga + Pinagana + Pumili ng mga wika na gusto mong basahin ang manga. Maaari mo itong baguhin sa ibang pagkakataon sa mga setting. + Lokal na storage + Mga paborito + Kasaysayan + Mode na listahan + Detalyadong listahan + Grid + Mga setting + Mga source ng Manga + Naglo-load… + Isara + Walang nahanap + Tanggalin + Bagong Kategorya + Nabasa + Wala pang paborito + I-paborito ito + Idagdag + I-save + Ibahagi + Lumikha ng shortcut… + Ibahagi sa %s + Maghanap + Maghanap ng manga + Nagda-download… + Nagpoproseso… + Na-download + Mga download + Pangalan + Sikat + Mga pahina + I-clear ang kasaysayan + I-clear ang kasaysayan ng paghahanap + Bagong bersyon: %s + Hindi tumutugma sa mga password + I-clear ang mga cookie + I-clear ang page cache + I-save + I-download + Mga setting ng abiso + Tunog ng abiso + Mga paboritong kategorya + Tanggalin + Parang walang laman dito… + Hanapin kung ano ang babasahin sa side menu. + Hanapin kung ano ang babasahin sa seksyong «Mag-explore» + Kamakailan + Folder para sa mga download + I-save ang pahina + Natanggal ang \"%s\" sa lokal na storage + Wala pang kasaysayan + Permanenteng i-clear ang lahat ng kasaysayan ng pagbabasa\? + Huwag suriin + Ulitin ang password + Protektahan ang app + Maling password + Bersyon %s + Mode ng scale + Walang available na update + Baliktarin + Grupo + Tahimik + Pagkasyahin sa lapad + Itim + Lumikha ng data backup + Ibalik mula sa backup + Naibalik ang lahat ng data + Ang data ay naibalik, ngunit may mga error + Ang napiling pagsasaayos ay maaalala para sa manga na ito + Isalin ang app na ito + Awtorisado na + Kinakailangan ang CAPTCHA + I-clear nang permanente ang lahat ng update history\? + Maglagay ng password para simulan ang app + Ang ilang device ay may iba\'t ibang gawi ng system, na maaaring masira ang mga gawain sa background. + Nakapila na + Mala-log out ka mula sa lahat ng source + Tapos na + Alisin ang lahat ng kamakailang query sa paghahanap nang permanente\? + Pagsasalin + I-block sa NSFW + Magmungkahi ng manga batay sa iyong mga kagustuhan + Ang lahat ng data ay lokal lamang na sinusuri sa device na ito at hindi kailanman ipinadala kahit saan. + Hindi pinagana + Hindi ma-load ang listahan ng mga genre + I-reset ang filter + Ang mga bagong kabanata ng iyong binabasa ay makikita dito + I-rotate ang screen + Pagkasyahin sa tangkad + Hindi kailanman + Sa Wi-Fi lang + Nagco-compute… + Kabanata %1$d ng %2$d + Subukan ulit + Pag-aayos ng order + I-clear + Mga taps ng gilid + Mga ginamit na source + Magagamit na mga source + Lagi na lang + I-preload ang mga pahina + Naka-log in bilang %s + Iba\'t ibang wika + Maghanap ng kabanata + %1$s%% + Hitsura + Hindi isali ang mga genre + Tukuyin ang mga genre na hindi mo nais na makita sa mga mungkahi + Nakumpleto na ang pagtanggal + Tumutulong na maiwasan ang pag-block ng iyong IP address + Naka-save na pagproseso ng manga + Mayroon nang account + Bumalik + Pag-synchronize + Ilagay ang iyong email upang magpatuloy + Itago + May mga bagong source ng manga + Hindi ka makakatanggap ng mga abiso ngunit ang mga bagong kabanata ay iha-highlight sa mga listahan + Paganahin ang mga abiso + Ayusin ang kategorya + Tina-track + Walang mga paboritong kategorya + Mag-log out + Magdagdag ng bookmark + Tinanggal ang bookmark + Inalis sa kasaysayan + DNS sa HTTPS + Default na mode + Automatikong matukoy ang reader mode + May nangyaring mali. Mangyaring magsumite ng isang bug report sa mga developer upang matulungan kaming ayusin ito. + Ipadala + Muling pagbabasa + Binitawan + Manga mula sa iyong mga paborito + Ang iyong kamakailang nabasa na manga + Pagtanggal ng data + Ipakita ang porsyento na nabasa sa kasaysayan at mga paborito + Ipakita lahat + Pumili ng saklaw + I-clear ang lahat ng kasaysayan + Maaari kang lumikha ng bookmark habang nagbabasa ng manga + Tinanggal ang mga bookmark + Random + Walang mga source ng manga + Paganahin ang mga source ng manga upang basahin ang manga online + Ayusin muli + Walang laman + Pindutin muli ang Bumalik upang lumabas + Pindutin ang Bumalik nang dalawang beses upang lumabas sa app + Pagkumpirma ng paglabas + Na-save na manga + Mag-Explore + Iba pang cache + Paggamit ng storage + Magagamit na + %s - %s + Inalis sa mga paborito + Mga pagpipilian + Incognito mode + Walang mga kabanata + Awtomatikong pag-scroll + Ch. %1$d/%2$d Pg. %3$d/%4$d + Ipakita ang information bar sa pagbasa + Archive ng mga comics + Folder na may mga larawan + Nakumpleto na ang pag-import + Magsisimula na ang pag-import + Feed + Gawing magagamit ang kamakailang manga sa pamamagitan ng mahabang pagpindot sa icon ng application + Ipakita ang mga kamakailang manga shortcut + Ergonomic na kontrol sa mambabasa + Pagwawasto ng kulay + Liwanag + Kaibahan + I-save o kalimutan ang mga hindi na-save na pagbabago\? + Kalimutan + Walang natitirang espasyo sa device + Pag-zoom sa webtoon + Iba\'t ibang wika + Server side error (%1$d). Subukang muli mamaya + I-clear din ang impormasyon tungkol sa mga bagong kabanata + Preloading ng nilalaman + Markahan bilang kasalukuyan + Wika + Ibahagi ang mga log + Magpakita ng kahina-hinalang nilalaman + Dynamic + Ipakita sa grid view + Asuka + Mion + Rikka + Sakura + Mamimi + Kanade + Wala naman dito + Mga serbisyo + Payagan ang mga hindi stable na update + Ipakita ang mga tagapagpahiwatig ng progress ng pagbabasa + Manga na minarkahan bilang NSFW ay hindi kailanman idadagdag sa kasaysayan at ang iyong progress ay hindi mase-save + Maaaring makatulong sa kaso ng ilang mga isyu. Ang lahat ng pahintulot ay mawawalan ng bisa + Imbalidong domain + Huling 2 oras + Nabura ang kasaysayan + Pamahalaan + Wala pang bookmark + 18+ + Hindi natagpuan o inalis ang nilalaman + Magtala ng ilang pagkilos para sa mga layunin ng pag-debug + Permanenteng tanggalin ang mga napiling item sa device\? + Walang mga kabanata sa manga na ito + Nag-a-update ang mga mungkahi + Pagbagal ng pag-download + Tatanggalin ang mga kabanata sa background + Kinansela + I-sync ang iyong data + Tingnan ang mga bagong kabanata at ipaalam ang tungkol dito + Pangalan + I-edit + Tanggalin ang bookmark + Makakatanggap ka ng mga abiso tungkol sa mga update ng manga na iyong binabasa + Mag-undo + Nagbabasa + Cache ng mga pahina + Mga bookmark + Sigurado ka bang gusto mong tanggalin ang mga napiling paboritong kategorya\? \nAng lahat ng manga sa loob nito ay mawawala at hindi na ito mababawi. - Idinagdag ang bookmark - Awtomatikong matukoy kung ang manga ay webtoon - Huwag paganahin ang pag-optimize ng baterya - Tumutulong sa mga pagsusuri sa mga update sa background - Nakaplano - Nakumpleto na - Naka-hold - Huwag paganahin ang lahat - Gumamit ng fingerprint kung magagamit - Ulat - I-reset - Magmungkahi ng mga update sa mga beta na bersyon ng app - Hindi magagamit ang network - I-on ang Wi-Fi o mobile network para magbasa ng manga online - Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina - Ipakita ang slider ng paglipat ng pahina - Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>magbukas ng manga sa isang web browser</a> upang matiyak na available ito sa souce<br>2. Tiyaking ginagamit mo ang <a href=kotatsu://about>pinakabagong bersyon ng Kotatsu</a><br>3. Kung available ito, magpadala ng ulat ng error sa mga developer. - Paganahin ang pag-log - Hindi pinagana ang source - Pag-import ng manga - Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo - Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito - Compact - Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. - Nagsimula na ang pag-download - Scheme ng kulay - Miku - Header ng UserAgent - B|kB|MB|GB|TB - Standard - Webtoon - Read mode - Error - Internal storage - External storage - Vibration - Domain - LED indicator - Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito - Nakuha ko - I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito - Mag-import ng dating ginawa na backup ng data ng user - Ipakita sa Istante - Bilis - Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. - Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. - Maghanap ng katulad - Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago - Mga pagsasalin - Hindi available ang WebView: tingnan kung naka-install ang WebView provider - Paganahin - Na-pause ang mga pag-download - Mga setting ng pag-synchronize - Address ng server - Maaari kang gumamit ng self-hosted synchronization server o isang default. Huwag baguhin ito kung hindi ka sigurado sa iyong ginagawa. - Huwag pansinin ang mga error sa SSL - Awtomatikong pumili ng mirror - Awtomatikong lumipat ng mga domain para sa mga remote source sa mga error kung available ang mga mirror - Kanselahin lahat - Mag-download lamang sa pamamagitan ng Wi-Fi - Itigil ang pag-download kapag lumipat sa isang mobile network - Naka-pause - Tanggalin ang nakumpleto na - Mga mungkahi: %s - I-pause - Minsang magpakita ng mga notification na may iminungkahing manga - Higit pa - Salamat nalang - Ipagpatuloy - Ang lahat ng mga aktibong pag download ay kakanselahin, bahagyang na download na data ay mawawala - Permanenteng ide-delete ang iyong history ng mga pag-download - Wala kang anumang mga pag-download - Ipinagpatuloy ang mga pag-download - Gusto mo bang makatanggap ng personalized na mga mungkahi sa manga\? - Inalis na ang mga download - Nakansela ang mga pag-download - \ No newline at end of file + Idinagdag ang bookmark + Awtomatikong matukoy kung ang manga ay webtoon + Huwag paganahin ang pag-optimize ng baterya + Tumutulong sa mga pagsusuri sa mga update sa background + Nakaplano + Nakumpleto na + Naka-hold + Huwag paganahin ang lahat + Gumamit ng fingerprint kung magagamit + Ulat + I-reset + Magmungkahi ng mga update sa mga beta na bersyon ng app + Hindi magagamit ang network + I-on ang Wi-Fi o mobile network para magbasa ng manga online + Mag-tap sa kanang gilid o ang pagpindot sa kanang key ay palaging lilipat sa susunod na pahina + Ipakita ang slider ng paglipat ng pahina + Mga detalye ng error:<br><tt>%1$s</tt><br><br>1. Subukang <a href=%2$s>magbukas ng manga sa isang web browser</a> upang matiyak na available ito sa souce<br>2. Tiyaking ginagamit mo ang <a href=kotatsu://about>pinakabagong bersyon ng Kotatsu</a><br>3. Kung available ito, magpadala ng ulat ng error sa mga developer. + Paganahin ang pag-log + Hindi pinagana ang source + Pag-import ng manga + Maaari mong tanggalin ang orihinal na file mula sa storage upang makatipid ng espasyo + Ang napiling mga setting ng kulay ay matatandaan para sa manga na ito + Compact + Upang subaybayan ang pag unlad ng pagbabasa, piliin ang Menu → Track sa screen ng mga detalye ng manga. + Nagsimula na ang pag-download + Scheme ng kulay + Miku + Header ng UserAgent + B|kB|MB|GB|TB + Standard + Webtoon + Read mode + Error + Internal storage + External storage + Vibration + Domain + LED indicator + Mangyaring i-restart ang application upang ilapat ang mga pagbabagong ito + Nakuha ko + I-tap at hawakan ang isang aytem upang muling ayusin ang mga ito + Mag-import ng dating ginawa na backup ng data ng user + Ipakita sa Istante + Bilis + Maaari kang pumili ng isa o higit pang .cbz o .zip file, ang bawat file ay makikilala bilang isang hiwalay na manga. + Maaari kang pumili ng isang directory na may mga archive o mga larawan. Ang bawat archive (o subdirectory) ay makikilala bilang isang kabanata. + Maghanap ng katulad + Maaari kang mag-sign in sa isang umiiral na account o lumikha ng bago + Mga pagsasalin + Hindi available ang WebView: tingnan kung naka-install ang WebView provider + Paganahin + Na-pause ang mga pag-download + Mga setting ng pag-synchronize + Address ng server + Maaari kang gumamit ng self-hosted synchronization server o isang default. Huwag baguhin ito kung hindi ka sigurado sa iyong ginagawa. + Huwag pansinin ang mga error sa SSL + Awtomatikong pumili ng mirror + Awtomatikong lumipat ng mga domain para sa mga remote source sa mga error kung available ang mga mirror + Kanselahin lahat + Mag-download lamang sa pamamagitan ng Wi-Fi + Itigil ang pag-download kapag lumipat sa isang mobile network + Naka-pause + Tanggalin ang nakumpleto na + Mga mungkahi: %s + I-pause + Minsang magpakita ng mga notification na may iminungkahing manga + Higit pa + Salamat nalang + Ipagpatuloy + Ang lahat ng mga aktibong pag download ay kakanselahin, bahagyang na download na data ay mawawala + Permanenteng ide-delete ang iyong history ng mga pag-download + Wala kang anumang mga pag-download + Ipinagpatuloy ang mga pag-download + Gusto mo bang makatanggap ng personalized na mga mungkahi sa manga\? + Inalis na ang mga download + Nakansela ang mga pag-download + diff --git a/app/src/main/res/values-fr/plurals.xml b/app/src/main/res/values-fr/plurals.xml index c0da2ac13..a7bf3bfc0 100644 --- a/app/src/main/res/values-fr/plurals.xml +++ b/app/src/main/res/values-fr/plurals.xml @@ -1,38 +1,33 @@ - - Il y a %1$d minute - Il y a %1$d minutes - Il y a %1$d minutes - - - %1$d page au total - %1$d pages au total - %1$d pages au total - - - %1$d élément - %1$d éléments - %1$d éléments - - - %1$d nouveau chapitre - %1$d nouveaux chapitres - %1$d nouveaux chapitres - - - %1$d chapitre - %1$d chapitres - %1$d chapitres - - - Il y a %1$d heure - Il y a %1$d heures - Il y a %1$d heures - - - Il y a %1$d jour - Il y a %1$d jours - Il y a %1$d jours - - \ No newline at end of file + + Il y a %1$d minute + Il y a %1$d minutes + Il y a %1$d minutes + + + %1$d élément + %1$d éléments + %1$d éléments + + + %1$d nouveau chapitre + %1$d nouveaux chapitres + %1$d nouveaux chapitres + + + %1$d chapitre + %1$d chapitres + %1$d chapitres + + + Il y a %1$d heure + Il y a %1$d heures + Il y a %1$d heures + + + Il y a %1$d jour + Il y a %1$d jours + Il y a %1$d jours + + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 04f0ee800..cfe28f185 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,429 +1,425 @@ - Lire la suite - Certains appareils ont un comportement différent du système, ce qui peut interrompre les tâches d\'arrière-plan. - Sauvegarde enregistrée - Bienvenue - Supprimer définitivement toutes les requêtes de recherche récentes \? - Le mot de passe doit comporter 4 caractères ou plus - Confirmer - Entrez un mot de passe pour démarrer l\'application avec - Suivant - Par défaut : %s - Connectez-vous pour voir ce contenu - Se connecter - Inverser - À la recherche de nouveaux chapitres - Effacer définitivement l\'historique des mises à jour \? - Effacer le flux - Tous les cookies ont été retirés - Effacer les cookies - Résoudre - CAPTCHA requis - Silencieux - On se souviendra de la configuration choisie pour ce manga - Appuyez pour réessayer - Aujourd\'hui - Groupe - Il y a longtemps - Hier - À l\'instant - Vous pouvez créer une sauvegarde de votre historique et de vos favoris et la restaurer - Les données ont été restaurées, mais il y a des erreurs - Toutes les données ont été restaurées - Fichier introuvable - Préparation… - Restauré - Restaurer à partir d\'une sauvegarde - Créer une sauvegarde des données - Sauvegarde et restauration - Utilise moins d\'énergie pour les écrans AMOLED - Noir - Garder au début - Ajuster à la largeur - Ajuster à la hauteur - Ajuster au centre - Mode mise à l\'échelle - Nouvelle catégorie - De droite à gauche - Aucune mise à jour disponible - Vérifier les mises à jour - Version %s - À propos - Les mots de passe ne correspondent pas - Répéter le mot de passe - Demander le mot de passe au démarrage de Kotatsu - Protéger l\'application - Mot de passe erroné - Entrez le mot de passe - Ne pas vérifier - Rechercher les mises à jour - La mise à jour des flux commencera bientôt - Mettre à Jour - Faire pivoter l\'écran - Effacé - Effacer le flux des mises à jour - Taille : %s - Nouvelle version : %s - Résultats de la recherche - Les nouveaux chapitres de ce que vous lisez sont présentés ici - Mises à jour - Lire plus tard - Catégorie vide - Tous les favoris - Terminé - Autre stockage - Pas de stockage disponible - Non disponible - Dossier pour les téléchargements - Animation de page - Récents - Étagère - Enregistrez-le à partir de sources en ligne ou importez des fichiers. - Sauvegardez d\'abord quelque chose - Trouvez ce que vous voulez lire dans le menu latéral. - Ce que vous lisez sera affiché ici - Essayez de reformuler la requête. - C\'est un peu vide ici… - Retirer - Catégories favorites - Vibration - Indicateur lumineux - Son de notification - Paramètres des notifications - Télécharger - Nouveaux chapitres - %1$d de %2$d activé(s) - Notifications - Ce manga a %s. Tout sauvegarder \? - Enregistrer - Ouvrir dans le navigateur - Une nouvelle version de l\'application est disponible - Domaine - Stockage externe - Stockage interne - Gestes uniquement - Effacé - Effacer l\'historique de recherche - Vider le cache des miniatures - Erreur - Continuer - Boutons de volume - Appuis au bord - Changer de pages - Paramètres du lecteur - Supprimer « %s » de l\'appareil de façon permanente \? - Supprimer le manga - Rechercher sur %s - Taille de la grille - Mode lecture - Webtoon - Standard - o|ko|Mo|Go|To - Vider le cache de la page - Historique et cache - Aucune description - Choisissez un fichier ZIP ou CBZ. - Cette opération n\'est pas prise en charge - Supprimer - Importer - Partager l\'image - Sauvegardé - Sauvegarder la page - « %s » supprimé du stockage local - Retirer - Effacer définitivement l\'historique de lecture \? - Effacer - Pages - Suivre le système - Sombre - Clair - Thème - Filtre - Ordre de tri - Évaluation - Le plus récent - Mis à jour - Populaire - Nom - Téléchargements - Téléchargé - Traitement… - Téléchargement… - Rechercher un manga - Rechercher - Partager %s - Créer un raccourci… - Partager - Enregistrer - Ajouter - Nouvelle catégorie - Ajouter aux favoris - Aucun favori pour le moment - Lire - Pas encore d\'historique - Rien n\'a été trouvé - Effacer l\'historique - Réessayer - Fermer - Chapitre %1$d sur %2$d - Chargement… - Sources des mangas - Paramètres - Mode liste - Grille - Liste détaillée - Liste - Chapitres - Détails - Erreur réseau - Une erreur s\'est produite - Historique - Favoris - Stockage local - Le chapitre est manquant - Téléchargez ou lisez ce chapitre manquant en ligne. - En file d\'attente - Traduction - Traduire cette application - Genres - Vous serez déconnecté de toutes les sources - La connexion sur %s n\'est pas prise en charge - Autorisé - Terminé - En cours - Par défaut - Exclure les mangas osés de l\'historique - Pages numérotées - Sources utilisées - Sources disponibles - Calcul… - Bloquer pour contenu sensible - Toujours bloquer - Politique relative aux captures d\'écran - Autoriser - Suggestions - Ne pas suggérer de mangas osés - Activer les suggestions - Suggérer des mangas en fonction de vos préférences - Toutes les données sont analysées localement sur cet appareil et ne sont jamais envoyées ailleurs. - Commencez à lire des mangas et vous recevrez des suggestions personnalisées - Impossible de charger la liste des genres - Activé - Désactivé - Uniquement en Wi-Fi - Toujours - Précharger les pages - Trouver le genre - Jamais - Réinitialiser le filtre - Sélectionnez les langues dans lesquelles vous souhaitez lire les mangas. Vous pouvez le changer plus tard dans les paramètres. - Connecté en tant que %s - 18+ - Langues diverses - Trouver un chapitre - Pas de chapitres dans ce manga - %1$s%% - Apparence - Contenu - Mise à jour des suggestions - Exclure des genres - Spécifiez les genres que vous ne voulez pas voir apparaître dans les suggestions - Supprimer définitivement les éléments sélectionnés de l\'appareil \? - Suppression terminée - Ralentissement du téléchargement - Permet d\'éviter le blocage de votre adresse IP - Les chapitres seront supprimés en arrière-plan - Traitement des mangas sauvegardés - Masquer - De nouvelles sources de mangas sont disponibles - Vérifier les nouveaux chapitres et les notifier - Activer les notifications - Vous recevrez des notifications sur les mises à jour des mangas que vous lisez - Vous ne recevrez pas de notifications mais les nouveaux chapitres seront mis en évidence dans les listes - Pas de catégories préférées - Nom - Modifier - Modifier la catégorie - Ajouter un marque-page - Retirer le marque-page - Marque-pages - Marque-page ajouté - Marque-page retiré - Annuler - Retiré de l\'historique - DNS sur HTTPS - Mode par défaut - Mode de détection automatique du lecteur - Détecter automatiquement si un manga est un webtoon - Désactiver l\'optimisation de la batterie - Aide à la vérification des mises à jour des antécédents - Un problème est survenu. Veuillez soumettre un rapport de bogue aux développeurs pour nous aider à le corriger. - Envoyer - Tout désactiver - Utiliser l\'empreinte digitale si elle est disponible - Vos mangas récemment lus - Les mangas de vos favoris - Signaler - Suivi - Planifié - Lecture - Afficher les indicateurs de progression de lecture - Afficher le pourcentage de lecture dans l\'historique et les favoris - Les mangas marqués comme étant pour adultes ne seront jamais ajoutés à l\'historique et votre progression ne sera pas sauvegardée - Peut aider en cas de problème. Toutes les autorisations seront invalidées - Tout afficher - En attente - Abandonné - Suppression des données - Se déconnecter - Terminé - Relecture - Domaine invalide - Sélectionner une plage - Contenu non trouvé ou supprimé - Détails de l\'erreur:<br><tt>%1$s</tt><br><br>1. Essayez d\'<a href=%2$s>ouvrir le manga dans un navigateur web</a> pour vous assurer qu\'il est disponible sur sa source<br>2. Assurez-vous que vous utilisez la <a href=kotatsu://about>dernière version de Kotatsu</a><br>3. Si elle est disponible, envoyez un rapport d\'erreur aux développeurs. - Rappuyez sur Retour pour quitter - Êtes-vous sûr·e de vouloir supprimer les catégories de favoris sélectionnées \? + Lire la suite + Certains appareils ont un comportement différent du système, ce qui peut interrompre les tâches d\'arrière-plan. + Sauvegarde enregistrée + Bienvenue + Supprimer définitivement toutes les requêtes de recherche récentes \? + Le mot de passe doit comporter 4 caractères ou plus + Confirmer + Entrez un mot de passe pour démarrer l\'application avec + Suivant + Par défaut : %s + Connectez-vous pour voir ce contenu + Se connecter + Inverser + À la recherche de nouveaux chapitres + Effacer définitivement l\'historique des mises à jour \? + Effacer le flux + Tous les cookies ont été retirés + Effacer les cookies + Résoudre + CAPTCHA requis + Silencieux + On se souviendra de la configuration choisie pour ce manga + Appuyez pour réessayer + Aujourd\'hui + Groupe + Il y a longtemps + Hier + À l\'instant + Vous pouvez créer une sauvegarde de votre historique et de vos favoris et la restaurer + Les données ont été restaurées, mais il y a des erreurs + Toutes les données ont été restaurées + Fichier introuvable + Préparation… + Restauré + Restaurer à partir d\'une sauvegarde + Créer une sauvegarde des données + Sauvegarde et restauration + Utilise moins d\'énergie pour les écrans AMOLED + Noir + Garder au début + Ajuster à la largeur + Ajuster à la hauteur + Ajuster au centre + Mode mise à l\'échelle + Nouvelle catégorie + De droite à gauche + Aucune mise à jour disponible + Vérifier les mises à jour + Version %s + À propos + Les mots de passe ne correspondent pas + Répéter le mot de passe + Demander le mot de passe au démarrage de Kotatsu + Protéger l\'application + Mot de passe erroné + Entrez le mot de passe + Ne pas vérifier + Rechercher les mises à jour + La mise à jour des flux commencera bientôt + Mettre à Jour + Faire pivoter l\'écran + Effacé + Effacer le flux des mises à jour + Taille : %s + Nouvelle version : %s + Résultats de la recherche + Les nouveaux chapitres de ce que vous lisez sont présentés ici + Mises à jour + Lire plus tard + Catégorie vide + Tous les favoris + Terminé + Autre stockage + Pas de stockage disponible + Non disponible + Dossier pour les téléchargements + Animation de page + Récents + Étagère + Enregistrez-le à partir de sources en ligne ou importez des fichiers. + Sauvegardez d\'abord quelque chose + Trouvez ce que vous voulez lire dans le menu latéral. + Ce que vous lisez sera affiché ici + Essayez de reformuler la requête. + C\'est un peu vide ici… + Retirer + Catégories favorites + Vibration + Indicateur lumineux + Son de notification + Paramètres des notifications + Télécharger + Nouveaux chapitres + %1$d de %2$d activé(s) + Notifications + Ce manga a %s. Tout sauvegarder \? + Enregistrer + Ouvrir dans le navigateur + Une nouvelle version de l\'application est disponible + Domaine + Stockage externe + Stockage interne + Gestes uniquement + Effacé + Effacer l\'historique de recherche + Vider le cache des miniatures + Erreur + Continuer + Boutons de volume + Appuis au bord + Changer de pages + Paramètres du lecteur + Supprimer « %s » de l\'appareil de façon permanente \? + Supprimer le manga + Rechercher sur %s + Taille de la grille + Mode lecture + Webtoon + Standard + o|ko|Mo|Go|To + Vider le cache de la page + Aucune description + Choisissez un fichier ZIP ou CBZ. + Cette opération n\'est pas prise en charge + Supprimer + Importer + Partager l\'image + Sauvegardé + Sauvegarder la page + « %s » supprimé du stockage local + Retirer + Effacer définitivement l\'historique de lecture \? + Effacer + Pages + Suivre le système + Sombre + Clair + Thème + Filtre + Ordre de tri + Évaluation + Le plus récent + Mis à jour + Populaire + Nom + Téléchargements + Téléchargé + Traitement… + Téléchargement… + Rechercher un manga + Rechercher + Partager %s + Créer un raccourci… + Partager + Enregistrer + Ajouter + Nouvelle catégorie + Ajouter aux favoris + Aucun favori pour le moment + Lire + Pas encore d\'historique + Rien n\'a été trouvé + Effacer l\'historique + Réessayer + Fermer + Chapitre %1$d sur %2$d + Chargement… + Sources des mangas + Paramètres + Mode liste + Grille + Liste détaillée + Liste + Chapitres + Détails + Erreur réseau + Une erreur s\'est produite + Historique + Favoris + Stockage local + Le chapitre est manquant + En file d\'attente + Traduction + Traduire cette application + Genres + Vous serez déconnecté de toutes les sources + La connexion sur %s n\'est pas prise en charge + Autorisé + Terminé + En cours + Par défaut + Exclure les mangas osés de l\'historique + Pages numérotées + Sources utilisées + Sources disponibles + Calcul… + Bloquer pour contenu sensible + Toujours bloquer + Politique relative aux captures d\'écran + Autoriser + Suggestions + Ne pas suggérer de mangas osés + Activer les suggestions + Suggérer des mangas en fonction de vos préférences + Toutes les données sont analysées localement sur cet appareil et ne sont jamais envoyées ailleurs. + Commencez à lire des mangas et vous recevrez des suggestions personnalisées + Impossible de charger la liste des genres + Activé + Désactivé + Uniquement en Wi-Fi + Toujours + Précharger les pages + Jamais + Réinitialiser le filtre + Sélectionnez les langues dans lesquelles vous souhaitez lire les mangas. Vous pouvez le changer plus tard dans les paramètres. + Connecté en tant que %s + 18+ + Langues diverses + Trouver un chapitre + Pas de chapitres dans ce manga + %1$s%% + Apparence + Mise à jour des suggestions + Exclure des genres + Spécifiez les genres que vous ne voulez pas voir apparaître dans les suggestions + Supprimer définitivement les éléments sélectionnés de l\'appareil \? + Suppression terminée + Ralentissement du téléchargement + Permet d\'éviter le blocage de votre adresse IP + Les chapitres seront supprimés en arrière-plan + Traitement des mangas sauvegardés + Masquer + De nouvelles sources de mangas sont disponibles + Vérifier les nouveaux chapitres et les notifier + Activer les notifications + Vous recevrez des notifications sur les mises à jour des mangas que vous lisez + Vous ne recevrez pas de notifications mais les nouveaux chapitres seront mis en évidence dans les listes + Pas de catégories préférées + Nom + Modifier + Modifier la catégorie + Ajouter un marque-page + Retirer le marque-page + Marque-pages + Marque-page ajouté + Marque-page retiré + Annuler + Retiré de l\'historique + DNS sur HTTPS + Mode par défaut + Mode de détection automatique du lecteur + Détecter automatiquement si un manga est un webtoon + Désactiver l\'optimisation de la batterie + Aide à la vérification des mises à jour des antécédents + Un problème est survenu. Veuillez soumettre un rapport de bogue aux développeurs pour nous aider à le corriger. + Envoyer + Tout désactiver + Utiliser l\'empreinte digitale si elle est disponible + Vos mangas récemment lus + Les mangas de vos favoris + Signaler + Suivi + Planifié + Lecture + Afficher les indicateurs de progression de lecture + Afficher le pourcentage de lecture dans l\'historique et les favoris + Les mangas marqués comme étant pour adultes ne seront jamais ajoutés à l\'historique et votre progression ne sera pas sauvegardée + Peut aider en cas de problème. Toutes les autorisations seront invalidées + Tout afficher + En attente + Abandonné + Suppression des données + Se déconnecter + Terminé + Relecture + Domaine invalide + Sélectionner une plage + Contenu non trouvé ou supprimé + Détails de l\'erreur:<br><tt>%1$s</tt><br><br>1. Essayez d\'<a href=%2$s>ouvrir le manga dans un navigateur web</a> pour vous assurer qu\'il est disponible sur sa source<br>2. Assurez-vous que vous utilisez la <a href=kotatsu://about>dernière version de Kotatsu</a><br>3. Si elle est disponible, envoyez un rapport d\'erreur aux développeurs. + Rappuyez sur Retour pour quitter + Êtes-vous sûr·e de vouloir supprimer les catégories de favoris sélectionnées \? \nTous les mangas qui s\'y trouvent seront perdus et ceci ne peut pas être annulé. - Appuyez deux fois sur la touche Retour pour quitter l\'appli - Disponible - Confirmation de sortie - %s - %s - Flux - Importation de mangas - Retiré des favoris - Effacer tout l\'historique - Les 2 dernières heures - Historique effacé - Gérer - Aucun marque-page - Vous pouvez créer un marque-page pendant la lecture d\'un manga - Marque-pages supprimés - Aucune source de mangas - Autoriser les sources de mangas de lire des mangas en ligne - Aléatoire - Réordonner - Vide - Explorer - Vos mangas seront affichés ici - Trouvez ce que vous voulez lire dans la section « Explorer » - Annulé - Le compte existe déjà - Retour - Synchronisation - Synchronisez vos données - Entrez votre courriel pour continuer - Mangas sauvegardés - Cache des pages - Autre cache - Utilisation du stockage - Options - Mode incognito - Aucun chapitre - Défilement automatique - Ch. %1$d/%2$d Pg. %3$d/%4$d - Afficher la barre d\'infos dans le lecteur - Archives des BD - Dossier avec des images - Importation terminée - Vous pouvez supprimer le fichier original du stockage pour gagner de l\'espace - L\'importation va bientôt commencer - Sauvegarde ou abandon des modifications non sauvegardées \? - Abandonner - Rendre les mangas récents disponibles en appuyant longuement sur l\'icône de l\'application - Taper sur le bord droit ou appuyer sur la touche droite permet toujours de passer à la page suivante - Contrôle ergonomique du lecteur - Afficher les raccourcis des mangas récents - Correction des couleurs - Luminosité - Contraste - Réinitialiser - Les paramètres de couleurs choisis seront sauvegardés pour ce manga - Il n\'y a plus d\'espace sur l\'appareil - Afficher le curseur de changement de page - Zoom Webtoon - Activez le Wi-Fi ou le réseau mobile pour lire les mangas en ligne - Différentes langues - Le réseau n\'est pas disponible - Compact - Erreur côté serveur (%1$d). Veuillez réessayer plus tard - Effacer aussi les informations sur les nouveaux chapitres - Source désactivée - Préchargement du contenu - Marquer comme actuel - Partager les journaux - Activer la journalisation - Enregistrer certaines actions à des fins de débogage - Langue - Afficher le contenu suspect - Dynamique - Schéma de couleurs - Afficher en vue grille - Pour suivre la progression de la lecture, sélectionnez Menu → Suivre sur l\'écran des détails du manga. - Prestations de service - Il n\'y a rien ici - Sakura - Rikka - Miku - Asuka - Mion - Mamimi - Autoriser les mises à jour instables - Téléchargement commencé - Kanade - Proposer des mises à jour des versions bêta de l\'application - En-tête UserAgent - Veuillez redémarrer l\'application pour appliquer ces changements - Compris - Vitesse - Importer une sauvegarde des données de l\'utilisateur créée précédemment - Vous pouvez sélectionner un répertoire contenant des archives ou des images. Chaque archive (ou sous-répertoire) sera reconnue comme un chapitre. - Vous pouvez sélectionner un ou plusieurs fichiers .cbz ou .zip, chaque fichier sera reconnu comme un manga séparé. - Afficher sur l\'étagère - Appuyez sur un élément et maintenez-le enfoncé pour le réorganiser - Trouver des similaires - Arrêter le téléchargement lors du passage à un réseau mobile - Vous pouvez vous connecter à un compte existant ou en créer un nouveau - Adresse du serveur - Vous pouvez utiliser un serveur de synchronisation autohébergé ou un serveur par défaut. Ne modifiez pas ce paramètre si vous n\'êtes pas sûr·e de ce que vous faites. - Retrait terminé - Activer - Non merci - Paramètres de synchronisation - Ignorer les erreurs SSL - Choisir le miroir automatiquement - Changement automatique de domaine pour les sources distantes en cas d\'erreur si des miroirs sont disponibles - Mettre en pause - Reprendre - En pause - Tout annuler - Téléchargement uniquement via Wi-Fi - L\'historique de vos téléchargements sera définitivement supprimé - Notifications parfois affichées avec des mangas suggérés - Tous les téléchargements actifs seront annulés, les données partiellement téléchargées seront perdues - Les téléchargements ont été interrompus - Suggestion : %s - Plus - Vous n\'avez pas de téléchargements - Les téléchargements ont repris - Les téléchargements ont été supprimés - Les téléchargements ont été annulés - Voulez-vous recevoir des suggestions de mangas personnalisées \? - WebView non disponible : vérifier si le fournisseur WebView est installé - Traductions - Effacer le cache réseau - Taper - Adresse - Port - Proxy - Téléchargé - Pseudonyme - Proxy d\'optimisation des images - Inverser les couleurs - Utilisez le service wsrv.nl pour réduire le trafic et augmenter la vitesse de chargement des images si possible - %1$s (%2$s) - Mot de passe - Valeur invalide - Autorisation (optionnel) - \ No newline at end of file + Appuyez deux fois sur la touche Retour pour quitter l\'appli + Disponible + Confirmation de sortie + %s - %s + Flux + Importation de mangas + Retiré des favoris + Effacer tout l\'historique + Les 2 dernières heures + Historique effacé + Gérer + Aucun marque-page + Vous pouvez créer un marque-page pendant la lecture d\'un manga + Marque-pages supprimés + Aucune source de mangas + Autoriser les sources de mangas de lire des mangas en ligne + Aléatoire + Réordonner + Vide + Explorer + Vos mangas seront affichés ici + Trouvez ce que vous voulez lire dans la section « Explorer » + Annulé + Le compte existe déjà + Retour + Synchronisation + Synchronisez vos données + Entrez votre courriel pour continuer + Mangas sauvegardés + Cache des pages + Autre cache + Utilisation du stockage + Options + Mode incognito + Aucun chapitre + Défilement automatique + Ch. %1$d/%2$d Pg. %3$d/%4$d + Afficher la barre d\'infos dans le lecteur + Archives des BD + Dossier avec des images + Importation terminée + Vous pouvez supprimer le fichier original du stockage pour gagner de l\'espace + L\'importation va bientôt commencer + Sauvegarde ou abandon des modifications non sauvegardées \? + Abandonner + Rendre les mangas récents disponibles en appuyant longuement sur l\'icône de l\'application + Taper sur le bord droit ou appuyer sur la touche droite permet toujours de passer à la page suivante + Contrôle ergonomique du lecteur + Afficher les raccourcis des mangas récents + Correction des couleurs + Luminosité + Contraste + Réinitialiser + Les paramètres de couleurs choisis seront sauvegardés pour ce manga + Il n\'y a plus d\'espace sur l\'appareil + Afficher le curseur de changement de page + Zoom Webtoon + Activez le Wi-Fi ou le réseau mobile pour lire les mangas en ligne + Différentes langues + Le réseau n\'est pas disponible + Compact + Erreur côté serveur (%1$d). Veuillez réessayer plus tard + Effacer aussi les informations sur les nouveaux chapitres + Source désactivée + Préchargement du contenu + Marquer comme actuel + Partager les journaux + Activer la journalisation + Enregistrer certaines actions à des fins de débogage + Langue + Afficher le contenu suspect + Dynamique + Schéma de couleurs + Afficher en vue grille + Pour suivre la progression de la lecture, sélectionnez Menu → Suivre sur l\'écran des détails du manga. + Prestations de service + Il n\'y a rien ici + Sakura + Rikka + Miku + Asuka + Mion + Mamimi + Autoriser les mises à jour instables + Téléchargement commencé + Kanade + Proposer des mises à jour des versions bêta de l\'application + En-tête UserAgent + Veuillez redémarrer l\'application pour appliquer ces changements + Compris + Vitesse + Importer une sauvegarde des données de l\'utilisateur créée précédemment + Vous pouvez sélectionner un répertoire contenant des archives ou des images. Chaque archive (ou sous-répertoire) sera reconnue comme un chapitre. + Vous pouvez sélectionner un ou plusieurs fichiers .cbz ou .zip, chaque fichier sera reconnu comme un manga séparé. + Afficher sur l\'étagère + Appuyez sur un élément et maintenez-le enfoncé pour le réorganiser + Trouver des similaires + Arrêter le téléchargement lors du passage à un réseau mobile + Vous pouvez vous connecter à un compte existant ou en créer un nouveau + Adresse du serveur + Vous pouvez utiliser un serveur de synchronisation autohébergé ou un serveur par défaut. Ne modifiez pas ce paramètre si vous n\'êtes pas sûr·e de ce que vous faites. + Retrait terminé + Activer + Non merci + Paramètres de synchronisation + Ignorer les erreurs SSL + Choisir le miroir automatiquement + Changement automatique de domaine pour les sources distantes en cas d\'erreur si des miroirs sont disponibles + Mettre en pause + Reprendre + En pause + Tout annuler + Téléchargement uniquement via Wi-Fi + L\'historique de vos téléchargements sera définitivement supprimé + Notifications parfois affichées avec des mangas suggérés + Tous les téléchargements actifs seront annulés, les données partiellement téléchargées seront perdues + Les téléchargements ont été interrompus + Suggestion : %s + Plus + Vous n\'avez pas de téléchargements + Les téléchargements ont repris + Les téléchargements ont été supprimés + Les téléchargements ont été annulés + Voulez-vous recevoir des suggestions de mangas personnalisées \? + WebView non disponible : vérifier si le fournisseur WebView est installé + Traductions + Effacer le cache réseau + Taper + Adresse + Port + Proxy + Téléchargé + Pseudonyme + Proxy d\'optimisation des images + Inverser les couleurs + Utilisez le service wsrv.nl pour réduire le trafic et augmenter la vitesse de chargement des images si possible + %1$s (%2$s) + Mot de passe + Valeur invalide + Autorisation (optionnel) + diff --git a/app/src/main/res/values-hi/plurals.xml b/app/src/main/res/values-hi/plurals.xml index 43fb5c692..ad027e19d 100644 --- a/app/src/main/res/values-hi/plurals.xml +++ b/app/src/main/res/values-hi/plurals.xml @@ -12,10 +12,6 @@ %1$d घंटेभर_पहले %1$d घंटोंभर_पहले - - कुल %1$d पेज - कुल %1$d पेजेस - %1$d नया चैप्टर %1$d नए चैप्टर diff --git a/app/src/main/res/values-in/plurals.xml b/app/src/main/res/values-in/plurals.xml index 3842c1fef..695fda2dd 100644 --- a/app/src/main/res/values-in/plurals.xml +++ b/app/src/main/res/values-in/plurals.xml @@ -1,8 +1,5 @@ - - Total %1$d halaman - %1$d item diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index de4eb06bd..c936966c4 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1,429 +1,425 @@ - Penyimpanan lokal - Favorit - Riwayat - Terjadi kesalahan - Kesalahan jaringan - Detail - Kisi - Mode daftar - Pengaturan - Sumber jarak jauh - Memuat… - Menghitung… - Bab %1$d dari %2$d - Tutup - Coba lagi - Nihil - Belum ada riwayat - Baca - Belum ada favorit - Favoritkan ini - Kategori baru - Tambah - Simpan - Bagikan - Buat pintasan… - Bagikan %s - Cari - Cari komik - Mengunduh… - Memproses… - Diunduh - Unduhan - Nama - Populer - Diperbarui - Terbaru - Peringkat - Urutan penyortiran - Saring - Tema - Terang - Gelap - Ikuti sistem - Halaman - Bersihkan - Hapus - Bersihkan riwayat - Hapus - Tindakan ini tidak didukung - Pilih antara berkas ZIP atau CBZ. - Tidak ada deskripsi - \"%s\" dihapus dari penyimpanan lokal - Simpan halaman - Disimpan - Bagikan gambar - Impor - Riwayat dan cache - Bersihkan cache halaman - B|kB|MB|GB|TB - Standar - Ukuran kisi - Cari di %s - Hapus komik - Hapus \"%s\" dari perangkat secara permanen\? - Pengaturan pembaca - Ganti halaman - Bab - Daftar - Daftar terperinci - Bersihkan semua riwayat baca secara permanen\? - Webtoon - Mode baca - Tombol volume - Lanjut - Bersihkan cache gambar mini - Bersihkan riwayat pencarian - Dibersihkan - Domain - Versi baru aplikasi tersedia - Buka di peramban web - Simpan - Pemberitahuan - %1$d dari %2$d diaktifkan - Bab baru - Unduh - Pengaturan pemberitahuan - Suara pemberitahuan - Sepi juga di sini… - Apa yang Anda baca akan ditampilkan di sini - Cari apa untuk di baca di bilah samping. - Simpan sesuatu dulu - Rak - Baru-baru ini - Animasi halaman - Folder unduhan - Tidak tersedia - Tidak ada penyimpanan yang tersedia - Penyimpanan lain - Selesai - Semua favorit - Kategori kosong - Baca nanti - Pembaruan - Bab baru dari apa yang Anda baca ditampilkan di sini - Hasil pencarian - Versi baru: %s - Ukuran: %s - Dibersihkan - Pembaruan - Mencari pembaruan - Jangan periksa - Kata sandi salah - Lindungi aplikasi - Ulangi kata sandi - Mode skala - Buat cadangan data - Dipulihkan - Semua data dipulihkan - Data berhasil dipulihkan, tapi ada kesalahan - Anda dapat membuat cadangan riwayat dan favorit Anda dan memulihkannya - Baru saja - Lama - Kelompok - Hari ini - Ketuk untuk coba lagi - Konfigurasi yang dipilih akan diingat untuk komik ini - Diam - CAPTCHA diperlukan - Selesaikan - Bersihkan kuki - Semua kuki telah dihapus - Bersihkan aliran - Periksa bab baru - Masuk untuk melihat konten ini - Selanjutnya - Masukkan kata sandi untuk memulai aplikasi - Konfirmasi - Hapus semua kueri pencarian baru-baru ini secara permanen\? - Selamat Datang - Cadangan disimpan - Beberapa perangkat mempunyai perilaku sistem yang berbeda, yang mungkin akan merusak tugas latar belakang. - Baca lebih lanjut - Bab ini menghilang - Terjemahan - Masuk pada %s tidak didukung - Anda akan keluar dari semua sumber - Genre - Selesai - Sedang berlangsung - Standar - Kecualikan komik NSFW dari riwayat - Nomor halaman - Sumber yang digunakan - Sumber yang tersedia - Kebijakan tangkapan layar - Bolehkan - Blokir pada NSFW - Selalu blokir - Saran - Aktifkan saran - Sarankan manga berdasarkan preferensi Anda - Semua data hanya dianalisis secara lokal pada perangkat ini dan tidak pernah dikirim ke mana pun. - Mulai membaca komik dan Anda akan mendapatkan saran yang dipersonalisasi - Jangan menyarankan komik NSFW - Selalu - Muat ulang halaman - Masuk sebagai %s - Diaktifkan - Dinonaktifkan - Tidak bisa memuat daftar genre - Atur ulang filter - Cari genre - Pilih bahasa komik yang ingin Anda baca. Anda bisa mengubahnya nanti di pengaturan. - Jangan Pernah - Hanya di Wi-Fi - 18+ - Berbagai bahasa - Cari bab - Tidak ada bab di komik ini - %1$s%% - Tampilan - Konten - Kecualikan genre - Tentukan genre yang Anda tidak ingin lihat di saran - Hapus yang dipilih dari perangkat secara permanen\? - Selesai menghapus - Perlambat unduhan - Memperbarui saran - Membantu menghidari pemblokiran alamat IP Anda - Bab akan dihapus di latar belakang - Sembunyikan - Tersedia sumber komik baru - Periksa bab baru dan beri tahu tentang itu - Anda akan menerima pemberitahuan tentang pembaruan komik yang Anda baca - Anda tidak akan menerima pemberitahuan, tapi bab baru akan disorot di daftar - Aktifkan pemberitahuan - Nama - Sunting - Sunting kategori - Tidak ada kategori favorit - Tambah markah - Hapus markah - Markah - Markah dihapus - Markah ditambahkan - Urung - Dihapus dari riwayat - Mode baca - Otomatis deteksi mode pembaca - Secara otomatis mendeteksi jika komik itu webtoon - Kategori baru - Indikator LED - Getaran - Kategori favorit - Hapus - Bersihkan aliran pembaruan - Kanan-ke-kiri - Putar layar - Pembaruan aliran akan dimulai - Masukkan kata sandi - Tanya kata sandi ketika memulai Kotatsu - Tentang - Periksa pembaruan - Kata sandi tidak sama - Versi %s - Penyimpanan internal - Penyimpanan eksternal - Kesalahan - Tidak ada pembaruan yang tersedia - Menggunakan daya lebih sedikit pada layar AMOLED - Hitam - Pencadangan dan pemulihan - Kemarin - Pulihkan dari cadangan - Berkas tidak ditemukan - Kata sandi harus 4 karakter atau lebih - Mempersiapkan… - Bersihkan semua riwayat pembaruan secara permanen\? - Masuk - Standar: %s - Unduh atau baca bab yang hilang ini secara daring. - Terjemahkan aplikasi ini - Tekan di tepi - Komik ini memiliki %s. Simpan semuanya\? - Pas tengah - Pas tinggi - Pas lebar - Balik - Mengantri - Resmi - Simpan dari sumber daring atau berkas impor. - Komik Anda akan ditampilkan di sini - Cari apa untuk dibaca di bagian «Jelajah» - Masukkan surel Anda untuk melanjutkan - Dibaca ulang - Jelajah - Direncanakan - Selesai - Dibatalkan - Sinkronisasi data Anda - Pelacakan - Keluar - Sinkronisasi - Kirim - Dibaca - Ditunda - Domain tidak valid - Belum ada markah - Anda bisa membuat markah ketika membaca komik - Markah dihapus - Tidak ada sumber komik - Acak - Kosong - Tampilkan bilah informasi di pembaca - Mengimpor komik - Dua jam terakhir - Tampilkan semua - Riwayat dihapus - Hapus semua riwayat - Pilihan - Impor selesai - Dihapus dari favorit - Impor akan segera dimulai - Konten tidak ditemukan atau dihapus - Tekan Kembali dua kali untuk keluar dari aplikasi - Konfirmasi keluar - Cache halaman - Cache lainnya - Penggunaan penyimpanan - Tersedia - Mode penyamaran - Gulir otomatis - Arsip komik - Folder dengan gambar - Anda bisa menghapus berkas asli dari penyimpanan untuk menghemat ruang - Umpan - Rincian error:<tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka manga di peramban web</a> untuk memastikan manga tersebut tersedia di sumbernya</a>2. Pastikan Anda menggunakan <a href= >manga versi terbaru</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Pastikan Anda menggunakan <a href=kotatsu://about>versi terbaru Kotatsu</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. - Kecerahan - Kontras - Atur Ulang - Pengaturan warna yang dipilih akan diingat untuk komik ini - Menyimpan atau membuang perubahan yang belum disimpan\? - Buang - Gunakan sidik jari jika tersedia - Komik dari favorit Anda - Komik yang baru-baru ini Anda baca - Penghapusan data - Akun sudah ada - Kembali - Membantu pemeriksaan pembaruan di latar belakang - Ada sesuatu yang salah. Mohon untuk mengirim laporan kutu (bug) ke pengembang untuk membantu kami memperbaikinya. - Lapor - Komik yang ditandai sebagai NSFW tidak akan ditambahkan ke riwayat dan pencapaian Anda tidak akan disimpan - Bisa membantu dalam beberapa masalah. Seluruh otorisasi akan menjadi tidak valid - Kelola - Aktifkan sumber komik untuk membaca komik daring - Yakin ingin menghapus kategori favorit yang dipilih\? + Penyimpanan lokal + Favorit + Riwayat + Terjadi kesalahan + Kesalahan jaringan + Detail + Kisi + Mode daftar + Pengaturan + Sumber jarak jauh + Memuat… + Menghitung… + Bab %1$d dari %2$d + Tutup + Coba lagi + Nihil + Belum ada riwayat + Baca + Belum ada favorit + Favoritkan ini + Kategori baru + Tambah + Simpan + Bagikan + Buat pintasan… + Bagikan %s + Cari + Cari komik + Mengunduh… + Memproses… + Diunduh + Unduhan + Nama + Populer + Diperbarui + Terbaru + Peringkat + Urutan penyortiran + Saring + Tema + Terang + Gelap + Ikuti sistem + Halaman + Bersihkan + Hapus + Bersihkan riwayat + Hapus + Tindakan ini tidak didukung + Pilih antara berkas ZIP atau CBZ. + Tidak ada deskripsi + \"%s\" dihapus dari penyimpanan lokal + Simpan halaman + Disimpan + Bagikan gambar + Impor + Bersihkan cache halaman + B|kB|MB|GB|TB + Standar + Ukuran kisi + Cari di %s + Hapus komik + Hapus \"%s\" dari perangkat secara permanen\? + Pengaturan pembaca + Ganti halaman + Bab + Daftar + Daftar terperinci + Bersihkan semua riwayat baca secara permanen\? + Webtoon + Mode baca + Tombol volume + Lanjut + Bersihkan cache gambar mini + Bersihkan riwayat pencarian + Dibersihkan + Domain + Versi baru aplikasi tersedia + Buka di peramban web + Simpan + Pemberitahuan + %1$d dari %2$d diaktifkan + Bab baru + Unduh + Pengaturan pemberitahuan + Suara pemberitahuan + Sepi juga di sini… + Apa yang Anda baca akan ditampilkan di sini + Cari apa untuk di baca di bilah samping. + Simpan sesuatu dulu + Rak + Baru-baru ini + Animasi halaman + Folder unduhan + Tidak tersedia + Tidak ada penyimpanan yang tersedia + Penyimpanan lain + Selesai + Semua favorit + Kategori kosong + Baca nanti + Pembaruan + Bab baru dari apa yang Anda baca ditampilkan di sini + Hasil pencarian + Versi baru: %s + Ukuran: %s + Dibersihkan + Pembaruan + Mencari pembaruan + Jangan periksa + Kata sandi salah + Lindungi aplikasi + Ulangi kata sandi + Mode skala + Buat cadangan data + Dipulihkan + Semua data dipulihkan + Data berhasil dipulihkan, tapi ada kesalahan + Anda dapat membuat cadangan riwayat dan favorit Anda dan memulihkannya + Baru saja + Lama + Kelompok + Hari ini + Ketuk untuk coba lagi + Konfigurasi yang dipilih akan diingat untuk komik ini + Diam + CAPTCHA diperlukan + Selesaikan + Bersihkan kuki + Semua kuki telah dihapus + Bersihkan aliran + Periksa bab baru + Masuk untuk melihat konten ini + Selanjutnya + Masukkan kata sandi untuk memulai aplikasi + Konfirmasi + Hapus semua kueri pencarian baru-baru ini secara permanen\? + Selamat Datang + Cadangan disimpan + Beberapa perangkat mempunyai perilaku sistem yang berbeda, yang mungkin akan merusak tugas latar belakang. + Baca lebih lanjut + Bab ini menghilang + Terjemahan + Masuk pada %s tidak didukung + Anda akan keluar dari semua sumber + Genre + Selesai + Sedang berlangsung + Standar + Kecualikan komik NSFW dari riwayat + Nomor halaman + Sumber yang digunakan + Sumber yang tersedia + Kebijakan tangkapan layar + Bolehkan + Blokir pada NSFW + Selalu blokir + Saran + Aktifkan saran + Sarankan manga berdasarkan preferensi Anda + Semua data hanya dianalisis secara lokal pada perangkat ini dan tidak pernah dikirim ke mana pun. + Mulai membaca komik dan Anda akan mendapatkan saran yang dipersonalisasi + Jangan menyarankan komik NSFW + Selalu + Muat ulang halaman + Masuk sebagai %s + Diaktifkan + Dinonaktifkan + Tidak bisa memuat daftar genre + Atur ulang filter + Pilih bahasa komik yang ingin Anda baca. Anda bisa mengubahnya nanti di pengaturan. + Jangan Pernah + Hanya di Wi-Fi + 18+ + Berbagai bahasa + Cari bab + Tidak ada bab di komik ini + %1$s%% + Tampilan + Kecualikan genre + Tentukan genre yang Anda tidak ingin lihat di saran + Hapus yang dipilih dari perangkat secara permanen\? + Selesai menghapus + Perlambat unduhan + Memperbarui saran + Membantu menghidari pemblokiran alamat IP Anda + Bab akan dihapus di latar belakang + Sembunyikan + Tersedia sumber komik baru + Periksa bab baru dan beri tahu tentang itu + Anda akan menerima pemberitahuan tentang pembaruan komik yang Anda baca + Anda tidak akan menerima pemberitahuan, tapi bab baru akan disorot di daftar + Aktifkan pemberitahuan + Nama + Sunting + Sunting kategori + Tidak ada kategori favorit + Tambah markah + Hapus markah + Markah + Markah dihapus + Markah ditambahkan + Urung + Dihapus dari riwayat + Mode baca + Otomatis deteksi mode pembaca + Secara otomatis mendeteksi jika komik itu webtoon + Kategori baru + Indikator LED + Getaran + Kategori favorit + Hapus + Bersihkan aliran pembaruan + Kanan-ke-kiri + Putar layar + Pembaruan aliran akan dimulai + Masukkan kata sandi + Tanya kata sandi ketika memulai Kotatsu + Tentang + Periksa pembaruan + Kata sandi tidak sama + Versi %s + Penyimpanan internal + Penyimpanan eksternal + Kesalahan + Tidak ada pembaruan yang tersedia + Menggunakan daya lebih sedikit pada layar AMOLED + Hitam + Pencadangan dan pemulihan + Kemarin + Pulihkan dari cadangan + Berkas tidak ditemukan + Kata sandi harus 4 karakter atau lebih + Mempersiapkan… + Bersihkan semua riwayat pembaruan secara permanen\? + Masuk + Standar: %s + Terjemahkan aplikasi ini + Tekan di tepi + Komik ini memiliki %s. Simpan semuanya\? + Pas tengah + Pas tinggi + Pas lebar + Balik + Mengantri + Resmi + Simpan dari sumber daring atau berkas impor. + Komik Anda akan ditampilkan di sini + Cari apa untuk dibaca di bagian «Jelajah» + Masukkan surel Anda untuk melanjutkan + Dibaca ulang + Jelajah + Direncanakan + Selesai + Dibatalkan + Sinkronisasi data Anda + Pelacakan + Keluar + Sinkronisasi + Kirim + Dibaca + Ditunda + Domain tidak valid + Belum ada markah + Anda bisa membuat markah ketika membaca komik + Markah dihapus + Tidak ada sumber komik + Acak + Kosong + Tampilkan bilah informasi di pembaca + Mengimpor komik + Dua jam terakhir + Tampilkan semua + Riwayat dihapus + Hapus semua riwayat + Pilihan + Impor selesai + Dihapus dari favorit + Impor akan segera dimulai + Konten tidak ditemukan atau dihapus + Tekan Kembali dua kali untuk keluar dari aplikasi + Konfirmasi keluar + Cache halaman + Cache lainnya + Penggunaan penyimpanan + Tersedia + Mode penyamaran + Gulir otomatis + Arsip komik + Folder dengan gambar + Anda bisa menghapus berkas asli dari penyimpanan untuk menghemat ruang + Umpan + Rincian error:<tt>%1$s</tt><br><br>1. Coba <a href=%2$s>buka manga di peramban web</a> untuk memastikan manga tersebut tersedia di sumbernya</a>2. Pastikan Anda menggunakan <a href= >manga versi terbaru</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. Pastikan Anda menggunakan <a href=kotatsu://about>versi terbaru Kotatsu</a><br>3. Jika tersedia, kirimkan laporan kesalahan ke pengembang. + Kecerahan + Kontras + Atur Ulang + Pengaturan warna yang dipilih akan diingat untuk komik ini + Menyimpan atau membuang perubahan yang belum disimpan\? + Buang + Gunakan sidik jari jika tersedia + Komik dari favorit Anda + Komik yang baru-baru ini Anda baca + Penghapusan data + Akun sudah ada + Kembali + Membantu pemeriksaan pembaruan di latar belakang + Ada sesuatu yang salah. Mohon untuk mengirim laporan kutu (bug) ke pengembang untuk membantu kami memperbaikinya. + Lapor + Komik yang ditandai sebagai NSFW tidak akan ditambahkan ke riwayat dan pencapaian Anda tidak akan disimpan + Bisa membantu dalam beberapa masalah. Seluruh otorisasi akan menjadi tidak valid + Kelola + Aktifkan sumber komik untuk membaca komik daring + Yakin ingin menghapus kategori favorit yang dipilih\? \nSemua komik di dalamnya akan hilang dan ini tidak dapat dibatalkan. - Atur Ulang - Komik tersimpan - Tekan Kembali lagi untuk keluar - Tidak ada bab - Tampilkan pintasan komik baru-baru ini - Buat komik baru-baru ini tersedia dengan menekan panjang pada ikon aplikasi - Pilih jangkauan - Matikan semua - Hanya gestur - DNS over HTTPS - Istirahat - Mamimi - Kesalahan sisi server (%1$d). Silakan coba lagi nanti - kompak - Pramuat konten - %s - %s - Tidak ada apapun di sini - Ketuk di tepi kanan atau menekan tombol kanan akan selalu beralih ke halaman berikutnya - Sumber dinonaktifkan - Tandai sebagai saat ini - Tampilkan konten yang mencurigakan - Untuk melacak kemajuan membaca, pilih Menu → Lacak di layar detail komik. - Layanan - Juga informasi yang jelas tentang bab baru - Nyalakan Wi-Fi atau jaringan seluler untuk membaca komik daring - Tajuk Agen Pengguna - Mulai ulang aplikasi untuk menerapkan perubahan ini - Kanade - Bagikan log - Tidak ada ruang tersisa di perangkat - Izinkan pembaruan yang tidak stabil - Usulkan pembaruan ke versi beta - Unduh dimulai - Tampilkan indikator kemajuan membaca - Tampilkan persentase baca dalam riwayat dan favorit - Bahasa - Cobalah untuk memformulasi ulang kueri. - Tetap di awal - Bab. %1$d/%2$d Hal. %3$d/%4$d - Aktifkan pencatatan - Rekam beberapa tindakan untuk tujuan debug - Dinamis - Skema warna - Perlihatkan dalam tampilan kisi - Miku - Asuka - Mion - Rikka - Sakura - Pemrosesan komik tersimpan - Nonaktifkan pengoptimalan baterai - Kontrol pembaca ergonomis - Koreksi warna - Perlihatkan penggeser peralihan halaman - Zoom webtoon - Berbagai bahasa - Jaringan tidak tersedia - Oke - Ketuk dan tahan item untuk menyusun ulang - Anda dapat memilih satu atau beberapa file .cbz atau .zip, setiap file akan dikenali sebagai komik terpisah. - Anda dapat memilih direktori yang berisi arsip atau gambar. Setiap arsip (atau subdirektori) akan dikenali sebagai sebuah bab. - Kecepatan - Impor cadangan data pengguna yang telah dibuat sebelumnya - Tampilkan di Rak - Anda dapat masuk ke akun yang sudah ada atau membuat akun baru - Temukan serupa - Alamat server - Unduh hanya melalui Wi-Fi - Unduhan telah dibatalkan - Aktifkan - Tidak, terima kasih - Pengaturan sinkronisasi - Anda dapat menggunakan server sinkronisasi yang dihosting sendiri atau server default. Jangan ubah ini jika Anda tidak yakin dengan apa yang Anda lakukan. - Abaikan kesalahan SSL - Pilih cermin secara otomatis - Secara otomatis mengalihkan domain untuk sumber jarak jauh saat terjadi kesalahan jika mirror tersedia - Jeda - Lanjut - Dijeda - Hapus selesai - Batalkan semua - Berhenti mengunduh saat beralih ke jaringan seluler - Saran: %s - Terkadang menampilkan notifikasi dengan manga yang disarankan - Lebih - Semua pengunduhan yang aktif akan dibatalkan, data yang sudah terunduh sebagian akan hilang - Riwayat unduhan Anda akan dihapus secara permanen - Anda tidak memiliki unduhan apa pun - Unduhan telah dilanjutkan - Unduhan telah dijeda - Unduhan telah dihapus - Apakah Anda ingin menerima saran manga yang dipersonalisasi\? - Terjemahan - WebView tidak tersedia: periksa apakah penyedia WebView telah diinstal - Hapus cache jaringan - Tipe - Alamat - Port - Proksi - Nilai tidak valid - %1$s (%2$s) - Gunakan layanan wsrv.nl untuk mengurangi penggunaan lalu lintas dan mempercepat pemuatan gambar jika memungkinkan - Proksi pengoptimalan gambar - NamaUser - Diunduh - Balikkan warna - Kata sandi - Otorisasi (opsional) - \ No newline at end of file + Atur Ulang + Komik tersimpan + Tekan Kembali lagi untuk keluar + Tidak ada bab + Tampilkan pintasan komik baru-baru ini + Buat komik baru-baru ini tersedia dengan menekan panjang pada ikon aplikasi + Pilih jangkauan + Matikan semua + Hanya gestur + DNS over HTTPS + Istirahat + Mamimi + Kesalahan sisi server (%1$d). Silakan coba lagi nanti + kompak + Pramuat konten + %s - %s + Tidak ada apapun di sini + Ketuk di tepi kanan atau menekan tombol kanan akan selalu beralih ke halaman berikutnya + Sumber dinonaktifkan + Tandai sebagai saat ini + Tampilkan konten yang mencurigakan + Untuk melacak kemajuan membaca, pilih Menu → Lacak di layar detail komik. + Layanan + Juga informasi yang jelas tentang bab baru + Nyalakan Wi-Fi atau jaringan seluler untuk membaca komik daring + Tajuk Agen Pengguna + Mulai ulang aplikasi untuk menerapkan perubahan ini + Kanade + Bagikan log + Tidak ada ruang tersisa di perangkat + Izinkan pembaruan yang tidak stabil + Usulkan pembaruan ke versi beta + Unduh dimulai + Tampilkan indikator kemajuan membaca + Tampilkan persentase baca dalam riwayat dan favorit + Bahasa + Cobalah untuk memformulasi ulang kueri. + Tetap di awal + Bab. %1$d/%2$d Hal. %3$d/%4$d + Aktifkan pencatatan + Rekam beberapa tindakan untuk tujuan debug + Dinamis + Skema warna + Perlihatkan dalam tampilan kisi + Miku + Asuka + Mion + Rikka + Sakura + Pemrosesan komik tersimpan + Nonaktifkan pengoptimalan baterai + Kontrol pembaca ergonomis + Koreksi warna + Perlihatkan penggeser peralihan halaman + Zoom webtoon + Berbagai bahasa + Jaringan tidak tersedia + Oke + Ketuk dan tahan item untuk menyusun ulang + Anda dapat memilih satu atau beberapa file .cbz atau .zip, setiap file akan dikenali sebagai komik terpisah. + Anda dapat memilih direktori yang berisi arsip atau gambar. Setiap arsip (atau subdirektori) akan dikenali sebagai sebuah bab. + Kecepatan + Impor cadangan data pengguna yang telah dibuat sebelumnya + Tampilkan di Rak + Anda dapat masuk ke akun yang sudah ada atau membuat akun baru + Temukan serupa + Alamat server + Unduh hanya melalui Wi-Fi + Unduhan telah dibatalkan + Aktifkan + Tidak, terima kasih + Pengaturan sinkronisasi + Anda dapat menggunakan server sinkronisasi yang dihosting sendiri atau server default. Jangan ubah ini jika Anda tidak yakin dengan apa yang Anda lakukan. + Abaikan kesalahan SSL + Pilih cermin secara otomatis + Secara otomatis mengalihkan domain untuk sumber jarak jauh saat terjadi kesalahan jika mirror tersedia + Jeda + Lanjut + Dijeda + Hapus selesai + Batalkan semua + Berhenti mengunduh saat beralih ke jaringan seluler + Saran: %s + Terkadang menampilkan notifikasi dengan manga yang disarankan + Lebih + Semua pengunduhan yang aktif akan dibatalkan, data yang sudah terunduh sebagian akan hilang + Riwayat unduhan Anda akan dihapus secara permanen + Anda tidak memiliki unduhan apa pun + Unduhan telah dilanjutkan + Unduhan telah dijeda + Unduhan telah dihapus + Apakah Anda ingin menerima saran manga yang dipersonalisasi\? + Terjemahan + WebView tidak tersedia: periksa apakah penyedia WebView telah diinstal + Hapus cache jaringan + Tipe + Alamat + Port + Proksi + Nilai tidak valid + %1$s (%2$s) + Gunakan layanan wsrv.nl untuk mengurangi penggunaan lalu lintas dan mempercepat pemuatan gambar jika memungkinkan + Proksi pengoptimalan gambar + NamaUser + Diunduh + Balikkan warna + Kata sandi + Otorisasi (opsional) + diff --git a/app/src/main/res/values-it/plurals.xml b/app/src/main/res/values-it/plurals.xml index de8c2c03b..0fdb0355c 100644 --- a/app/src/main/res/values-it/plurals.xml +++ b/app/src/main/res/values-it/plurals.xml @@ -1,9 +1,5 @@ - - %1$d pagina in totale - %1$d pagine in totale - %1$d nuovo capitolo %1$d nuovi capitoli diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 193367044..b34a26a79 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,6 +1,5 @@ - Cronologia e cache Nessuna descrizione File non valido. Sono supportati solo ZIP e CBZ. Questa operazione non è supportata @@ -182,7 +181,6 @@ Adatta alla larghezza Modalità scala Capitolo mancante - Questo capitolo manca sul tuo dispositivo. Scaricalo o leggilo in linea. In coda Traduzione Traduci questa applicazione @@ -211,7 +209,6 @@ Abilitato Disabilitato Non suggerire manga NSFW - Trova il genere Ripristina il filtro Seleziona le lingue in cui vuoi leggere i manga. Puoi cambiarla in seguito nelle impostazioni. Mai @@ -225,7 +222,6 @@ Nessun capitolo in questo manga %1$s%% Aspetto - Contenuto Aggiornamento dei suggerimenti Specifica i generi che non vuoi vedere nei suggerimenti Escludi generi diff --git a/app/src/main/res/values-ja/plurals.xml b/app/src/main/res/values-ja/plurals.xml index 5872418c3..cf5756968 100644 --- a/app/src/main/res/values-ja/plurals.xml +++ b/app/src/main/res/values-ja/plurals.xml @@ -15,9 +15,6 @@ %1$dチャプター - - 合計%1$dページ - %1$d新しい章 diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 160cd572a..4f2a2cef9 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,429 +1,425 @@ - 履歴 - ロード中… - チャプター %1$d of %2$d - 共有 - 履歴を削除 - 検索 - 漫画を検索 - 閉じる - お気に入り - エラーが発生しました - 詳細 - - リスト - 詳細リスト - グリッド - リストモード - マンガのソース - 再試行 - 何も見つかりませんでした - まだ履歴はありません - 読む - お気に入りの本はありません - お気に入りの本 - 新たなカテゴリー - 追加 - 保存 - ショートカットを作成します… - 共有する%s - ダウンロード中… - 処理中… - ダウンロードした本 - ダウンロード - 名前 - 人気 - ローカルストレージ - 最新 - 評価 - ソート順に並べ替え - フォローシステム - クリア - すべての履歴を永久にクリアしますか? - 削除 - 「%s 」がローカルストレージから削除されました - ページを保存 - 保存しました - 画像を共有する - インポート - 消去 - この操作はサポートされていません - 説明がありません - 履歴とキャッシュ - ページのキャッシュをクリアする - B|kB|MB|GB|TB - 設定 - ライトテーマ - フィルター - ダークテーマ - ページ - テーマ - ネットワークエラー - アップデート - ZIPファイルまたはCBZファイルを選択してください。 - 標準 - ウェブトゥーン - 読み取りモード - グリッドのサイズ - %sで検索 - 漫画を削除 - お使いのデバイスから「%s」を完全に削除しますか? - リーダーの設定 - ページを変更 - エッジタップ - ボリュームボタン - 続ける - エラー - サムネイルキャッシュをクリア - クリア - ジェスチャーのみ - 内部ストレージ - ドメイン - ブラウザーで開く - この漫画には%sがあります。 すべて保存しますか? - 保存 - 通知 - %2$dの%1$d - 新しいチャプター - ダウンロード - 通知の設定 - 通知音 - LEDインジケータ - バイブレーション - お気に入りのカテゴリー - 削除 - クエリを再定式化してみてください。 - 読んだ内容がここに表示されます - サイドメニューで何を読むかを見つけてください。 - 最初に何かを保存する - 本棚 - 最近 - ページアニメーション - ダウンロード用のフォルダ - 利用出来ません - 使用可能なストレージがありません - その他のストレージ - 完了 - 全てのお気に入り - 後で読む - 更新 - あなたが読んでいるものの新しいチャプターがここに示されています - の検索結果 - サイズ:%s - 更新フィードをクリア - クリア - アップデート - フィードの更新はまもなく開始されます - アップデートを確認 - チェックしない - Kotatsuを起動したときにパスワードを入力する - パスワードを繰り返す - パスワードが違います - この本の詳細 - 現在のバージョン%s - 検索履歴をクリア - 外部ストレージ - Kotatsuの新しい更新が利用可能です - ここは空っぽです… - 空のカテゴリー - オンラインソースから保存するかファイルをインポートします。 - 新しいバージョン:%s - 画面を回転させる - パスワードを入力してください - パスワードが間違っています - アプリを保護する - 最新のアップデートを確認する - 利用可能なアップデートはありません - 右から左 - 承認済み - %sへのログインはサポートされていません - 完成 - 進行中 - デフォルト - ナンバリングページ - 使用したソース - 利用可能なソース - 新しいカテゴリー - 高さを合わせる - チャプターがありません - すべての更新履歴を完全に消去しますか? - この不足した章をダウンロードしたり、オンラインで読んだりすることができます。 - このコンテンツを表示するにはサインインしてください - ファイルが見つかりません - パスワードは4文字以上である必要があります - ちょうど今 - ずっと前 - バックアップを保存 - グループ - フィードをクリア - バックアップから復元 - 確認 - 履歴とお気に入りのバックアップを作成して復元できます - 続きを読む - ブラック - データは復元されましたがエラーが発生しました - 最近の検索クエリを全て完全に削除しますか? - 幅を合わせる - 新しいチャプターを探しています - アプリを起動するためのパスワードを入力してください - データバックアップを作成 - 解決しました - タップして再試行してください - CAPTCHAが必要です - デフォルト:%s - 昨日 - このアプリを翻訳 - 全てのデータが復元されました - 復元 - 準備中… - 開始時に維持 - バックアップと復元 - リバース - 選択した構成はこの漫画のために記憶されます - クッキーを削除 - フィットセンター - 全てのソースからログアウトされます - NSFW漫画を履歴から除外する - キュー - 全てのCookieが削除されました - 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 - ジャンル - スケールモード - 今日 - Kotatsuを翻訳する(Weblateのサイトに移動します) - 次のページ - サイレント - サインイン - ようこそ - AMOLEDスクリーンでさらに少ない電力を使用 - コンピューティング… - 許可する - 常にブロック - スクリーンショットポリシー - NSFWでブロック - 提案 - すべてのデータは、このデバイス上でローカルでのみ分析され、どこにも送信されることはありません。 - サジェスト機能を有効 - あなたの好みに合わせて漫画を提案 - ジャンルリストを読み込めません - 無効 - マンガを読み始めると、個人的な提案を受けることができます - 有効 - NSFWのマンガを提案しない - フィルターをリセット - ジャンルを探す - Wi-Fiのみ使用 - 決して - 漫画を読みたい言語を選択します。後で設定から変更することができます。 - 常に - ページのプリロード - %sとしてログイン - 18歳以上 - さまざまな言語 - チャプターを検索 - この漫画の章はありません - %1$s%% - コンテンツ - 更新のご提案 - 外観 - ジャンルを除く - サジェストで表示したくないジャンルを指定 - 選択した項目をデバイスから完全に削除しますか? - 削除が完了しました - IPアドレスのブロックを回避することができます - 保存されたマンガの処理 - ダウンロードの速度低下 - チャプターはバックグラウンドで削除されます - 隠す - 新しいマンガソースが利用可能です - 新着チャプターの確認とお知らせ - 読んでいるマンガの更新情報をお知らせします - 通知を有効にする - 通知はありませんが、新しいチャプターはリストでハイライト表示されます - 名称 - 編集 - カテゴリーを編集する - お気に入りのカテゴリーはありません - ブックマーク - ブックマーク削除 - 元に戻す - 履歴から削除 - ブックマークの追加 - ブックマークの削除 - ブックマークを追加 - HTTPS 経由の DNS - リーダーモードの自動検出 - デフォルトモード - マンガがウェブトゥーンかどうかを自動判定 - バッテリー最適化の無効化 - バックグラウンドの更新チェックを支援 - 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 - 送信 - すべて無効にする - 最近読んだ漫画 - 指紋がある場合は、指紋を使用する - お気に入りの漫画 - 報告 - 読書 - 再読込 - 完了 - 保留中 - 追跡 - ログアウト - 予定 - ドロップ - データの削除 - 履歴とお気に入りに既読率を表示する - いくつかの問題の場合に助けることができる。すべての認証が無効になります - 読書の進行状況インジケーターを表示 - NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない - すべて表示 - 無効なドメイン - 範囲を選択 - コンテンツが見つからない、または削除された - 管理 - ランダム - 選択したお気に入りカテゴリを本当に削除してもよいですか? + 履歴 + ロード中… + チャプター %1$d of %2$d + 共有 + 履歴を削除 + 検索 + 漫画を検索 + 閉じる + お気に入り + エラーが発生しました + 詳細 + + リスト + 詳細リスト + グリッド + リストモード + マンガのソース + 再試行 + 何も見つかりませんでした + まだ履歴はありません + 読む + お気に入りの本はありません + お気に入りの本 + 新たなカテゴリー + 追加 + 保存 + ショートカットを作成します… + 共有する%s + ダウンロード中… + 処理中… + ダウンロードした本 + ダウンロード + 名前 + 人気 + ローカルストレージ + 最新 + 評価 + ソート順に並べ替え + フォローシステム + クリア + すべての履歴を永久にクリアしますか? + 削除 + 「%s 」がローカルストレージから削除されました + ページを保存 + 保存しました + 画像を共有する + インポート + 消去 + この操作はサポートされていません + 説明がありません + ページのキャッシュをクリアする + B|kB|MB|GB|TB + 設定 + ライトテーマ + フィルター + ダークテーマ + ページ + テーマ + ネットワークエラー + アップデート + ZIPファイルまたはCBZファイルを選択してください。 + 標準 + ウェブトゥーン + 読み取りモード + グリッドのサイズ + %sで検索 + 漫画を削除 + お使いのデバイスから「%s」を完全に削除しますか? + リーダーの設定 + ページを変更 + エッジタップ + ボリュームボタン + 続ける + エラー + サムネイルキャッシュをクリア + クリア + ジェスチャーのみ + 内部ストレージ + ドメイン + ブラウザーで開く + この漫画には%sがあります。 すべて保存しますか? + 保存 + 通知 + %2$dの%1$d + 新しいチャプター + ダウンロード + 通知の設定 + 通知音 + LEDインジケータ + バイブレーション + お気に入りのカテゴリー + 削除 + クエリを再定式化してみてください。 + 読んだ内容がここに表示されます + サイドメニューで何を読むかを見つけてください。 + 最初に何かを保存する + 本棚 + 最近 + ページアニメーション + ダウンロード用のフォルダ + 利用出来ません + 使用可能なストレージがありません + その他のストレージ + 完了 + 全てのお気に入り + 後で読む + 更新 + あなたが読んでいるものの新しいチャプターがここに示されています + の検索結果 + サイズ:%s + 更新フィードをクリア + クリア + アップデート + フィードの更新はまもなく開始されます + アップデートを確認 + チェックしない + Kotatsuを起動したときにパスワードを入力する + パスワードを繰り返す + パスワードが違います + この本の詳細 + 現在のバージョン%s + 検索履歴をクリア + 外部ストレージ + Kotatsuの新しい更新が利用可能です + ここは空っぽです… + 空のカテゴリー + オンラインソースから保存するかファイルをインポートします。 + 新しいバージョン:%s + 画面を回転させる + パスワードを入力してください + パスワードが間違っています + アプリを保護する + 最新のアップデートを確認する + 利用可能なアップデートはありません + 右から左 + 承認済み + %sへのログインはサポートされていません + 完成 + 進行中 + デフォルト + ナンバリングページ + 使用したソース + 利用可能なソース + 新しいカテゴリー + 高さを合わせる + チャプターがありません + すべての更新履歴を完全に消去しますか? + このコンテンツを表示するにはサインインしてください + ファイルが見つかりません + パスワードは4文字以上である必要があります + ちょうど今 + ずっと前 + バックアップを保存 + グループ + フィードをクリア + バックアップから復元 + 確認 + 履歴とお気に入りのバックアップを作成して復元できます + 続きを読む + ブラック + データは復元されましたがエラーが発生しました + 最近の検索クエリを全て完全に削除しますか? + 幅を合わせる + 新しいチャプターを探しています + アプリを起動するためのパスワードを入力してください + データバックアップを作成 + 解決しました + タップして再試行してください + CAPTCHAが必要です + デフォルト:%s + 昨日 + このアプリを翻訳 + 全てのデータが復元されました + 復元 + 準備中… + 開始時に維持 + バックアップと復元 + リバース + 選択した構成はこの漫画のために記憶されます + クッキーを削除 + フィットセンター + 全てのソースからログアウトされます + NSFW漫画を履歴から除外する + キュー + 全てのCookieが削除されました + 一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。 + ジャンル + スケールモード + 今日 + Kotatsuを翻訳する(Weblateのサイトに移動します) + 次のページ + サイレント + サインイン + ようこそ + AMOLEDスクリーンでさらに少ない電力を使用 + コンピューティング… + 許可する + 常にブロック + スクリーンショットポリシー + NSFWでブロック + 提案 + すべてのデータは、このデバイス上でローカルでのみ分析され、どこにも送信されることはありません。 + サジェスト機能を有効 + あなたの好みに合わせて漫画を提案 + ジャンルリストを読み込めません + 無効 + マンガを読み始めると、個人的な提案を受けることができます + 有効 + NSFWのマンガを提案しない + フィルターをリセット + Wi-Fiのみ使用 + 決して + 漫画を読みたい言語を選択します。後で設定から変更することができます。 + 常に + ページのプリロード + %sとしてログイン + 18歳以上 + さまざまな言語 + チャプターを検索 + この漫画の章はありません + %1$s%% + 更新のご提案 + 外観 + ジャンルを除く + サジェストで表示したくないジャンルを指定 + 選択した項目をデバイスから完全に削除しますか? + 削除が完了しました + IPアドレスのブロックを回避することができます + 保存されたマンガの処理 + ダウンロードの速度低下 + チャプターはバックグラウンドで削除されます + 隠す + 新しいマンガソースが利用可能です + 新着チャプターの確認とお知らせ + 読んでいるマンガの更新情報をお知らせします + 通知を有効にする + 通知はありませんが、新しいチャプターはリストでハイライト表示されます + 名称 + 編集 + カテゴリーを編集する + お気に入りのカテゴリーはありません + ブックマーク + ブックマーク削除 + 元に戻す + 履歴から削除 + ブックマークの追加 + ブックマークの削除 + ブックマークを追加 + HTTPS 経由の DNS + リーダーモードの自動検出 + デフォルトモード + マンガがウェブトゥーンかどうかを自動判定 + バッテリー最適化の無効化 + バックグラウンドの更新チェックを支援 + 何か問題が発生しました。開発者にバグレポートを提出し、解決にご協力ください。 + 送信 + すべて無効にする + 最近読んだ漫画 + 指紋がある場合は、指紋を使用する + お気に入りの漫画 + 報告 + 読書 + 再読込 + 完了 + 保留中 + 追跡 + ログアウト + 予定 + ドロップ + データの削除 + 履歴とお気に入りに既読率を表示する + いくつかの問題の場合に助けることができる。すべての認証が無効になります + 読書の進行状況インジケーターを表示 + NSFWとマークされたマンガは履歴に追加されず、進行状況も保存されない + すべて表示 + 無効なドメイン + 範囲を選択 + コンテンツが見つからない、または削除された + 管理 + ランダム + 選択したお気に入りカテゴリを本当に削除してもよいですか? \nその中にあるマンガはすべて失われ、元に戻すことはできません。 - - 探検 - アプリを終了するには、戻るを2回押してください - 保存したマンガ - チャプターなし - 自動スクロール - マンガのインポート - 続行するにはメールアドレスを入力してください - «探索»セクションで読むべきものを見つける - インポートが完了しました - あなたのマンガはここに表示されます - キャンセル - データの同期 - アカウントは既に存在します - 戻る - 過去 2 時間 - ブックマークはまだありません - 同期 - ページキャッシュ - 利用可能 - すべての履歴を消去する - 履歴が消去されました - 並べ替え - マンガを読みながらブックマークを作成することができます - ブックマークを削除しました - マンガのソースがない - マンガのソースを有効にして、オンラインでマンガを読めるようにする - もう一度戻るを押して終了します - %s -%s - 退出確認 - ストレージの使用状況 - その他のキャッシュ - シークレットモード - 画像を含むフォルダ - まもなくインポートが開始されます - お気に入りから削除 - オプション - ストレージから元のファイルを削除して、容量を節約することができます - Ch.%1$d/%2$d Pg.%3$d/%4$d - リーダーで情報バーを表示する - コミックアーカイブ - フィード - エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用可能かどうか確認してください<br>2.<a href=kotatsu://about>最新版のこたつ</a><br>3.利用可能であれば、開発者にエラーレポートを送ってみてください。 - 人間工学に基づいたリーダーコントロール - 最近のマンガのショートカットを表示 - アプリケーションアイコンを長押しして最近のマンガを利用できるようにする - 右端をタップするか、右キーを押すと、常に次のページに切り替わります - 色補正 - 輝度 - コントラスト - リセット - 未保存の変更を保存または破棄しますか\? - 選択した色の設定は、この漫画のために記憶されます - 破棄 - デバイスに空き容量がありません - ページ切り替えスライダーを表示 - サーバーサイドエラー (%1$d) です。後で再試行してください - 新しいチャプターの情報も明確に - さまざまな言語 - ネットワークが利用できません - Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます - Webtoonズーム - コンパクト - マミミ - - ここには何もありません - 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 - サービス - デバッグ目的でいくつかのアクションを記録する - ミク - ユーザー エージェント ヘッダー - コンテンツのプリロード - ログを共有 - 不安定な更新を許可 - アプリのベータ版へのアップデートを提案する - ダウンロードが開始されました - 言語 - ソースが無効になっています - 現在としてマーク - ログ記録を有効にする - 疑わしいコンテンツを表示する - ダイナミック - 配色 - グリッドビューで表示 - アスカ - ミオン - リッカ - さくら - この変更を適用するには、アプリケーションを再起動してください - 項目をタップ&ホールドして並び替えをすることができます - .cbzまたは.zipファイルを1つ以上選択することができ、各ファイルは別のマンガとして認識されます。 - 了解 - 翻訳 - 過去に作成したユーザーデータのバックアップをインポートする - 棚に表示 - %1$s (%2$s) - 色を反転させる - 有効 - 結構です - ネットワークキャッシュをクリアする - ダウンロードは削除されました - 自分で用意した同期サーバーか、デフォルトのものを使用することができます。よく分からない場合は変更しないでください。 - 一時停止 - ダウンロードがキャンセルされました - WebViewが利用できません:WebView providerがインストールされているかどうかを確認してください - ダウンロード済み - 画像最適化プロキシ - wsrv.nl サービスを使用して、トラフィック使用量を削減し、可能であれば画像の読み込みを高速化します - アーカイブや画像のあるディレクトリを選択することができます。各アーカイブ(またはサブディレクトリ)は、1つのチャプターとして認識されます。 - 類似したものを探す - タイプ - アドレス - ポート - プロキシ - 同期の設定 - サーバーアドレス - 速度 - SSLエラーを無視する - ミラーを自動的に選択する - ミラーがある場合、エラー時にリモートソースのドメインを自動で切り替える - 履歴書 - 一時停止 - 全てキャンセル - Wi-Fi経由でのみダウンロード - モバイルデータ通信への切り替え時にダウンロードを停止する - 提案: %s - 提案されたマンガの通知を表示することがあります - もっと見る - アクティブなダウンロードはすべてキャンセルされ、部分的にダウンロードされたデータは失われます - ダウンロード履歴は完全に削除されます - ダウンロードはありません - ダウンロードが再開されました - ダウンロードが一時停止されました - パーソナライズされた漫画の提案を受け取りますか? - 削除が完了 - 既存のアカウントにサインインするか、新規にアカウントを作成することができます - 無効な値 - ユーザー名 - パスワード - オーソライズ(オプション) - \ No newline at end of file + + 探検 + アプリを終了するには、戻るを2回押してください + 保存したマンガ + チャプターなし + 自動スクロール + マンガのインポート + 続行するにはメールアドレスを入力してください + «探索»セクションで読むべきものを見つける + インポートが完了しました + あなたのマンガはここに表示されます + キャンセル + データの同期 + アカウントは既に存在します + 戻る + 過去 2 時間 + ブックマークはまだありません + 同期 + ページキャッシュ + 利用可能 + すべての履歴を消去する + 履歴が消去されました + 並べ替え + マンガを読みながらブックマークを作成することができます + ブックマークを削除しました + マンガのソースがない + マンガのソースを有効にして、オンラインでマンガを読めるようにする + もう一度戻るを押して終了します + %s -%s + 退出確認 + ストレージの使用状況 + その他のキャッシュ + シークレットモード + 画像を含むフォルダ + まもなくインポートが開始されます + お気に入りから削除 + オプション + ストレージから元のファイルを削除して、容量を節約することができます + Ch.%1$d/%2$d Pg.%3$d/%4$d + リーダーで情報バーを表示する + コミックアーカイブ + フィード + エラーの詳細:<br><tt>%1$s</tt><br><br>1. <a href=%2$s>Webブラウザで漫画を開いてみて</a>、そのソースで利用可能かどうか確認してください<br>2.<a href=kotatsu://about>最新版のこたつ</a><br>3.利用可能であれば、開発者にエラーレポートを送ってみてください。 + 人間工学に基づいたリーダーコントロール + 最近のマンガのショートカットを表示 + アプリケーションアイコンを長押しして最近のマンガを利用できるようにする + 右端をタップするか、右キーを押すと、常に次のページに切り替わります + 色補正 + 輝度 + コントラスト + リセット + 未保存の変更を保存または破棄しますか\? + 選択した色の設定は、この漫画のために記憶されます + 破棄 + デバイスに空き容量がありません + ページ切り替えスライダーを表示 + サーバーサイドエラー (%1$d) です。後で再試行してください + 新しいチャプターの情報も明確に + さまざまな言語 + ネットワークが利用できません + Wi-Fiまたはモバイルネットワークをオンにして、オンラインでマンガを読むことができます + Webtoonズーム + コンパクト + マミミ + + ここには何もありません + 読書の進捗状況を確認するには、マンガの詳細画面で「メニュー」→「追跡」を選択します。 + サービス + デバッグ目的でいくつかのアクションを記録する + ミク + ユーザー エージェント ヘッダー + コンテンツのプリロード + ログを共有 + 不安定な更新を許可 + アプリのベータ版へのアップデートを提案する + ダウンロードが開始されました + 言語 + ソースが無効になっています + 現在としてマーク + ログ記録を有効にする + 疑わしいコンテンツを表示する + ダイナミック + 配色 + グリッドビューで表示 + アスカ + ミオン + リッカ + さくら + この変更を適用するには、アプリケーションを再起動してください + 項目をタップ&ホールドして並び替えをすることができます + .cbzまたは.zipファイルを1つ以上選択することができ、各ファイルは別のマンガとして認識されます。 + 了解 + 翻訳 + 過去に作成したユーザーデータのバックアップをインポートする + 棚に表示 + %1$s (%2$s) + 色を反転させる + 有効 + 結構です + ネットワークキャッシュをクリアする + ダウンロードは削除されました + 自分で用意した同期サーバーか、デフォルトのものを使用することができます。よく分からない場合は変更しないでください。 + 一時停止 + ダウンロードがキャンセルされました + WebViewが利用できません:WebView providerがインストールされているかどうかを確認してください + ダウンロード済み + 画像最適化プロキシ + wsrv.nl サービスを使用して、トラフィック使用量を削減し、可能であれば画像の読み込みを高速化します + アーカイブや画像のあるディレクトリを選択することができます。各アーカイブ(またはサブディレクトリ)は、1つのチャプターとして認識されます。 + 類似したものを探す + タイプ + アドレス + ポート + プロキシ + 同期の設定 + サーバーアドレス + 速度 + SSLエラーを無視する + ミラーを自動的に選択する + ミラーがある場合、エラー時にリモートソースのドメインを自動で切り替える + 履歴書 + 一時停止 + 全てキャンセル + Wi-Fi経由でのみダウンロード + モバイルデータ通信への切り替え時にダウンロードを停止する + 提案: %s + 提案されたマンガの通知を表示することがあります + もっと見る + アクティブなダウンロードはすべてキャンセルされ、部分的にダウンロードされたデータは失われます + ダウンロード履歴は完全に削除されます + ダウンロードはありません + ダウンロードが再開されました + ダウンロードが一時停止されました + パーソナライズされた漫画の提案を受け取りますか? + 削除が完了 + 既存のアカウントにサインインするか、新規にアカウントを作成することができます + 無効な値 + ユーザー名 + パスワード + オーソライズ(オプション) + diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index 0eda0d4ec..da52aec1e 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -58,7 +58,6 @@ Суретті бөлісу Импорт Сипаттамасы жоқ - Тарих пен кәш Б|кБ|МБ|ГБ|ТБ Стандарт Уебтүн diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index d5a6ea14f..162338c1b 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -51,7 +51,6 @@ 저장됨 이미지 공유하기 ZIP 혹은 CBZ 파일을 선택하세요. - 기록 및 캐시 만화 제거 볼륨 키 결과 없음 @@ -202,7 +201,6 @@ 모든 검색 기록을 영구적으로 삭제 하시겠어요\? 더 읽기 대기열 - 이 챕터는 다운로드 하거나 온라인으로 읽어야 합니다. 모든 사이트에서 로그아웃됩니다 장르 완료됨 @@ -218,13 +216,11 @@ 아무 만화나 읽어보세요 당신의 기록을 바탕으로 개인화된 추천 만화를 제공합니다 활성화됨 필터 초기화 - 장르 찾기 와이파이에 연결된 경우에만 항상 무슨 언어의 만화를 읽을지 선택하세요. 나중에 설정에서 이를 변경할 수 있습니다. 18+ %1$s%% - 컨텐츠 페이지 미리 로드하기 %s로 로그인 됨 외관 diff --git a/app/src/main/res/values-nb-rNO/plurals.xml b/app/src/main/res/values-nb-rNO/plurals.xml index 0b7aaadbf..4659237c8 100644 --- a/app/src/main/res/values-nb-rNO/plurals.xml +++ b/app/src/main/res/values-nb-rNO/plurals.xml @@ -1,9 +1,5 @@ - - Totalt %1$d side - Totalt %1$d sider - %1$d nytt kapittel %1$d nye kapitler diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 80395c7b4..4884bfd7b 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -53,7 +53,6 @@ Nettserie Forvalg Tøm sidehurtiglager - Historikk og hurtiglager Velg en ZIP- eller CBZ-fil. Ustøttet handling Importer @@ -181,7 +180,6 @@ Historikk Favoritter Lokallagring - Last ned eller les dette manglende kapittelet på nett. Kapittelet mangler I kø Fullført @@ -214,7 +212,6 @@ Alltid Forhåndsinnlast bilder Tilbakestill filter - Finn sjanger Aldri Kun på Wi-Fi Velg språkene du ønsker å lese manga. Du kan endre dette senere i innstillingene. @@ -224,7 +221,6 @@ %1$s%% Forskjellige språk Ingen kapitler i denne mangaen - Innhold Utseende Navn Rediger diff --git a/app/src/main/res/values-ne/plurals.xml b/app/src/main/res/values-ne/plurals.xml index 67fc0c98b..b140ecec1 100644 --- a/app/src/main/res/values-ne/plurals.xml +++ b/app/src/main/res/values-ne/plurals.xml @@ -1,9 +1,5 @@ - - कुल %1$d पृष्ठ - कुल %1$d पृष्ठहरू - %1$d नयाँ अध्याय %1$d नयाँ अध्यायहरू diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 446981da9..4d4df7987 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1,142 +1,141 @@ - डाउनलोड गर्दै… - डाउनलोड गरेको - फिल्टर - अँध्यारो - खाली गर्नुहोस् - पृष्ठहरू - एउटा त्रुटि भयो - सूची मोड - सूची - पुनः प्रयास गर्नुहोस् - केही पनि फेला परेन - पढ्नुहोस् - लोकल भण्डारण - इतिहास - नेटवर्क त्रुटि - अध्यायहरू - सेटिङहरू - माङ्गा स्रोतहरू - लोड हुँदै… - इतिहास खाली गर्नुहोस् - अहिले कुनै मनपर्ने छैन - मनपर्ने मा राख्नुहोस् - नयाँ वर्ग - %s साझा गर्नुहोस् - खोज्नुहोस् - माङ्गा खोज्नुहोस् - प्रक्रिया गर्दैछ… - डाउनलोडहरू - नाम - अपडेट गरिएको - नवीनतम - क्रमबद्ध क्रम - थीम - उज्यालो - सिस्टम पालना गर्नुहोस् - कम्प्युटिङ… - मनपर्नेहरू - विवरणहरू - विस्तृत सूची - ग्रिड - %2$d को अध्याय %1$d - बन्द गर्नुहोस् - अहिलेसम्म इतिहास छैन - थप्नुहोस् - बचत गर्नुहोस् - साझा गर्नुहोस् - सर्टकट सिर्जना गर्नुहोस्… - लोकप्रिय - मूल्याङ्कन - नयाँ अध्यायहरू - सबै पढेको इतिहास स्थायी रूपमा खाली गर्ने हो\? - हटाउनुहोस् - लोकल भण्डारणबाट %s हटाइयो - सेभ गरियो - पृष्ठ सेभ गर्नुहोस् - छवि साझा गर्नुहोस् - आयात गर्नुहोस् - स्ट्यानडर्ड - वेबटून - पढ्ने मोड - ग्रिड साइज - यन्त्रबाट %s स्थायी रूपमा हटाउने हो\? - रिडर सेटिङहरू - %s मा खोज्नुहोस् - माङ्गा हटाउनुहोस् - पृष्ठ स्विच गर्नुहोस् - किनारा ट्यापहरू - भोल्युम बटन - जारी राख्नुहोस् - त्रुटि - खाली गरियो - जेस्चर मात्र - थम्बनेल क्यास खाली गर्नुहोस् - खोज इतिहास खाली गर्नुहोस् - डोमेन - यो माङ्गामा %s छ। यो सबै सेभ गर्ने\? - आन्तरिक भण्डारण - एपको नयाँ संस्करण उपलब्ध छ - बाह्य भण्डारण - वेब ब्राउजरमा खोल्नुहोस् - डाउनलोड - सूचना सेटिङ - LED सूचक - भाईब्रेशन - मनपर्ने वर्गहरू - हटाउनुहोस् - यहाँ अलि खाली जस्तो छ… - सोधपुछ सुधार गर्ने प्रयास गर्नुहोस्। - तपाईँले पढेको कुरा यहाँ देखाइनेछ - साइड मेनुमा के पढ्ने फेला पार्नुहोस्। - पृष्ठ एनिमेसन - डाउनलोडका लागि फोल्डर - हालैका - उपलब्ध छैन - तपाईंले पढिरहनु भएको माङ्गाको नयाँ अध्यायहरू यहाँ देखाइएको छ - खोज परिणामहरू - अपडेट फिड खाली गर्नुहोस् - स्क्रिन घुमाउनुहोस् - अपडेट - पासवर्डहरू म्याच गरेनन् - बारेमा - संस्करण %s - यो अपरेशन समर्थित छैन - कुनै विवरण छैन - इतिहास र क्यास - पृष्ठ क्यास खाली गर्नुहोस् - सूचना आवाज - पहिले केही सेभ गर्नुहोस् - यसलाई अनलाइन स्रोतहरूबाट सेभ गर्नुहोस् वा फाइलहरू आयात गर्नुहोस्। - खाली गरियो - एप सुरक्षित गर्नुहोस् - Kotatsu सुरु गर्दा पासवर्ड माग्नुहोस् - पासवर्ड दोहोर्याउनुहोस् - हटाउनुहोस् - या त ZIP वा CBZ फाइल छान्नुहोस्। - B|kB|MB|GB|TB - सेभ - सूचनाहरू - %2$d को %1$d अन - तपाईंको माङ्गा यहाँ देखाउनेछ - «अन्वेषण» भागमा के पढ्ने फेला पार्नुहोस् - दराज - भण्डारण उपलब्ध छैन - अन्य भण्डारण - सकियो - सबै मनपर्नेहरू - खाली वर्ग - पछि पढ्ने - अपडेटहरू - नयाँ संस्करण: %s - साइज: %s - फिड अपडेट चाँडै सुरु हुनेछ - अपडेटहरू खोज्नुहोस् - जाँच नगर्नुहोस् - गलत पासवर्ड - अपडेटका लागि जाँच गर्नुहोस् - कुनै अपडेट उपलब्ध छैन - अन्वेषण - पासवर्ड एन्टर गर्नुहोस् - \ No newline at end of file + डाउनलोड गर्दै… + डाउनलोड गरेको + फिल्टर + अँध्यारो + खाली गर्नुहोस् + पृष्ठहरू + एउटा त्रुटि भयो + सूची मोड + सूची + पुनः प्रयास गर्नुहोस् + केही पनि फेला परेन + पढ्नुहोस् + लोकल भण्डारण + इतिहास + नेटवर्क त्रुटि + अध्यायहरू + सेटिङहरू + माङ्गा स्रोतहरू + लोड हुँदै… + इतिहास खाली गर्नुहोस् + अहिले कुनै मनपर्ने छैन + मनपर्ने मा राख्नुहोस् + नयाँ वर्ग + %s साझा गर्नुहोस् + खोज्नुहोस् + माङ्गा खोज्नुहोस् + प्रक्रिया गर्दैछ… + डाउनलोडहरू + नाम + अपडेट गरिएको + नवीनतम + क्रमबद्ध क्रम + थीम + उज्यालो + सिस्टम पालना गर्नुहोस् + कम्प्युटिङ… + मनपर्नेहरू + विवरणहरू + विस्तृत सूची + ग्रिड + %2$d को अध्याय %1$d + बन्द गर्नुहोस् + अहिलेसम्म इतिहास छैन + थप्नुहोस् + बचत गर्नुहोस् + साझा गर्नुहोस् + सर्टकट सिर्जना गर्नुहोस्… + लोकप्रिय + मूल्याङ्कन + नयाँ अध्यायहरू + सबै पढेको इतिहास स्थायी रूपमा खाली गर्ने हो\? + हटाउनुहोस् + लोकल भण्डारणबाट %s हटाइयो + सेभ गरियो + पृष्ठ सेभ गर्नुहोस् + छवि साझा गर्नुहोस् + आयात गर्नुहोस् + स्ट्यानडर्ड + वेबटून + पढ्ने मोड + ग्रिड साइज + यन्त्रबाट %s स्थायी रूपमा हटाउने हो\? + रिडर सेटिङहरू + %s मा खोज्नुहोस् + माङ्गा हटाउनुहोस् + पृष्ठ स्विच गर्नुहोस् + किनारा ट्यापहरू + भोल्युम बटन + जारी राख्नुहोस् + त्रुटि + खाली गरियो + जेस्चर मात्र + थम्बनेल क्यास खाली गर्नुहोस् + खोज इतिहास खाली गर्नुहोस् + डोमेन + यो माङ्गामा %s छ। यो सबै सेभ गर्ने\? + आन्तरिक भण्डारण + एपको नयाँ संस्करण उपलब्ध छ + बाह्य भण्डारण + वेब ब्राउजरमा खोल्नुहोस् + डाउनलोड + सूचना सेटिङ + LED सूचक + भाईब्रेशन + मनपर्ने वर्गहरू + हटाउनुहोस् + यहाँ अलि खाली जस्तो छ… + सोधपुछ सुधार गर्ने प्रयास गर्नुहोस्। + तपाईँले पढेको कुरा यहाँ देखाइनेछ + साइड मेनुमा के पढ्ने फेला पार्नुहोस्। + पृष्ठ एनिमेसन + डाउनलोडका लागि फोल्डर + हालैका + उपलब्ध छैन + तपाईंले पढिरहनु भएको माङ्गाको नयाँ अध्यायहरू यहाँ देखाइएको छ + खोज परिणामहरू + अपडेट फिड खाली गर्नुहोस् + स्क्रिन घुमाउनुहोस् + अपडेट + पासवर्डहरू म्याच गरेनन् + बारेमा + संस्करण %s + यो अपरेशन समर्थित छैन + कुनै विवरण छैन + पृष्ठ क्यास खाली गर्नुहोस् + सूचना आवाज + पहिले केही सेभ गर्नुहोस् + यसलाई अनलाइन स्रोतहरूबाट सेभ गर्नुहोस् वा फाइलहरू आयात गर्नुहोस्। + खाली गरियो + एप सुरक्षित गर्नुहोस् + Kotatsu सुरु गर्दा पासवर्ड माग्नुहोस् + पासवर्ड दोहोर्याउनुहोस् + हटाउनुहोस् + या त ZIP वा CBZ फाइल छान्नुहोस्। + B|kB|MB|GB|TB + सेभ + सूचनाहरू + %2$d को %1$d अन + तपाईंको माङ्गा यहाँ देखाउनेछ + «अन्वेषण» भागमा के पढ्ने फेला पार्नुहोस् + दराज + भण्डारण उपलब्ध छैन + अन्य भण्डारण + सकियो + सबै मनपर्नेहरू + खाली वर्ग + पछि पढ्ने + अपडेटहरू + नयाँ संस्करण: %s + साइज: %s + फिड अपडेट चाँडै सुरु हुनेछ + अपडेटहरू खोज्नुहोस् + जाँच नगर्नुहोस् + गलत पासवर्ड + अपडेटका लागि जाँच गर्नुहोस् + कुनै अपडेट उपलब्ध छैन + अन्वेषण + पासवर्ड एन्टर गर्नुहोस् + diff --git a/app/src/main/res/values-nn/plurals.xml b/app/src/main/res/values-nn/plurals.xml index ed6c18ca4..c0fc3296b 100644 --- a/app/src/main/res/values-nn/plurals.xml +++ b/app/src/main/res/values-nn/plurals.xml @@ -16,10 +16,6 @@ %1$d element %1$d element - - I alt %1$d side - I alt %1$d sider - %1$d nytt kapittel %1$d nye kapittel diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 905125266..52fa0b42f 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -1,362 +1,358 @@ - Det hende ein feil - Rutenett - Innstillingar - Mangakjelder - Tøm historikken - Historikken er tom - Les - Lik - Ny hop - Legg til - Hent - Lag ein snarveg … - Del %s - Søk - Søk manga - Hentar … - Handsamar … - Henta - Nyaste - Omdøme - Sil ut - Ljos - Sider - Tøm - Tøm lesehistorikken for godt\? - Tak bort - Hent sida - Henta - Del biletet - Før inn - Slett - Vel ei ZIP- eller CBZ-fil. - Ingen utgreiing - Tøm mellomminnet til sida - Vanleg - Nettserie - Rutenettstorleik - Slett mangaen - Slett «%s» ifrå eininga\? - Leseinnstillingar - Bla med - Hald fram - Feil - Tøm mellomminnet for småbilete - Tøm søkehistorikken - Tømt - Berre handvendingar - Hent - Varsel - %1$d av %2$d - Hent - Varselinnstillingar - Varselljod - Varselljos - Dirring - Hopar til leiting - Hent ifrå nettkjelder eller før inn filer. - Hylla - Nytt - Legg henta mangaar i: - Ferdig - Alt du likar - Tom hop - Les seinare - Oppdateringar - Søkesvar - Ny utgåve: %s - Tømt - Snu skjermen - Leit etter oppdateringar - Nei - Om - Leit etter oppdateringar - Høgre-til-venstre - Lesevising - Høv til høgda - Høv til breidda - Svart - Tryggleikskopiering og gjenoppretting - Lag ein tryggleikskopi - Gjenoppretta - Fann ikkje fila - Gjenoppretta all data - Gjenoppretta dataa, men med feil - Trykk for å røyna att - Listeslag - Henta - Likar - Historikk - Nettverksfeil - Liste - Hentar fram … - Steng - Røyn att - Fann ikkje noko - Del - Henta - Namn - Oppdatert - Vising - Lyd systemet - Mørk - Historikken og mellomminnet - Hent noko først - Ikkje tilgjengeleg - Oppdater - Storleik: %s - Brukar mindre straum på AMOLED-skjermar - Utgåve %s - Ingen tilgjengelege oppdateringar - Ny hop - Midtstill - Auk byrjinga av sida - Gjenopprett ifrå ein tryggleikskopi - Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting - Førebur … - Forval - No - I dag - I går - Lenge sida - Lesing - Randetrykk - Ljodstyrkeknappar - Ei ny utgåve av appen er tilgjengeleg - Opne i ein nettlesar - Denne mangaen har %s. Hent alle\? - Det du les vert vist her - Rit inn lykelordet - Gjentak lykelordet - Lykelorda er ulike - Brigde av oppsettet vedkjem berre denne mangaen - Stille - Krev CAPTCHA - Løys - Slett infokapslane - Sletta infokapslane - Tøm oppdateringshistorikken\? - Logg inn - Neste - Stadfest - Lykelordet må vera lengre enn fire teikn - Tryggleikskopi laga - Les meir - I kø - Omset denne appen - Omsetjing - Godkjend - Slag - Fullgjort - I gang - Utelèt mangaar med vakse innhald ifrå historikken - Sidetal - Nytta kjelder - Tilgjengelege kjelder - Skjermbilete - Hindre alltid - Råd - Slå på råd - Rå om mangaar ut ifrå det du har lese - Byrja å lesa nokre mangaar for å få personlege råd - Ikkje rå mangaar med vakse innhald - Påslegen - Kunne ikkje hente inn slaglista - Finn slag - Ulike mål - %1$s%% - Innhald - Oppdaterer råd - Utelat slag - Sletta - Avgrens hentesnøggleiken - Lægjer vona for at IP-adressa di vert blokkert - Handsamar henta manga - Avbroten - Kontoen finst alt - Attende - Synkroniser dataet ditt - Rit inn e-postadressa di for å halda fram - Skjul - Namn - Brigd - Brigd hopen - Sporing - Ingen likte hopar - Logg ut - Bokmerk - Tak bort bokmerket - Bokmerke - Teken bort ifrå historikken - DNS over HTTPS - Forvald lesing - Finn sjølvverkande ut av lesing - Finn sjølvverkande ut av om mangaen er ein nettserie - Slå av batterilenging - Send - Les - Skal lesa - Les att - Lesen - På vent - Gjeven opp - Slå av alle - Mangaar du har nyleg lese - Sletting av data - Vis % lesen i historikken og likerlista - Kan løysa nokre feil. Alle godkjenningar vert ugilde - Vis alle - Ugildt domene - Vel område - Tøm heile historikken - Tømte historikken - Ingen bokmerke endå - Du kan lage bokmerke medan du les - Tok bort bokmerka - Ingen mangakjelder - Slå på minst ei mangakjelde for å lesa mangaar på nett - Tilfeldig - Flytt - Tom - Trykk Attende att for å gå or appen - Utgåingsstadfesting - Mellominnet for sider - Mellomminnet for anna - Tilgjengeleg - %s - %s - Teken or likerlista - Fann ikkje innhaldet - Bla sjølvverkande - Teikneseriearkiv - Mappe med bilete - Fører inn manga - Brigd letar - Ljosstyrk - Still attende - Spar eller avvis dei usparte brigda\? - Avvis - Eininga er fylt - Vis ei rulleline til blading - Auk/mink nettseriar - Ulike mål - Nettverk ikkje tilgjengeleg - Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett - Tjenarfeil (%1$d). Røyn att seinare - Kjelde avslegen - Hent inn innhald på forhand - Merk som aktuelt - Mål - Del loggføringar - Slå på loggføring - Tak opp nokre gjerder til bruk i istandsetjing. - Skiftande - Letar - Vis som rutenett - Rikka - Asuka - Sakura - Mamimi - Kanade - Ingenting her - Tenester - Har byrja å hente - Tøm søkehistorikken\? - Velkomen - Du vert logga ut ifrå alle kjeldane - Hindre ved vakse innhald - Slett - Her var det tomt … - Spør om lykelordet ved byrjing av appen - Feil lykelord - Vern appen - Logg inn for å sjå dette innhaldet - Vern appen med eit lykelord - All data vert handsama på eininga di og vert ikkje førte over til noka teneste - Avslegen - Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. - Aldri - Berre på Wi-Fi - 18+ - Alltid - Hent sider på forhand - Utsjånaden - Slett valde ting ifrå eininga di\? - Logga inn som %s - Opplys om kva slags slag du ikkje vil få råd om - Synkronisering - Nye mangakjelder tilgjengelege - Du kjem til å få varsel når mangaar du les vert oppdaterte - Slå på varsel - La til eit bokmerke - Tok bort bokmerket - Angre - Nytt fingermerke om tilgjengeleg - Vis leseframgang - Mangaar du likar - Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart - Slett dei valde hopane\? + Det hende ein feil + Rutenett + Innstillingar + Mangakjelder + Tøm historikken + Historikken er tom + Les + Lik + Ny hop + Legg til + Hent + Lag ein snarveg … + Del %s + Søk + Søk manga + Hentar … + Handsamar … + Henta + Nyaste + Omdøme + Sil ut + Ljos + Sider + Tøm + Tøm lesehistorikken for godt\? + Tak bort + Hent sida + Henta + Del biletet + Før inn + Slett + Vel ei ZIP- eller CBZ-fil. + Ingen utgreiing + Tøm mellomminnet til sida + Vanleg + Nettserie + Rutenettstorleik + Slett mangaen + Slett «%s» ifrå eininga\? + Leseinnstillingar + Bla med + Hald fram + Feil + Tøm mellomminnet for småbilete + Tøm søkehistorikken + Tømt + Berre handvendingar + Hent + Varsel + %1$d av %2$d + Hent + Varselinnstillingar + Varselljod + Varselljos + Dirring + Hopar til leiting + Hent ifrå nettkjelder eller før inn filer. + Hylla + Nytt + Legg henta mangaar i: + Ferdig + Alt du likar + Tom hop + Les seinare + Oppdateringar + Søkesvar + Ny utgåve: %s + Tømt + Snu skjermen + Leit etter oppdateringar + Nei + Om + Leit etter oppdateringar + Høgre-til-venstre + Lesevising + Høv til høgda + Høv til breidda + Svart + Tryggleikskopiering og gjenoppretting + Lag ein tryggleikskopi + Gjenoppretta + Fann ikkje fila + Gjenoppretta all data + Gjenoppretta dataa, men med feil + Trykk for å røyna att + Listeslag + Henta + Likar + Historikk + Nettverksfeil + Liste + Hentar fram … + Steng + Røyn att + Fann ikkje noko + Del + Henta + Namn + Oppdatert + Vising + Lyd systemet + Mørk + Hent noko først + Ikkje tilgjengeleg + Oppdater + Storleik: %s + Brukar mindre straum på AMOLED-skjermar + Utgåve %s + Ingen tilgjengelege oppdateringar + Ny hop + Midtstill + Auk byrjinga av sida + Gjenopprett ifrå ein tryggleikskopi + Du kan tryggleikskopiera historikken og likerlista di til seinare gjenoppretting + Førebur … + Forval + No + I dag + I går + Lenge sida + Lesing + Randetrykk + Ljodstyrkeknappar + Ei ny utgåve av appen er tilgjengeleg + Opne i ein nettlesar + Denne mangaen har %s. Hent alle\? + Det du les vert vist her + Rit inn lykelordet + Gjentak lykelordet + Lykelorda er ulike + Brigde av oppsettet vedkjem berre denne mangaen + Stille + Krev CAPTCHA + Løys + Slett infokapslane + Sletta infokapslane + Tøm oppdateringshistorikken\? + Logg inn + Neste + Stadfest + Lykelordet må vera lengre enn fire teikn + Tryggleikskopi laga + Les meir + I kø + Omset denne appen + Omsetjing + Godkjend + Slag + Fullgjort + I gang + Utelèt mangaar med vakse innhald ifrå historikken + Sidetal + Nytta kjelder + Tilgjengelege kjelder + Skjermbilete + Hindre alltid + Råd + Slå på råd + Rå om mangaar ut ifrå det du har lese + Byrja å lesa nokre mangaar for å få personlege råd + Ikkje rå mangaar med vakse innhald + Påslegen + Kunne ikkje hente inn slaglista + Ulike mål + %1$s%% + Oppdaterer råd + Utelat slag + Sletta + Avgrens hentesnøggleiken + Lægjer vona for at IP-adressa di vert blokkert + Handsamar henta manga + Avbroten + Kontoen finst alt + Attende + Synkroniser dataet ditt + Rit inn e-postadressa di for å halda fram + Skjul + Namn + Brigd + Brigd hopen + Sporing + Ingen likte hopar + Logg ut + Bokmerk + Tak bort bokmerket + Bokmerke + Teken bort ifrå historikken + DNS over HTTPS + Forvald lesing + Finn sjølvverkande ut av lesing + Finn sjølvverkande ut av om mangaen er ein nettserie + Slå av batterilenging + Send + Les + Skal lesa + Les att + Lesen + På vent + Gjeven opp + Slå av alle + Mangaar du har nyleg lese + Sletting av data + Vis % lesen i historikken og likerlista + Kan løysa nokre feil. Alle godkjenningar vert ugilde + Vis alle + Ugildt domene + Vel område + Tøm heile historikken + Tømte historikken + Ingen bokmerke endå + Du kan lage bokmerke medan du les + Tok bort bokmerka + Ingen mangakjelder + Slå på minst ei mangakjelde for å lesa mangaar på nett + Tilfeldig + Flytt + Tom + Trykk Attende att for å gå or appen + Utgåingsstadfesting + Mellominnet for sider + Mellomminnet for anna + Tilgjengeleg + %s - %s + Teken or likerlista + Fann ikkje innhaldet + Bla sjølvverkande + Teikneseriearkiv + Mappe med bilete + Fører inn manga + Brigd letar + Ljosstyrk + Still attende + Spar eller avvis dei usparte brigda\? + Avvis + Eininga er fylt + Vis ei rulleline til blading + Auk/mink nettseriar + Ulike mål + Nettverk ikkje tilgjengeleg + Slå på Wi-Fi eller mobilnettverk for å lesa mangaar på nett + Tjenarfeil (%1$d). Røyn att seinare + Kjelde avslegen + Hent inn innhald på forhand + Merk som aktuelt + Mål + Del loggføringar + Slå på loggføring + Tak opp nokre gjerder til bruk i istandsetjing. + Skiftande + Letar + Vis som rutenett + Rikka + Asuka + Sakura + Mamimi + Kanade + Ingenting her + Tenester + Har byrja å hente + Tøm søkehistorikken\? + Velkomen + Du vert logga ut ifrå alle kjeldane + Hindre ved vakse innhald + Slett + Her var det tomt … + Spør om lykelordet ved byrjing av appen + Feil lykelord + Vern appen + Logg inn for å sjå dette innhaldet + Vern appen med eit lykelord + All data vert handsama på eininga di og vert ikkje førte over til noka teneste + Avslegen + Vel måla du vil lesa mangaar på. Du kan brigde på dette seinare i innstillingane. + Aldri + Berre på Wi-Fi + 18+ + Alltid + Hent sider på forhand + Utsjånaden + Slett valde ting ifrå eininga di\? + Logga inn som %s + Opplys om kva slags slag du ikkje vil få råd om + Synkronisering + Nye mangakjelder tilgjengelege + Du kjem til å få varsel når mangaar du les vert oppdaterte + Slå på varsel + La til eit bokmerke + Tok bort bokmerket + Angre + Nytt fingermerke om tilgjengeleg + Vis leseframgang + Mangaar du likar + Mangaar merkte med vakse innhald vert ikkje lagde til i historikken din, og framgangen din vert ikkje spart + Slett dei valde hopane\? \nDu kan ikkje angre. Alle mangaane inni vert tekne ut av likerlista. - Innstillingar - Dei siste to timane - Handsam - Trykk Attende to gongar for å gå or appen - Henta mangaar - Privat modus - Førte inn - Slett den opphavlege fila for å frigjera rom - Byrjar å føra inn snart - Motsetjing - Brigde av letane vedkjem berre denne mangaen - Vis mistenksamt innhald - Mion - Miku - Byrja om appen for å nytta desse brigda - Kapittel - Utreknar… - Kapittel %1$d av %2$d - Ustødd gjerd - B|kB|MB|GB|TB - Domene - Nye kapittel - Mangaane dine vert viste her - Siderørsle - Nye kapittel av det du les vert viste her - Sjå etter nye kapittel - Siste øvst - Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. - Hent eller les dette saknande kapittelet på nettet. - Saknar kapittelet - Finn kapittel - Ingen kapittel i denne mangaen - Kapittel vert teken bort i bakgrunnen - Sjå etter og varsle om nye kapittel - Nye kapittel vert merkte i listene utan varsel - Gransk - Ingen kapittel - Ka. %1$d/%2$d Side %3$d/%4$d - Vis opplysingsområde i lesevisinga - Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side - Samantrengt - Vis i hylla - Før inn ei tryggleikskopi av brukardata - Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. - Snøggleik - Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. - Tøm au opplysingar om nye kapittel - Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. - Skjønar - Trykk og hald på eit element for å flytta på det - Sletta «%s» ifrå eininga - Indre gøyme - Ytre gøyme - Ingen tilgjengelege gøyme - Anna gøyme - Røyn å skriva det om. - Ingen likte enno - Mest lest for tida - Søk på %s - Finn lesnadar i sidemenyen. - Finn lesnadar i «Gransk»-delen - \ No newline at end of file + Innstillingar + Dei siste to timane + Handsam + Trykk Attende to gongar for å gå or appen + Henta mangaar + Privat modus + Førte inn + Slett den opphavlege fila for å frigjera rom + Byrjar å føra inn snart + Motsetjing + Brigde av letane vedkjem berre denne mangaen + Vis mistenksamt innhald + Mion + Miku + Byrja om appen for å nytta desse brigda + Kapittel + Utreknar… + Kapittel %1$d av %2$d + Ustødd gjerd + B|kB|MB|GB|TB + Domene + Nye kapittel + Mangaane dine vert viste her + Siderørsle + Nye kapittel av det du les vert viste her + Sjå etter nye kapittel + Siste øvst + Nokre einingar har systemåtferd som kan knuse bakgrunnsføreloger. + Saknar kapittelet + Finn kapittel + Ingen kapittel i denne mangaen + Kapittel vert teken bort i bakgrunnen + Sjå etter og varsle om nye kapittel + Nye kapittel vert merkte i listene utan varsel + Gransk + Ingen kapittel + Ka. %1$d/%2$d Side %3$d/%4$d + Vis opplysingsområde i lesevisinga + Trykk på høgre side eller ljodstyrke-ned-knappen blar alltid til neste side + Samantrengt + Vis i hylla + Før inn ei tryggleikskopi av brukardata + Du kan velja ei mappe med arkiv eller bilete. Kvart arkiv (eller undermappe) vert tydde som eit kapittel. + Snøggleik + Vel ei eller fleire .cbz eller .zip-filer, kvar fil vert tydde som ein eigen manga. + Tøm au opplysingar om nye kapittel + Trykk «Meny → Spor» på ei mangadetaljside for å spore leseframdrifta. + Skjønar + Trykk og hald på eit element for å flytta på det + Sletta «%s» ifrå eininga + Indre gøyme + Ytre gøyme + Ingen tilgjengelege gøyme + Anna gøyme + Røyn å skriva det om. + Ingen likte enno + Mest lest for tida + Søk på %s + Finn lesnadar i sidemenyen. + Finn lesnadar i «Gransk»-delen + diff --git a/app/src/main/res/values-or/plurals.xml b/app/src/main/res/values-or/plurals.xml index 9a190afa8..3c8d454dd 100644 --- a/app/src/main/res/values-or/plurals.xml +++ b/app/src/main/res/values-or/plurals.xml @@ -1,27 +1,23 @@ - - %1$d ମିନିଟ୍ ପୂର୍ଵେ - %1$d ମିନିଟ୍ ପୂର୍ଵେ - - - %1$d ଦିନ ପୂର୍ଵେ - %1$d ଦିନ ପୂର୍ଵେ - - - %1$dଟିଏ ନୂଆ ଅଧ୍ୟାୟ - %1$dଟି ନୂଆ ଅଧ୍ୟାୟ - - - ମୋଟ %1$dଟିଏ ପୃଷ୍ଠା - ମୋଟ %1$dଟି ପୃଷ୍ଠା - - - %1$d ଘଣ୍ଟା ପୂର୍ଵେ - %1$d ଘଣ୍ଟା ପୂର୍ଵେ - - - %1$dଟିଏ ଅଧ୍ୟାୟ - %1$dଟି ଅଧ୍ୟାୟ - - \ No newline at end of file + + %1$d ମିନିଟ୍ ପୂର୍ଵେ + %1$d ମିନିଟ୍ ପୂର୍ଵେ + + + %1$d ଦିନ ପୂର୍ଵେ + %1$d ଦିନ ପୂର୍ଵେ + + + %1$dଟିଏ ନୂଆ ଅଧ୍ୟାୟ + %1$dଟି ନୂଆ ଅଧ୍ୟାୟ + + + %1$d ଘଣ୍ଟା ପୂର୍ଵେ + %1$d ଘଣ୍ଟା ପୂର୍ଵେ + + + %1$dଟିଏ ଅଧ୍ୟାୟ + %1$dଟି ଅଧ୍ୟାୟ + + diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index b55162b4b..0e883613f 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -1,29 +1,28 @@ - ଇତିଵୃତ୍ତି - ଵିଵରଣୀ - ସେଟିଂ - ପରାମର୍ଶ: %s - ହେଲା - ସେଵା - ବୁଝିଗଲି - କଳା - ଥିମ୍ - ଵେଗ - ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା - ପାଠକ ସେଟିଂ - ଵିଜ୍ଞପ୍ତି - ଥାକ - ସର୍ଵଦା - ଵିଷୟଵସ୍ତୁ - ଵିଜ୍ଞପ୍ତି ସେଟିଂ - ରୂପ - ଯାଞ୍ଚ କରନି - ଅଦ୍ୟତନ ପାଇଁ ଯାଞ୍ଚ କରିବା - ଗତକାଲି - ଆଜି - ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରି ଏହା ଵିଷୟରେ ସୂଚିତ କରିବା - ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରିବା - ଫାଇଲ ମିଳୁନାହିଁ - ବ୍ୟାକଅପ୍ ଓ ପୁନରୁଦ୍ଧାର - \ No newline at end of file + ଇତିଵୃତ୍ତି + ଵିଵରଣୀ + ସେଟିଂ + ପରାମର୍ଶ: %s + ହେଲା + ସେଵା + ବୁଝିଗଲି + କଳା + ଥିମ୍ + ଵେଗ + ଡାଉନଲୋଡ୍ ଆରମ୍ଭ ହେଲା + ପାଠକ ସେଟିଂ + ଵିଜ୍ଞପ୍ତି + ଥାକ + ସର୍ଵଦା + ଵିଜ୍ଞପ୍ତି ସେଟିଂ + ରୂପ + ଯାଞ୍ଚ କରନି + ଅଦ୍ୟତନ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଗତକାଲି + ଆଜି + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରି ଏହା ଵିଷୟରେ ସୂଚିତ କରିବା + ନୂଆ ଅଧ୍ୟାୟ ପାଇଁ ଯାଞ୍ଚ କରିବା + ଫାଇଲ ମିଳୁନାହିଁ + ବ୍ୟାକଅପ୍ ଓ ପୁନରୁଦ୍ଧାର + diff --git a/app/src/main/res/values-pl/plurals.xml b/app/src/main/res/values-pl/plurals.xml index 2779a1496..8a68c940e 100644 --- a/app/src/main/res/values-pl/plurals.xml +++ b/app/src/main/res/values-pl/plurals.xml @@ -10,11 +10,6 @@ %1$d minuty temu %1$d minut temu - - Łącznie %1$d strona - Łącznie %1$d strony - Łącznie %1$d stron - %1$d godzinę temu %1$d godziny temu diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 9dc982b98..e99ab579a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,420 +1,416 @@ - Ulubione - Historia - Napotkano błąd - Szczegółowy - Rozdziały - Lista - Lista szczegółowa - Siatka - Tryb listy - Ustawienia - Ładowanie… - Rozdział %1$d z %2$d - Zamknij - Wyczyść historię - Dodaj - Zapisz - Udostępnij - Szukaj - Szukaj mang - Pobieranie… - Pobrano - Pobrane - Nazwa - Popularność - Najnowsze - Ocena - Filtry - Jasny - Ciemny - Strony - Wyczyść - Usuń - Udostępnij zdjęcie - Usuń - Brak opisu - Tryb czytania - Błąd sieci - Obliczanie… - Spróbuj ponownie - Nic nie znaleziono - Brak historii - Czytaj - Brak ulubionych - Dodaj do ulubionych - Nowa kategoria - Stwórz skrót… - Udostępnij %s - Przetwarzanie… - Zaktualizowane - Zapisz stronę - Zapisano - Wibracje - Biblioteka - Ostatnie - Tryb czarny - Przygotowywanie… - Plik nieznaleziony - Wczoraj - Dawno temu - Grupa - Dzisiaj - Zaloguj - Dalej - Potwierdź - Witaj - Skończone - W trakcie - Zezwól - Proponowane - Włącz propozycje - Włączone - Wyłączone - Nigdy - Zawsze - Znajdź rozdział - %1$s%% - Wygląd - Schowaj - Synchronizacja - Synchronizuj swoje dane - Nazwa - Edytuj - Wyloguj - Cofnij - Wyślij - Planowane - Czytane - Czytane ponownie - Skończone - Pokaż wszystkie - Wybierz zakres - Wyczyść całą historię - Ostatnie 2 godziny - Historia wyczyszczona - Zarządzaj - Losowe - Puste - Przeglądaj - Dostępne - Ustawienia - Źródło wyłączone - Kompaktowy - Błąd po stronie serwera (%1$d). Sprónuj ponownie później - Sieć niedostępna - Inne języki - Odrzuć - Jasność - Kontrast - Korekcja kolorów - Automatyczne przewijanie - Brak rozdziałów - Tryb incognito - Usunięto z ulubionych - Wykorzystana pamięć - Zapisane mangi - Brak zakładek - Możesz tworzyć zakładki w trakcie czytania mangi - Zakładki usunięte - Twoje ostatnio czytane mangi - Wyłącz wszystkie - Wyłącz optymalizację baterii - Autowykrywanie trybu czytania - Usunięte z historii - Dodano zakładkę - Usunięto zakładkę - Zakładki - Usuń zakładkę - Dodaj zakładkę - Brak ulubionych kategorii - Edytuj kategorię - Włącz powiadomienia - Wróć - Konto już istnieje - Anulowano - Zwolnienie pobierania - Brak rozdziałów w tej mandze - Różne języki - Tylko na Wi-Fi - Zawsze blokuj - Gatunki - Znajdź gatunek - Czytaj więcej - Rozwiąż - Wymagane CAPTCHA - Cichy - Dotknij aby spróbować ponownie - Teraz - Przywrócone - Dopasuj do szerokości - Dopasuj do wysokości - Dopasuj do środka - Nowa kategoria - Brak nowych aktualizacji - Sprawdź dostępność aktualizacji - Wersja %s - O aplikacji - Usuń - Jest tu dosyć pusto… - Ulubione kategorie - Powiadomienie LED - Nowe rozdziały - Pamięć wewnętrzna - Tutaj będą wyświetlane Twoje mangi - Znajdź materiały do czytania w zakładce „Przeglądaj” - W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz - Strony w pamięci podręcznej - Animacja przewracania strony - Inne rzeczy w pamięci podręcznej - Otwórz w przeglądarce - Numerowane strony - Powiadomienia - Dźwięk powiadomień - Ustawienia powiadomień - Zewnętrzne źródła - Motyw - Systemowy - Historia i pamięć podręczna - Wyczyść pamięć podręczną stron - B|kB|MB|GB|TB - Wielkość siatki - Szukaj na %s - Usuń mangę - Dalej - Błąd - Wyczyszczone - Pamięć wewnętrzna - Pamięć zewnętrzna - Domena - Nowa wersja aplikacji jest dostępna - Ta manga ma %s. Zapisać wszystko? - Zapisz - Pobierz - Najpierw coś zapisz - Niedostępne - Zapisz - Wszystkie ulubione - Pusta kategoria - Czytaj później - Aktualizacje - Nowa wersja: %s - Wielkość: %s - Obróć ekran - Odśwież - Szukaj aktualizacji - Nie sprawdzaj - Wprowadź hasło - Złe hasło - Chroń aplikację - Pytaj o hasło przy starcie Kotatsu - Wprowadź ponownie hasło - Zużywa mniej prądu na ekranach AMOLED - Kopia zapasowa i przywracanie - Utwórz kopię zapasową danych - Przywróć z kopii zapasowej - 18+ - %1$d na %2$d włączone - Standardowy - Webtoon - Ustawienia czytnika - Zmiana strony - Przyciski głośności - Dotknięcie krawędzi - Wyczyszczone - Tryb skalowania - Wyczyść ciasteczka - Wszystkie ciasteczka wyczyszczone - Przetłumacz tą aplikację - Tłumaczenie - Dostępne źródła - Tylko gesty - Brak dostępnej pamięci - Inny - Wyniki wyszukiwania - Wszystkie dane zostały przywrócone - Dane zostały przywrócone, ale z błędami - Od tyłu - Domyślny - Polityka zrzutów ekranu - Wyklucz gatunki - Określ gatunki, których nie chcesz widzieć w sugestiach - Zalogowano jako %s - Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. - Zgłoś - Usuwanie danych - Nieważna domena - Zmień kolejność - Potwierdzenie wyjścia - %s - %s - Rozdz. %1$d/%2$d Str. %3$d/%4$d - Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online - Importuj - Wybierz plik ZIP lub CBZ. - Wyczyść historię wyszukiwania - Ta operacja nie jest obsługiwana - Tryb sortowania - Treści - Nie można załadować listy gatunków - Wstrzymane - Porzucone - Użyj odcisku palca, jeśli jest dostępny - Mangi z Twoich ulubionych - Pokaż wskaźniki postępu czytania - Pokaż procent przeczytania w historii i ulubionych - Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane - DNS przez HTTPS - Tryb domyślny - Trwale wyczyścić całą historię czytania? - „%s” usunięte z pamięci lokalnej - Wyczyść tablicę aktualizacji - Tablica - Usunąć trwale „%s” z urządzenia? - Wyczyść pamięć podręczną miniatur - Spróbuj przeformułować zapytanie. - To co czytasz będzie wyświetlane tutaj - Znajdź to, co warto przeczytać, w menu bocznym. - Zapisz ze źródeł online lub zaimportuj pliki. - Folder pobranych - Aktualizacja tablicy rozpocznie się wkrótce - Niezgodne hasła - Od prawej do lewej - Trzymaj na starcie - Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją - Wybrana konfiguracja zostanie zapamiętana dla tej mangi - Wyczyść tablicę - Wyczyścić trwale całą historię aktualizacji? - Szukanie nowych rozdziałów - Zaloguj się, aby wyświetlić tę zawartość - Domyślnie: %s - Wprowadź hasło, aby uruchomić aplikację - Hasło musi mieć co najmniej 4 znaki - Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? - Zapisano kopię zapasową - Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. - W kolejce - Pobierz lub przeczytaj ten brakujący rozdział online. - Brak rozdziału - Uprawniony - Logowanie na %s nie jest obsługiwane - Zostaniesz wylogowany ze wszystkich źródeł - Wyklucz mangi NSFW z historii - Wykorzystane źródła - Zablokuj na NSFW - Proponuj mangi na podstawie Twoich preferencji - Wszystkie dane są analizowane tylko lokalnie na tym urządzeniu i nigdy nie są nigdzie wysyłane. - Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie - Nie proponuj mang NSFW - Zresetuj filtr - Ładuj wstępnie strony - Aktualizowanie sugestii - Trwale usunąć wybrane elementy z urządzenia? - Usuwanie zakończone - Pomaga uniknąć blokowania Twojego adresu IP - Przetwarzanie zapisanej mangi - Rozdziały zostaną usunięte w tle - Wpisz swój adres e-mail, aby kontynuować - Dostępne są nowe źródła mang - Sprawdzaj dostępność nowych rozdziałów i informuj o nich - Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz - Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach - Śledzenie - Automatycznie wykryj, czy manga to webtoon - Pomaga w sprawdzaniu aktualizacji w tle - Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. - Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione - Brak źródeł mang - Włącz źródła mang do czytania mang online - Czy na pewno chcesz usunąć wybrane ulubione kategorie\? + Ulubione + Historia + Napotkano błąd + Szczegółowy + Rozdziały + Lista + Lista szczegółowa + Siatka + Tryb listy + Ustawienia + Ładowanie… + Rozdział %1$d z %2$d + Zamknij + Wyczyść historię + Dodaj + Zapisz + Udostępnij + Szukaj + Szukaj mang + Pobieranie… + Pobrano + Pobrane + Nazwa + Popularność + Najnowsze + Ocena + Filtry + Jasny + Ciemny + Strony + Wyczyść + Usuń + Udostępnij zdjęcie + Usuń + Brak opisu + Tryb czytania + Błąd sieci + Obliczanie… + Spróbuj ponownie + Nic nie znaleziono + Brak historii + Czytaj + Brak ulubionych + Dodaj do ulubionych + Nowa kategoria + Stwórz skrót… + Udostępnij %s + Przetwarzanie… + Zaktualizowane + Zapisz stronę + Zapisano + Wibracje + Biblioteka + Ostatnie + Tryb czarny + Przygotowywanie… + Plik nieznaleziony + Wczoraj + Dawno temu + Grupa + Dzisiaj + Zaloguj + Dalej + Potwierdź + Witaj + Skończone + W trakcie + Zezwól + Proponowane + Włącz propozycje + Włączone + Wyłączone + Nigdy + Zawsze + Znajdź rozdział + %1$s%% + Wygląd + Schowaj + Synchronizacja + Synchronizuj swoje dane + Nazwa + Edytuj + Wyloguj + Cofnij + Wyślij + Planowane + Czytane + Czytane ponownie + Skończone + Pokaż wszystkie + Wybierz zakres + Wyczyść całą historię + Ostatnie 2 godziny + Historia wyczyszczona + Zarządzaj + Losowe + Puste + Przeglądaj + Dostępne + Ustawienia + Źródło wyłączone + Kompaktowy + Błąd po stronie serwera (%1$d). Sprónuj ponownie później + Sieć niedostępna + Inne języki + Odrzuć + Jasność + Kontrast + Korekcja kolorów + Automatyczne przewijanie + Brak rozdziałów + Tryb incognito + Usunięto z ulubionych + Wykorzystana pamięć + Zapisane mangi + Brak zakładek + Możesz tworzyć zakładki w trakcie czytania mangi + Zakładki usunięte + Twoje ostatnio czytane mangi + Wyłącz wszystkie + Wyłącz optymalizację baterii + Autowykrywanie trybu czytania + Usunięte z historii + Dodano zakładkę + Usunięto zakładkę + Zakładki + Usuń zakładkę + Dodaj zakładkę + Brak ulubionych kategorii + Edytuj kategorię + Włącz powiadomienia + Wróć + Konto już istnieje + Anulowano + Zwolnienie pobierania + Brak rozdziałów w tej mandze + Różne języki + Tylko na Wi-Fi + Zawsze blokuj + Gatunki + Czytaj więcej + Rozwiąż + Wymagane CAPTCHA + Cichy + Dotknij aby spróbować ponownie + Teraz + Przywrócone + Dopasuj do szerokości + Dopasuj do wysokości + Dopasuj do środka + Nowa kategoria + Brak nowych aktualizacji + Sprawdź dostępność aktualizacji + Wersja %s + O aplikacji + Usuń + Jest tu dosyć pusto… + Ulubione kategorie + Powiadomienie LED + Nowe rozdziały + Pamięć wewnętrzna + Tutaj będą wyświetlane Twoje mangi + Znajdź materiały do czytania w zakładce „Przeglądaj” + W tym miejscu pojawią się powiadomienia o nowych rozdziałach z mang które czytasz + Strony w pamięci podręcznej + Animacja przewracania strony + Inne rzeczy w pamięci podręcznej + Otwórz w przeglądarce + Numerowane strony + Powiadomienia + Dźwięk powiadomień + Ustawienia powiadomień + Zewnętrzne źródła + Motyw + Systemowy + Wyczyść pamięć podręczną stron + B|kB|MB|GB|TB + Wielkość siatki + Szukaj na %s + Usuń mangę + Dalej + Błąd + Wyczyszczone + Pamięć wewnętrzna + Pamięć zewnętrzna + Domena + Nowa wersja aplikacji jest dostępna + Ta manga ma %s. Zapisać wszystko? + Zapisz + Pobierz + Najpierw coś zapisz + Niedostępne + Zapisz + Wszystkie ulubione + Pusta kategoria + Czytaj później + Aktualizacje + Nowa wersja: %s + Wielkość: %s + Obróć ekran + Odśwież + Szukaj aktualizacji + Nie sprawdzaj + Wprowadź hasło + Złe hasło + Chroń aplikację + Pytaj o hasło przy starcie Kotatsu + Wprowadź ponownie hasło + Zużywa mniej prądu na ekranach AMOLED + Kopia zapasowa i przywracanie + Utwórz kopię zapasową danych + Przywróć z kopii zapasowej + 18+ + %1$d na %2$d włączone + Standardowy + Webtoon + Ustawienia czytnika + Zmiana strony + Przyciski głośności + Dotknięcie krawędzi + Wyczyszczone + Tryb skalowania + Wyczyść ciasteczka + Wszystkie ciasteczka wyczyszczone + Przetłumacz tą aplikację + Tłumaczenie + Dostępne źródła + Tylko gesty + Brak dostępnej pamięci + Inny + Wyniki wyszukiwania + Wszystkie dane zostały przywrócone + Dane zostały przywrócone, ale z błędami + Od tyłu + Domyślny + Polityka zrzutów ekranu + Wyklucz gatunki + Określ gatunki, których nie chcesz widzieć w sugestiach + Zalogowano jako %s + Wybierz języki, w których chcesz czytać mangi. Możesz zmienić to później w ustawieniach. + Zgłoś + Usuwanie danych + Nieważna domena + Zmień kolejność + Potwierdzenie wyjścia + %s - %s + Rozdz. %1$d/%2$d Str. %3$d/%4$d + Włącz Wi-Fi lub sieć komórkową, aby czytać mangę online + Importuj + Wybierz plik ZIP lub CBZ. + Wyczyść historię wyszukiwania + Ta operacja nie jest obsługiwana + Tryb sortowania + Nie można załadować listy gatunków + Wstrzymane + Porzucone + Użyj odcisku palca, jeśli jest dostępny + Mangi z Twoich ulubionych + Pokaż wskaźniki postępu czytania + Pokaż procent przeczytania w historii i ulubionych + Manga oznaczona jako NSFW nigdy nie zostanie dodana do historii, a Twoje postępy nie zostaną zapisane + DNS przez HTTPS + Tryb domyślny + Trwale wyczyścić całą historię czytania? + „%s” usunięte z pamięci lokalnej + Wyczyść tablicę aktualizacji + Tablica + Usunąć trwale „%s” z urządzenia? + Wyczyść pamięć podręczną miniatur + Spróbuj przeformułować zapytanie. + To co czytasz będzie wyświetlane tutaj + Znajdź to, co warto przeczytać, w menu bocznym. + Zapisz ze źródeł online lub zaimportuj pliki. + Folder pobranych + Aktualizacja tablicy rozpocznie się wkrótce + Niezgodne hasła + Od prawej do lewej + Trzymaj na starcie + Możesz utworzyć kopię zapasową swojej historii i ulubionych oraz przywrócić ją + Wybrana konfiguracja zostanie zapamiętana dla tej mangi + Wyczyść tablicę + Wyczyścić trwale całą historię aktualizacji? + Szukanie nowych rozdziałów + Zaloguj się, aby wyświetlić tę zawartość + Domyślnie: %s + Wprowadź hasło, aby uruchomić aplikację + Hasło musi mieć co najmniej 4 znaki + Trwale usunąć wszystkie ostatnie zapytania wyszukiwania? + Zapisano kopię zapasową + Systemy niektórych urządzeń inaczej się zachowują. Może to zakłócać wykonywanie zadań w tle. + W kolejce + Brak rozdziału + Uprawniony + Logowanie na %s nie jest obsługiwane + Zostaniesz wylogowany ze wszystkich źródeł + Wyklucz mangi NSFW z historii + Wykorzystane źródła + Zablokuj na NSFW + Proponuj mangi na podstawie Twoich preferencji + Wszystkie dane są analizowane tylko lokalnie na tym urządzeniu i nigdy nie są nigdzie wysyłane. + Zacznij czytać mangę, a otrzymasz spersonalizowane sugestie + Nie proponuj mang NSFW + Zresetuj filtr + Ładuj wstępnie strony + Aktualizowanie sugestii + Trwale usunąć wybrane elementy z urządzenia? + Usuwanie zakończone + Pomaga uniknąć blokowania Twojego adresu IP + Przetwarzanie zapisanej mangi + Rozdziały zostaną usunięte w tle + Wpisz swój adres e-mail, aby kontynuować + Dostępne są nowe źródła mang + Sprawdzaj dostępność nowych rozdziałów i informuj o nich + Będziesz otrzymywać powiadomienia o aktualizacjach mang, które czytasz + Nie będziesz otrzymywać powiadomień, ale nowe rozdziały będą podświetlane na listach + Śledzenie + Automatycznie wykryj, czy manga to webtoon + Pomaga w sprawdzaniu aktualizacji w tle + Coś poszło nie tak. Zgłoś błąd programistom, aby pomóc nam go naprawić. + Może pomóc w przypadku niektórych problemów. Wszystkie autoryzacje zostaną unieważnione + Brak źródeł mang + Włącz źródła mang do czytania mang online + Czy na pewno chcesz usunąć wybrane ulubione kategorie\? \nWszystkie w nich mangi zostaną usunięte i nie będzie można tego cofnąć. - Naciśnij ponownie Wstecz, aby wyjść - Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji - Treść nie została znaleziona lub została usunięta - Pokaż pasek informacji w czytniku - Archiwum komiksów - Folder z obrazami - Importowanie mangi - Importowanie zakończone - Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce - Import rozpocznie się wkrótce - Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi - Pokaż ostatnie skróty do mang - Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji - Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony - Ergonomiczne sterowanie czytnikiem - Zapisać czy odrzucić niezapisane zmiany? - Brak miejsca w urządzeniu - Pokaż suwak przełączania stron - Powiększanie webtoon - Wyczyść też informacje o nowych rozdziałach - Resetuj - Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a>, aby upewnić się, że jest dostępna w swoim źródle<br>2. Upewnij się, że używasz <a href=kotatsu://about>najnowszej wersji Kotatsu</a><br>3. Jeśli jest dostępny, wyślij raport o błędzie do programistów. - Mamimi - Kanade - Usługi - Tutaj nic nie ma - By śledzić postęp w czytaniu, wybierz Menu → Śledź na ekranie detali mangi. - Znajdź podobne - Nagłówek UserAgent - Tłumaczenia - Udostępnij dzienniki - Zapisz niektóre działania do celów debugowania - Zezwól na niestabilne altualizacje - Rozumiem - Uruchom ponownie aplikację by wprowadzić te zmiany - Prędkość - Stuknij i przytrzymaj element, aby zmienić jego kolejność - Możesz wybrać jeden lub więcej plików .cbz lub .zip, każdy plik zostanie rozpoznany jako osobna manga. - Możesz wybrać katalog z archiwami lub obrazami. Każde archiwum (lub podkatalog) zostanie rozpoznane jako rozdział. - Włączać - Wstępne ładowanie treści - Oznacz jako aktualne - Włącz logowanie - Pokaż podejrzane treści - Schemat kolorów - Pokaż w widoku siatki - Miku - Dynamiczne - Asuka - Rikka - Sakura - Mion - Ignoruj błędy SSL - Wybierz lustro automatycznie - Zaimportuj utworzoną wcześniej kopię zapasową danych użytkownika - Pokaż na półce - Automatycznie przełączaj domeny dla zdalnych źródeł w przypadku błędów, jeśli dostępne są kopie lustrzane - Pauza - Wznawiać - Wstrzymane - Anulować całość - Pobieraj tylko przez Wi-Fi - Zatrzymaj pobieranie po przełączeniu na sieć komórkową - Sugestia: %s - Czasami wyświetlaj powiadomienia z sugerowaną mangą - Więcej - Nie, dziękuję - Wszystkie aktywne pobrania zostaną anulowane, częściowo pobrane dane zostaną utracone - Usuwanie zakończone - Język - Zaproponuj aktualizacje do wersji beta aplikacji - Pobieranie rozpoczęte - Ustawienia synchronizacji - Adres serwera - Możesz użyć samoobsługowego serwera synchronizacji lub serwera domyślnego. Nie zmieniaj tego, jeśli nie jesteś pewien, co robisz. - Twoja historia pobrań zostanie trwale usunięta - Nie masz żadnych pobrań - Pobieranie zostało wstrzymane - Pobieranie zostało wznowione - Pobieranie zostało anulowane - Pliki do pobrania zostały usunięte - Czy chcesz otrzymywać spersonalizowane sugestie dotyczące mangi\? - WebView niedostępny: sprawdź, czy dostawca WebView jest zainstalowany - Wyczyść pamięć podręczną sieci - Typ - Adres - Port - Proxy - Możesz zalogować się na istniejące konto lub utworzyć nowe - \ No newline at end of file + Naciśnij ponownie Wstecz, aby wyjść + Naciśnij dwukrotnie przycisk Wstecz, aby wyjść z aplikacji + Treść nie została znaleziona lub została usunięta + Pokaż pasek informacji w czytniku + Archiwum komiksów + Folder z obrazami + Importowanie mangi + Importowanie zakończone + Możesz usunąć oryginalny plik z pamięci, aby zaoszczędzić miejsce + Import rozpocznie się wkrótce + Wybrane ustawienia kolorów zostaną zapamiętane dla tej mangi + Pokaż ostatnie skróty do mang + Pokaż ostatnie mangi po długim naciśnięciu ikony aplikacji + Stuknięcie w prawą krawędź lub naciśnięcie prawego klawisza zawsze powoduje przejście do następnej strony + Ergonomiczne sterowanie czytnikiem + Zapisać czy odrzucić niezapisane zmiany? + Brak miejsca w urządzeniu + Pokaż suwak przełączania stron + Powiększanie webtoon + Wyczyść też informacje o nowych rozdziałach + Resetuj + Szczegóły błędu:<br><tt>%1$s</tt><br><br>1. Spróbuj <a href=%2$s>otworzyć mangę w przeglądarce internetowej</a>, aby upewnić się, że jest dostępna w swoim źródle<br>2. Upewnij się, że używasz <a href=kotatsu://about>najnowszej wersji Kotatsu</a><br>3. Jeśli jest dostępny, wyślij raport o błędzie do programistów. + Mamimi + Kanade + Usługi + Tutaj nic nie ma + By śledzić postęp w czytaniu, wybierz Menu → Śledź na ekranie detali mangi. + Znajdź podobne + Nagłówek UserAgent + Tłumaczenia + Udostępnij dzienniki + Zapisz niektóre działania do celów debugowania + Zezwól na niestabilne altualizacje + Rozumiem + Uruchom ponownie aplikację by wprowadzić te zmiany + Prędkość + Stuknij i przytrzymaj element, aby zmienić jego kolejność + Możesz wybrać jeden lub więcej plików .cbz lub .zip, każdy plik zostanie rozpoznany jako osobna manga. + Możesz wybrać katalog z archiwami lub obrazami. Każde archiwum (lub podkatalog) zostanie rozpoznane jako rozdział. + Włączać + Wstępne ładowanie treści + Oznacz jako aktualne + Włącz logowanie + Pokaż podejrzane treści + Schemat kolorów + Pokaż w widoku siatki + Miku + Dynamiczne + Asuka + Rikka + Sakura + Mion + Ignoruj błędy SSL + Wybierz lustro automatycznie + Zaimportuj utworzoną wcześniej kopię zapasową danych użytkownika + Pokaż na półce + Automatycznie przełączaj domeny dla zdalnych źródeł w przypadku błędów, jeśli dostępne są kopie lustrzane + Pauza + Wznawiać + Wstrzymane + Anulować całość + Pobieraj tylko przez Wi-Fi + Zatrzymaj pobieranie po przełączeniu na sieć komórkową + Sugestia: %s + Czasami wyświetlaj powiadomienia z sugerowaną mangą + Więcej + Nie, dziękuję + Wszystkie aktywne pobrania zostaną anulowane, częściowo pobrane dane zostaną utracone + Usuwanie zakończone + Język + Zaproponuj aktualizacje do wersji beta aplikacji + Pobieranie rozpoczęte + Ustawienia synchronizacji + Adres serwera + Możesz użyć samoobsługowego serwera synchronizacji lub serwera domyślnego. Nie zmieniaj tego, jeśli nie jesteś pewien, co robisz. + Twoja historia pobrań zostanie trwale usunięta + Nie masz żadnych pobrań + Pobieranie zostało wstrzymane + Pobieranie zostało wznowione + Pobieranie zostało anulowane + Pliki do pobrania zostały usunięte + Czy chcesz otrzymywać spersonalizowane sugestie dotyczące mangi\? + WebView niedostępny: sprawdź, czy dostawca WebView jest zainstalowany + Wyczyść pamięć podręczną sieci + Typ + Adres + Port + Proxy + Możesz zalogować się na istniejące konto lub utworzyć nowe + diff --git a/app/src/main/res/values-pt-rBR/plurals.xml b/app/src/main/res/values-pt-rBR/plurals.xml index ff7cb185c..081afb690 100644 --- a/app/src/main/res/values-pt-rBR/plurals.xml +++ b/app/src/main/res/values-pt-rBR/plurals.xml @@ -8,10 +8,6 @@ %1$d capítulo %1$d capítulos - - Total de %1$d página - Total de %1$d páginas - %1$d novo capítulo %1$d novos capítulos diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 41f1dc1a9..b52effbd3 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -56,7 +56,6 @@ Deletar Escolha um arquivo ZIP ou CBZ. Sem descrição - Histórico e cache Limpar cache da página B|kB|MB|GB|TB Padrão @@ -150,7 +149,6 @@ Alguns dispositivos têm um comportamento de sistema diferente, o que pode interromper as tarefas em segundo plano. Consulte mais informação Na fila - Baixe ou leia este capítulo perdido online. O capítulo está em falta Traduzir este aplicativo Tradução @@ -180,7 +178,6 @@ Desabilitado Não foi possível carregar a lista de gêneros Redefinir filtro - Encontrar gênero Selecione os idiomas que você deseja ler mangá. Você pode alterá-lo mais tarde nas configurações. Nunca Somente em Wi-Fi @@ -226,7 +223,6 @@ %1$s%% Atualização de sugestões Aparência - Conteúdo Excluir gêneros Especifique os gêneros que você não deseja ver nas sugestões Remoção concluída diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index eae27e6af..eaefda767 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -47,7 +47,6 @@ Atualizado Deletar Essa operação não é suportada - Histórico e cache Limpar cache de página B|kB|MB|GB|TB Padrão @@ -156,7 +155,6 @@ Fontes usadas Enfileirado Traduzir esta aplicação - Baixe ou leia este capítulo perdido online. O capítulo está em falta Autorizado O login em %s não é suportado @@ -213,7 +211,6 @@ Não foi possível carregar a lista de gêneros Somente em Wi-Fi Selecione os idiomas que deseja ler mangá. Pode alterá-lo mais tarde nas configurações. - Encontrar gênero Sempre Redefinir filtro Nunca @@ -224,7 +221,6 @@ Atualização das sugestões Aparência Encontrar capítulo - Conteúdo Não há capítulos nesta manga %1$s%% O seu mangá será exibido aqui diff --git a/app/src/main/res/values-ru/plurals.xml b/app/src/main/res/values-ru/plurals.xml index 9dcd4db39..a3ef775fa 100644 --- a/app/src/main/res/values-ru/plurals.xml +++ b/app/src/main/res/values-ru/plurals.xml @@ -1,10 +1,5 @@ - - Всего %1$d страница - Всего %1$d страницы - Всего %1$d страниц - %1$d элемент %1$d элемента diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ff3015e29..8484a01fc 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,422 +1,418 @@ - На устройстве - Избранное - История - Произошла ошибка - Ошибка сети - Подробности - Главы - Список - Подробный список - Сетка - Вид списка - Настройки - Источники манги - Загрузка… - Глава %1$d из %2$d - Закрыть - Повторить - Очистить историю - Ничего не найдено - Истории пока нет - Читать - Избранного пока нет - В избранное - Новая категория - Добавить - Сохранить - Поделиться - Создать ярлык… - Поделиться %s - Поиск - Поиск манги - Загрузка… - Обработка… - Загружено - Загрузки - Имя - Популярная - Обновлённая - Новая - Рейтинг - Порядок сортировки - Фильтр - Тема - Светлая - Тёмная - Как в системе - Страницы - Очистить - Очистить всю историю чтения полностью\? - Удалить - «%s» удалено с устройства - Сохранить страницу - Сохранено - Поделиться изображением - Импорт - Удалить - Операция не поддерживается - Выберите файл в формате CBZ или ZIP. - Описание отсутствует - История и кэш - Очистить кэш страниц - Б|кБ|МБ|ГБ|ТБ - Стандартный - Манхва - Режим чтения - Размер сетки - Поиск по %s - Удалить мангу - Удалить \"%s\" с устройства навсегда\? - Настройки режима чтения - Листание страниц - Нажатия по краям - Кнопки громкости - Продолжить - Ошибка - Очистить кэш миниатюр - Очистить историю поиска - Очищено - Только жесты - Внутренний накопитель - Внешний накопитель - Домен - Доступна новая версия приложения - Открыть в веб-браузере - В этой манге %s. Сохранить их все\? - Сохранить - Уведомления - Включено %1$d из %2$d - Новые главы - Загрузить - Настройки уведомлений - Звук уведомления - Светодиодная индикация - Вибросигнал - Категории избранного - Удалить - Как-то здесь пусто… - Попробуйте переформулировать запрос. - То, что вы прочитаете, будет отображено здесь - Найдите, что почитать, в боковом меню. - Сохраните что-нибудь - Сохраните что-нибудь из онлайн-каталога или импортируйте из файла. - Полка - Недавнее - Анимация пролистывания - Папка для загрузок - Недоступно - Нет доступного хранилища - Другое хранилище - Готово - Всё избранное - Категория пуста - Прочитать позже - Обновления - Новые главы из того, что вы читаете, будут показаны здесь - Результаты поиска - Новая версия: %s - Размер: %s - Очистить ленту обновлений - Очищено - Повернуть экран - Обновить - Обновление скоро начнётся - Следить за обновлениями - Не проверять - Введите пароль - Неверный пароль - Защитить приложение - Запрашивать пароль при запуске Kotatsu - Повторите пароль - Пароли не совпадают - О программе - Версия %s - Проверить обновления - Нет доступных обновлений - Справа налево - Создать категорию - Масштабирование - Вписать в экран - Подогнать по высоте - Подогнать по ширине - Исходный размер - Чёрная - Потребляет меньше энергии на экранах AMOLED - Резервное копирование и восстановление - Создать резервную копию - Восстановить данные - Восстановлено - Подготовка… - Файл не найден - Все данные были восстановлены - Данные были восстановлены, но возникли некоторые ошибки - Вы можете создать резервную копию избранного и истории и потом восстановить их - Только что - Вчера - Давно - Группировать - Сегодня - Попробовать ещё раз - Выбранный режим будет сохранён для текущей манги - Без звука - Необходимо пройти CAPTCHA - Пройти - Очистить куки - Все файлы cookie были удалены - Очистить ленту - Удалить всю историю обновлений навсегда\? - Проверка новых глав - В обратном порядке - Войти - Авторизуйтесь, чтобы просмотреть этот контент - По умолчанию: %s - Далее - Введите пароль для запуска приложения - Подтвердить - Пароль должен состоять из 4 символов или более - Добро пожаловать - Удалить все последние поисковые запросы навсегда\? - Резервная копия сохранена - Некоторые устройства имеют различное поведение системы, что может привести к нарушению фоновых задач. - Подробнее - В очереди - Глава отсутствует - Скачайте или прочитайте эту недостающую главу онлайн. - Помочь с переводом приложения - Перевод - Авторизация выполнена - Вход в %s не поддерживается - Вы выйдете из всех источников - Жанры - Завершено - Онгоинг - По умолчанию - Исключить NSFW мангу из истории - Нумерация страниц - Включенные источники - Доступные источники - Политика скриншотов - Разрешить - Запретить для NSFW - Всегда блокировать - Рекомендации - Включить рекомендации - Предлагать мангу на основе Ваших предпочтений - Все данные анализируются только локально на этом устройстве и никуда не отправляются. - Начните читать мангу, чтобы получать персональные предложения - Не предлагать NSFW мангу - Включено - Выключено - Не удалось загрузить список жанров - Вычисление… - Сбросить фильтр - Поиск по жанрам - Выберите языки, на которых Вы хотите читать мангу. Это можно будет изменить позже в настройках. - Никогда - Только по Wi-Fi - Всегда - Предварительная загрузка страниц - Вы авторизованы как %s - 18+ - Разные языки - Найти главу - В этой манге нет глав - Оформление - Контент - Обновление рекомендаций - Исключить жанры - Укажите жанры, которые Вы не хотите видеть в рекомендациях - Удалить выбранную мангу с накопителя? - Удаление завершено - Замедление загрузки - Помогает избежать блокировки IP-адреса - Обработка сохранённой манги - Главы будут удалены в фоновом режиме - Скрыть - Доступны новые источники манги - Проверять новые главы и уведомлять о них - Вы будете получать уведомления об обновлении манги, которую Вы читаете - Вы не будете получать уведомления, но новые главы будут отображаться в списке - Включить уведомления - Название - Изменить - Изменить категорию - Отслеживание - Нет категорий избранного - Добавить закладку - Удалить закладку - Закладки - Закладка удалена - Закладка добавлена - Отменить - Удалено из истории - DNS поверх HTTPS - Режим по умолчанию - Автоопределение режима чтения - Автоматически определяет, является ли манга веб-комиксом - Отключить оптимизацию батареи - Помогает с фоновой проверкой обновлений - Что-то пошло не так. Пожалуйста, отправьте отчёт разработчикам, чтобы помочь всё исправить. - Отправить - Отключить все - Использовать отпечаток пальца, если доступно - Манга из Вашего избранного - Манга, которую Вы недавно читали - Читаю - Запланировано - Отложено - Заброшено - Завершено - Показать процент прочитанного в истории и избранном - Манга, помеченная как NSFW, никогда не будет добавлена в историю и ваш прогресс чтения не будет сохранен - %1$s%% - Отчёт - Выйти - Перечитываю - Показать индикаторы прогресса чтения - Удаление данных - Может помочь в случае каких-либо проблем. Все авторизации будут аннулированы - Показать все - Неверное доменное имя - Найдите, что почитать во разделе «Обзор» - Назад - Выбрать диапазон - История очищена - Настроить - Закладок пока нет - Закладки удалены - Нет источников манги - Включите источники манги для чтения онлайн - Случайная - Упорядочить - Пусто - Обзор - Нажмите Назад ещё раз, чтобы выйти - Нажмите Назад 2 раза для выхода из приложения - Другой кэш - Опции - Контент не найден или был удален - Гл. %1$d/%2$d Стр. %3$d/%4$d - Показывать информационную панель в режиме чтения - Архив комиксов - Вы можете удалить исходный файл из хранилища, чтобы сэкономить место на нём - Режим инкогнито - Синхронизация - Синхронизируйте ваши данные - Введите электронную почту, чтобы продолжить - Ваша манга будет показана здесь - Аккаунт уже существует - Вы можете создавать закладки во время чтения манги - Подтверждение выхода - Отменено - Очистить всю историю - Последние 2 часа - Вы уверены, что хотите удалить выбранные категории избранного\? + На устройстве + Избранное + История + Произошла ошибка + Ошибка сети + Подробности + Главы + Список + Подробный список + Сетка + Вид списка + Настройки + Источники манги + Загрузка… + Глава %1$d из %2$d + Закрыть + Повторить + Очистить историю + Ничего не найдено + Истории пока нет + Читать + Избранного пока нет + В избранное + Новая категория + Добавить + Сохранить + Поделиться + Создать ярлык… + Поделиться %s + Поиск + Поиск манги + Загрузка… + Обработка… + Загружено + Загрузки + Имя + Популярная + Обновлённая + Новая + Рейтинг + Порядок сортировки + Фильтр + Тема + Светлая + Тёмная + Как в системе + Страницы + Очистить + Очистить всю историю чтения полностью\? + Удалить + «%s» удалено с устройства + Сохранить страницу + Сохранено + Поделиться изображением + Импорт + Удалить + Операция не поддерживается + Выберите файл в формате CBZ или ZIP. + Описание отсутствует + Очистить кэш страниц + Б|кБ|МБ|ГБ|ТБ + Стандартный + Манхва + Режим чтения + Размер сетки + Поиск по %s + Удалить мангу + Удалить \"%s\" с устройства навсегда\? + Настройки режима чтения + Листание страниц + Нажатия по краям + Кнопки громкости + Продолжить + Ошибка + Очистить кэш миниатюр + Очистить историю поиска + Очищено + Только жесты + Внутренний накопитель + Внешний накопитель + Домен + Доступна новая версия приложения + Открыть в веб-браузере + В этой манге %s. Сохранить их все\? + Сохранить + Уведомления + Включено %1$d из %2$d + Новые главы + Загрузить + Настройки уведомлений + Звук уведомления + Светодиодная индикация + Вибросигнал + Категории избранного + Удалить + Как-то здесь пусто… + Попробуйте переформулировать запрос. + То, что вы прочитаете, будет отображено здесь + Найдите, что почитать, в боковом меню. + Сохраните что-нибудь + Сохраните что-нибудь из онлайн-каталога или импортируйте из файла. + Полка + Недавнее + Анимация пролистывания + Папка для загрузок + Недоступно + Нет доступного хранилища + Другое хранилище + Готово + Всё избранное + Категория пуста + Прочитать позже + Обновления + Новые главы из того, что вы читаете, будут показаны здесь + Результаты поиска + Новая версия: %s + Размер: %s + Очистить ленту обновлений + Очищено + Повернуть экран + Обновить + Обновление скоро начнётся + Следить за обновлениями + Не проверять + Введите пароль + Неверный пароль + Защитить приложение + Запрашивать пароль при запуске Kotatsu + Повторите пароль + Пароли не совпадают + О программе + Версия %s + Проверить обновления + Нет доступных обновлений + Справа налево + Создать категорию + Масштабирование + Вписать в экран + Подогнать по высоте + Подогнать по ширине + Исходный размер + Чёрная + Потребляет меньше энергии на экранах AMOLED + Резервное копирование и восстановление + Создать резервную копию + Восстановить данные + Восстановлено + Подготовка… + Файл не найден + Все данные были восстановлены + Данные были восстановлены, но возникли некоторые ошибки + Вы можете создать резервную копию избранного и истории и потом восстановить их + Только что + Вчера + Давно + Группировать + Сегодня + Попробовать ещё раз + Выбранный режим будет сохранён для текущей манги + Без звука + Необходимо пройти CAPTCHA + Пройти + Очистить куки + Все файлы cookie были удалены + Очистить ленту + Удалить всю историю обновлений навсегда\? + Проверка новых глав + В обратном порядке + Войти + Авторизуйтесь, чтобы просмотреть этот контент + По умолчанию: %s + Далее + Введите пароль для запуска приложения + Подтвердить + Пароль должен состоять из 4 символов или более + Добро пожаловать + Удалить все последние поисковые запросы навсегда\? + Резервная копия сохранена + Некоторые устройства имеют различное поведение системы, что может привести к нарушению фоновых задач. + Подробнее + В очереди + Глава отсутствует + Помочь с переводом приложения + Перевод + Авторизация выполнена + Вход в %s не поддерживается + Вы выйдете из всех источников + Жанры + Завершено + Онгоинг + По умолчанию + Исключить NSFW мангу из истории + Нумерация страниц + Включенные источники + Доступные источники + Политика скриншотов + Разрешить + Запретить для NSFW + Всегда блокировать + Рекомендации + Включить рекомендации + Предлагать мангу на основе Ваших предпочтений + Все данные анализируются только локально на этом устройстве и никуда не отправляются. + Начните читать мангу, чтобы получать персональные предложения + Не предлагать NSFW мангу + Включено + Выключено + Не удалось загрузить список жанров + Вычисление… + Сбросить фильтр + Выберите языки, на которых Вы хотите читать мангу. Это можно будет изменить позже в настройках. + Никогда + Только по Wi-Fi + Всегда + Предварительная загрузка страниц + Вы авторизованы как %s + 18+ + Разные языки + Найти главу + В этой манге нет глав + Оформление + Обновление рекомендаций + Исключить жанры + Укажите жанры, которые Вы не хотите видеть в рекомендациях + Удалить выбранную мангу с накопителя? + Удаление завершено + Замедление загрузки + Помогает избежать блокировки IP-адреса + Обработка сохранённой манги + Главы будут удалены в фоновом режиме + Скрыть + Доступны новые источники манги + Проверять новые главы и уведомлять о них + Вы будете получать уведомления об обновлении манги, которую Вы читаете + Вы не будете получать уведомления, но новые главы будут отображаться в списке + Включить уведомления + Название + Изменить + Изменить категорию + Отслеживание + Нет категорий избранного + Добавить закладку + Удалить закладку + Закладки + Закладка удалена + Закладка добавлена + Отменить + Удалено из истории + DNS поверх HTTPS + Режим по умолчанию + Автоопределение режима чтения + Автоматически определяет, является ли манга веб-комиксом + Отключить оптимизацию батареи + Помогает с фоновой проверкой обновлений + Что-то пошло не так. Пожалуйста, отправьте отчёт разработчикам, чтобы помочь всё исправить. + Отправить + Отключить все + Использовать отпечаток пальца, если доступно + Манга из Вашего избранного + Манга, которую Вы недавно читали + Читаю + Запланировано + Отложено + Заброшено + Завершено + Показать процент прочитанного в истории и избранном + Манга, помеченная как NSFW, никогда не будет добавлена в историю и ваш прогресс чтения не будет сохранен + %1$s%% + Отчёт + Выйти + Перечитываю + Показать индикаторы прогресса чтения + Удаление данных + Может помочь в случае каких-либо проблем. Все авторизации будут аннулированы + Показать все + Неверное доменное имя + Найдите, что почитать во разделе «Обзор» + Назад + Выбрать диапазон + История очищена + Настроить + Закладок пока нет + Закладки удалены + Нет источников манги + Включите источники манги для чтения онлайн + Случайная + Упорядочить + Пусто + Обзор + Нажмите Назад ещё раз, чтобы выйти + Нажмите Назад 2 раза для выхода из приложения + Другой кэш + Опции + Контент не найден или был удален + Гл. %1$d/%2$d Стр. %3$d/%4$d + Показывать информационную панель в режиме чтения + Архив комиксов + Вы можете удалить исходный файл из хранилища, чтобы сэкономить место на нём + Режим инкогнито + Синхронизация + Синхронизируйте ваши данные + Введите электронную почту, чтобы продолжить + Ваша манга будет показана здесь + Аккаунт уже существует + Вы можете создавать закладки во время чтения манги + Подтверждение выхода + Отменено + Очистить всю историю + Последние 2 часа + Вы уверены, что хотите удалить выбранные категории избранного\? \nВся манга в них будет потеряна и это не может быть отменено. - Кэш страниц - %s - %s - Использование хранилища - Доступно - Сохранённая манга - Удалено из избранного - Нет глав - Автоматическое листание - Папка с изображениями - Импорт манги - Импорт завершён - Импорт скоро начнётся - Лента - Сведения об ошибке:<br><tt>%1$s</tt><br><br>1. Попробуйте <a href=%2$s>открыть мангу в веб-браузере</a>, чтобы убедиться, что она доступна в источнике<br>2. Убедитесь, что вы используете <a href=kotatsu://about>последнюю версию Kotatsu</a><br>3. Если возможно, отправьте отчёт об ошибке разработчикам. - Показывать ярлыки последней прочитанной манги - Сделать недавно прочитанную мангу доступной по долгому нажатию на иконку приложения - Нажатие на правый край или нажатие правой клавиши всегда переключает на следующую страницу - Эргономичное управление режимом чтения - Сбросить - Отменить - Сохранить или отменить несохранённые изменения\? - Контрастность - Яркость - Цветокоррекция - Выбранные настройки цвета будут сохранены для этой манги - Не осталось свободного места на накопителе - Масштабирование в режиме манхвы - Показывать слайдер переключения страниц - Включите Wi-Fi или передачу данных, чтобы читать мангу онлайн - Разные языки - Сеть недоступна - Также очистить информацию о новых главах - Внутренняя ошибка сервера (%1$d). Повторите попытку позже - Компактный - Источник отключен - Предварительная загрузка содержимого - Пометить как текущую - Язык - Поделиться логами - Включить логирование - Записывать некоторые действия для отладки - Отображать сомнительный контент - Динамическая - Цветовая схема - Показать в виде сетки - Мику - Аска - Мион - Рикка - Сакура - Службы - Мамими - Канадэ - Чтобы отслеживать прогресс чтения, выберите «Меню» → «Отслеживать» на экране сведений о манге. - Здесь ничего нет - Загрузка началась - Разрешить нестабильные обновления - Предлагать обновления до бета-версий приложения - Пожалуйста, перезапустите приложение, чтобы применить эти изменения - Заголовок UserAgent - Понятно - Нажмите и удерживайте элемент, чтобы изменить их порядок - Вы можете выбрать один или несколько файлов .cbz или .zip, каждый файл будет распознан как отдельная манга. - Вы можете выбрать каталог с архивами или изображениями. Каждый архив (или подкаталог) будет распознан как глава. - Скорость - Импорт ранее созданной резервной копии пользовательских данных - Показать на полке - Найти похожие - Вы можете войти в уже существующий аккаунт или же создать новый - Игнорировать ошибки SSL - Выбрать зеркало автоматически - Автоматически переключать домены для удалённых источников при ошибках, если доступны зеркала - Пауза - Возобновить - Удалить завершённые - Отменить все - Настройки синхронизации - Вы можете использовать собственный сервер синхронизации или сервер по умолчанию. Не изменяйте эту настройку, если не уверены, что делаете. - Адрес сервера - Останавливать загрузку при переключении на мобильную сеть - Приостановлено - Скачивать только через Wi-Fi - Нет, спасибо - Включить - Ещё - Все активные загрузки будут отменены, частично загруженные данные будут утеряны - У Вас нет ни одной загрузки - Загрузки возобновлены - Загрузки приостановлены - Загрузки удалены - Загрузки отменены - Рекомендация: %s - Иногда показывать уведомления с рекомендуемой мангой - Ваша история загрузок будет удалена - Хотите ли Вы получать персонализированные рекомендации манги\? - Переводы - WebView недоступен: проверьте, установлен ли провайдер WebView - Очистить сетевой кеш - Адрес - Тип - Прокси - Порт - %1$s (%2$s) - Неверное значение - \ No newline at end of file + Кэш страниц + %s - %s + Использование хранилища + Доступно + Сохранённая манга + Удалено из избранного + Нет глав + Автоматическое листание + Папка с изображениями + Импорт манги + Импорт завершён + Импорт скоро начнётся + Лента + Сведения об ошибке:<br><tt>%1$s</tt><br><br>1. Попробуйте <a href=%2$s>открыть мангу в веб-браузере</a>, чтобы убедиться, что она доступна в источнике<br>2. Убедитесь, что вы используете <a href=kotatsu://about>последнюю версию Kotatsu</a><br>3. Если возможно, отправьте отчёт об ошибке разработчикам. + Показывать ярлыки последней прочитанной манги + Сделать недавно прочитанную мангу доступной по долгому нажатию на иконку приложения + Нажатие на правый край или нажатие правой клавиши всегда переключает на следующую страницу + Эргономичное управление режимом чтения + Сбросить + Отменить + Сохранить или отменить несохранённые изменения\? + Контрастность + Яркость + Цветокоррекция + Выбранные настройки цвета будут сохранены для этой манги + Не осталось свободного места на накопителе + Масштабирование в режиме манхвы + Показывать слайдер переключения страниц + Включите Wi-Fi или передачу данных, чтобы читать мангу онлайн + Разные языки + Сеть недоступна + Также очистить информацию о новых главах + Внутренняя ошибка сервера (%1$d). Повторите попытку позже + Компактный + Источник отключен + Предварительная загрузка содержимого + Пометить как текущую + Язык + Поделиться логами + Включить логирование + Записывать некоторые действия для отладки + Отображать сомнительный контент + Динамическая + Цветовая схема + Показать в виде сетки + Мику + Аска + Мион + Рикка + Сакура + Службы + Мамими + Канадэ + Чтобы отслеживать прогресс чтения, выберите «Меню» → «Отслеживать» на экране сведений о манге. + Здесь ничего нет + Загрузка началась + Разрешить нестабильные обновления + Предлагать обновления до бета-версий приложения + Пожалуйста, перезапустите приложение, чтобы применить эти изменения + Заголовок UserAgent + Понятно + Нажмите и удерживайте элемент, чтобы изменить их порядок + Вы можете выбрать один или несколько файлов .cbz или .zip, каждый файл будет распознан как отдельная манга. + Вы можете выбрать каталог с архивами или изображениями. Каждый архив (или подкаталог) будет распознан как глава. + Скорость + Импорт ранее созданной резервной копии пользовательских данных + Показать на полке + Найти похожие + Вы можете войти в уже существующий аккаунт или же создать новый + Игнорировать ошибки SSL + Выбрать зеркало автоматически + Автоматически переключать домены для удалённых источников при ошибках, если доступны зеркала + Пауза + Возобновить + Удалить завершённые + Отменить все + Настройки синхронизации + Вы можете использовать собственный сервер синхронизации или сервер по умолчанию. Не изменяйте эту настройку, если не уверены, что делаете. + Адрес сервера + Останавливать загрузку при переключении на мобильную сеть + Приостановлено + Скачивать только через Wi-Fi + Нет, спасибо + Включить + Ещё + Все активные загрузки будут отменены, частично загруженные данные будут утеряны + У Вас нет ни одной загрузки + Загрузки возобновлены + Загрузки приостановлены + Загрузки удалены + Загрузки отменены + Рекомендация: %s + Иногда показывать уведомления с рекомендуемой мангой + Ваша история загрузок будет удалена + Хотите ли Вы получать персонализированные рекомендации манги\? + Переводы + WebView недоступен: проверьте, установлен ли провайдер WebView + Очистить сетевой кеш + Адрес + Тип + Прокси + Порт + %1$s (%2$s) + Неверное значение + diff --git a/app/src/main/res/values-sr/plurals.xml b/app/src/main/res/values-sr/plurals.xml index 815b8609d..43e137252 100644 --- a/app/src/main/res/values-sr/plurals.xml +++ b/app/src/main/res/values-sr/plurals.xml @@ -1,10 +1,5 @@ - - Тотално %1$d странa - Тотално %1$d странице - Тотално %1$d странице - %1$d ставке %1$d ставки diff --git a/app/src/main/res/values-sv/plurals.xml b/app/src/main/res/values-sv/plurals.xml index 6c5a40864..4769abc96 100644 --- a/app/src/main/res/values-sv/plurals.xml +++ b/app/src/main/res/values-sv/plurals.xml @@ -1,9 +1,5 @@ - - Totalt %1$d sida - Totalt %1$d sidor - %1$d artikel %1$d artiklar diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 95ceb535e..7aa01f538 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -54,7 +54,6 @@ Mörkt Denna åtgärden stöds inte Ingen beskrivning - Historik och cache Rensa Rensa all läshistorik permanent\? \"%s\" borttaget från lokal lagring @@ -121,7 +120,6 @@ Vissa enheter har olika systembeteende vilket kan ha sönder bakgrundsjobb. Läs mer Köad - Ladda ned eller läs det saknade kapitlet online. Kapitlet saknas Översätt denna app Översättning @@ -146,7 +144,6 @@ Inaktiverad Kunde inte ladda genrelistan Återställ filter - Hitta genre Välj det språk som du vill läsa manga på. Du kan ändra detta i inställningarna senare. Aldrig Endast på Wi-Fi @@ -158,7 +155,6 @@ Hitta kapitel Inga kapitel i denna manga Utseende - Innehåll Uppdaterar förslag Uteslut genrer Ange genrer som du inte vill få förslag på diff --git a/app/src/main/res/values-tr/plurals.xml b/app/src/main/res/values-tr/plurals.xml index c0c12380a..447fd4fea 100644 --- a/app/src/main/res/values-tr/plurals.xml +++ b/app/src/main/res/values-tr/plurals.xml @@ -1,9 +1,5 @@ - - Toplam %1$d sayfa - Toplam %1$d sayfa - %1$d öge %1$d öge diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d8eae7df3..bea32c07d 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,422 +1,418 @@ - Ağ hatası - Dahili Depolama - Favoriler - Geçmiş - Bölümler - Liste - Detaylı liste - Izgara - Liste modu - Yükleniyor… - Kapat - Tekrar dene - Geçmişi temizle - Hiçbir şey bulunamadı - Geçmiş yok - Oku - Henüz favorileriniz yok - Favoriniz - Yeni kategori - Ekle - Kaydet - Paylaş - %s Paylaş - Ara - Manga ara - İndiriliyor… - İşleniyor… - İndirildi - İndirilenler - Ad - Güncellenme - Yeniler - Puanlama - Litre - Tema - Açık - Koyu - Takip sistemi - Sayfalar - Temizle - Tüm okuma geçmişi kalıcı olarak silinsin mi\? - Kaldır - “%s” yerel depolama alanından sil - Sayfayı kaydet - Resmi paylaş - Popüler - Detaylar - Ayarlar - Kaydet - Bir hata oluştu - Manga kaynakları - Geçmiş ve önbellek - Temizlendi - Devam - Müsait değil - Boş kategori - Kaldır - Sil - Bölüm %1$d / %2$d - Bir ZIP veya CBZ dosyası seçin. - Okuma modu - Izgara boyutu - Webtoon - B|kB|MB|GB|TB - Okuyucu ayarları - Ses butonları - Hata - Küçük resim önbelleğini temizle - Yalnızca hareketler - Alan adi - Web tarayıcısında aç - Yeni bölümler - Bildirim ayarları - Bildirim sesi - LED göstergesi - Titreşim - Diğer depolama - Güncellemeler - Kısayol oluştur… - İçe aktar - Mangayı sil - Bilgi işleniyor… - Sıralama düzeni - Açıklama yok - Bu işlem desteklenmiyor - Standart - Sayfa önbelleğini temizle - %s üzerinde ara - Dahili depolama - Bildirimler - Sayfaları değiştir - Kaydet - İndir - İndirilenler klasörü - Harici depolama - Uygulamanın yeni bir sürümü mevcut - Favori kategoriler - Bitti - Sonra oku - Sayfa animasyonu - Kullanılabilir depolama alanı yok - “%s” cihazdan kalıcı olarak silinsin mi\? - Arama geçmişini temizle - Burası biraz boş… - Ekranı döndür - Ölçek modu - Yüksekliğe sığdır - Siyah - Başlangıçta tut - Akışı temizle - Bu eksik bölümü çevrim içi olarak indirin veya okuyun. - Yedekten geri yükle - Güncelle - Oturum aç - Bitti - Hakkında - Bu içeriği görüntülemek için oturum açın - Onayla - Yetkilendirildi - Az önce - Kenar dokunuşları - Bu mangada %s var. Hepsi kaydedilsin mi\? - %1$d / %2$d açık - Sorguyu yeniden biçimlendirmeyi deneyin. - Okuduklarınız burada görüntülenecek - Yan menüde ne okuyacağınızı bulun. - Önce bir şey kaydedin - Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. - Raf - Son - Boyut: %s - Temizlendi - Parola gir - Kotatsu başlatılırken parola sor - Güncellemeleri ara - Güncelleme akışını temizle - Akış güncellemesi yakında başlayacak - Sürüm %s - Güncellemeleri denetle - Merkeze sığdır - Genişliğe sığdır - AMOLED ekranlarda daha az güç kullanır - Yedekle ve geri yükle - Veri yedeği oluştur - Geri yüklendi - Hazırlanıyor… - Dün - Grup - Sessiz - Çöz - Çerezleri temizle - Öntanımlı: %s - Ters - Parola 4 veya daha fazla karakterden oluşmalıdır - Hoş geldiniz - Sıraya alındı - Bölüm eksik - Bu uygulamayı çevirin - Çeviri - Devam ediyor - Tüm kaynaklardaki oturumunuz kapatılacak - Kullanılan kaynaklar - Kullanılabilir kaynaklar - Uygunsuz mangayı geçmişten hariç tut - Numaralı sayfalar - Arama sonuçları - Parolayı tekrarla - Denetleme - Yanlış parola - Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz - Uzun zaman önce - Bugün - Güncelleme yok - Tüm favoriler - Okuduklarınızın yeni bölümleri burada gösterilir - Yeni sürüm: %s - Uygulamayı koru - Parolalar eşleşmiyor - Sağdan-sola - Yeni kategori - Dosya bulunamadı - Tüm veriler geri yüklendi - Veriler geri yüklendi, ancak hatalar var - Tekrar denemek için dokunun - İleri - CAPTCHA gerekli - Tüm çerezler kaldırıldı - Seçilen yapılandırma bu manga için hatırlanacak - Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? - Uygulamayı başlatmak için bir parola girin - Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? - Yedek kaydedildi - Türler - Öntanımlı - %s üzerinde oturum açma desteklenmiyor - Daha fazla oku - Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. - Ekran görüntüsü politikası - Uygunsuzlarda engelle - Her zaman engelle - İzin ver - Yeni bölümleri denetle - Öneriler - Önerileri etkinleştir - Tercihlerinize göre manga önerileri alın - Tüm veriler sadece bu cihaz üzerinde yerel olarak işlenir ve asla herhangi bir yere satılmaz. - Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız - Uygunsuz manga önerme - Etkin - Devre dışı - Türler listesi yüklenemiyor - Filtreyi sıfırla - Tür bul - Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. - Her zaman - Hiçbir zaman - Yalnızca Wi-Fi\'de - Sayfaları önceden yükle - %s olarak oturum açıldı - 18+ - Çeşitli diller - Bölüm bul - Bu mangada bölüm yok - %%%1$s - İçerik - Öneriler güncelleniyor - Görünüm - Türleri hariç tut - Önerilerde görmek istemediğiniz türleri belirtin - Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? - Kaldırma tamamlandı - Bölümler arka planda kaldırılacak. - İndirmeyi yavaşlat - IP adresinizin engellenmesinden kaçınmanıza yardımcı olur - Kaydedilen manga işleme - Gizle - Yeni manga kaynakları var - Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak - Bildirimleri etkinleştir - Yeni bölümleri denetle ve bildirim gönder - Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız - Favori kategori yok - Ad - Düzenle - Kategoriyi düzenle - Yer imi ekle - Yer imini kaldır - Yer imleri - Yer imi kaldırıldı - Yer imi eklendi - Geri al - Geçmişten kaldırıldı - HTTPS üzerinden DNS - Okuyucu modunu otomatik algıla - Manganın webtoon olup olmadığını otomatik olarak algıla - Öntanımlı mod - Pil iyileştirmesini devre dışı bırak - Arka planda güncelleme denetimlerine yardımcı olur - Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. - Gönder - Tümünü devre dışı bırak - Varsa parmak izi kullan - Favorilerinizden mangalar - Son okuduğunuz mangalar - Bildir - İzleme - Oturumu kapat - Okunuyor - Tamamlandı - Okuma ilerleme göstergelerini göster - Verileri sil - Geçmişte ve favorilerde okunma yüzdesini göster - Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir - Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır - Beklemede - Bırakıldı - Planlandı - Yeniden okunuyor - Tümünü göster - Geçersiz etki alanı - Aralık seç - İçerik bulunamadı veya kaldırıldı - Manganız burada görüntülenecek - İptal edilmiş - Hesap zaten var - Geri - Senkronizasyon - Verini yedekle - Devam etmek için E-Postanızı girin - Tüm gecmişi temizle - Son 2 saat - Geçmiş temizlendi - Yönet - Yer işareti yok - Manga okurken yer işareti oluşturabilirsiniz - Yer işaretleri kaldırıldı - Manga kaynağı yok - Çevrimiçi manga okumak için manga kaynaklarını aktif edin - Rastgele - Boş - Keşfet - Çıkmak için tekrar Geri tıkla - Çıkmak için iki defa Geri tıkla - Favorilerden kaldırıldı - Çıkış doğrulaması - Çizgi roman arşivi - Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. <a href=kotatsu://about> Kotatsunun son sürümünü kullandığnızdan emin olun.</a>/br> 3. Mevcutsa, geliştiricilere bir hata reporu gönderin. - «Keşfet» kısmında neler okuyacağınızı bulun - Seçilen favori kategorileri silmek istediğinizden emin misiniz\? + Ağ hatası + Dahili Depolama + Favoriler + Geçmiş + Bölümler + Liste + Detaylı liste + Izgara + Liste modu + Yükleniyor… + Kapat + Tekrar dene + Geçmişi temizle + Hiçbir şey bulunamadı + Geçmiş yok + Oku + Henüz favorileriniz yok + Favoriniz + Yeni kategori + Ekle + Kaydet + Paylaş + %s Paylaş + Ara + Manga ara + İndiriliyor… + İşleniyor… + İndirildi + İndirilenler + Ad + Güncellenme + Yeniler + Puanlama + Litre + Tema + Açık + Koyu + Takip sistemi + Sayfalar + Temizle + Tüm okuma geçmişi kalıcı olarak silinsin mi\? + Kaldır + “%s” yerel depolama alanından sil + Sayfayı kaydet + Resmi paylaş + Popüler + Detaylar + Ayarlar + Kaydet + Bir hata oluştu + Manga kaynakları + Temizlendi + Devam + Müsait değil + Boş kategori + Kaldır + Sil + Bölüm %1$d / %2$d + Bir ZIP veya CBZ dosyası seçin. + Okuma modu + Izgara boyutu + Webtoon + B|kB|MB|GB|TB + Okuyucu ayarları + Ses butonları + Hata + Küçük resim önbelleğini temizle + Yalnızca hareketler + Alan adi + Web tarayıcısında aç + Yeni bölümler + Bildirim ayarları + Bildirim sesi + LED göstergesi + Titreşim + Diğer depolama + Güncellemeler + Kısayol oluştur… + İçe aktar + Mangayı sil + Bilgi işleniyor… + Sıralama düzeni + Açıklama yok + Bu işlem desteklenmiyor + Standart + Sayfa önbelleğini temizle + %s üzerinde ara + Dahili depolama + Bildirimler + Sayfaları değiştir + Kaydet + İndir + İndirilenler klasörü + Harici depolama + Uygulamanın yeni bir sürümü mevcut + Favori kategoriler + Bitti + Sonra oku + Sayfa animasyonu + Kullanılabilir depolama alanı yok + “%s” cihazdan kalıcı olarak silinsin mi\? + Arama geçmişini temizle + Burası biraz boş… + Ekranı döndür + Ölçek modu + Yüksekliğe sığdır + Siyah + Başlangıçta tut + Akışı temizle + Yedekten geri yükle + Güncelle + Oturum aç + Bitti + Hakkında + Bu içeriği görüntülemek için oturum açın + Onayla + Yetkilendirildi + Az önce + Kenar dokunuşları + Bu mangada %s var. Hepsi kaydedilsin mi\? + %1$d / %2$d açık + Sorguyu yeniden biçimlendirmeyi deneyin. + Okuduklarınız burada görüntülenecek + Yan menüde ne okuyacağınızı bulun. + Önce bir şey kaydedin + Çevrim içi kaynaklardan kaydedin veya dosyaları içe aktarın. + Raf + Son + Boyut: %s + Temizlendi + Parola gir + Kotatsu başlatılırken parola sor + Güncellemeleri ara + Güncelleme akışını temizle + Akış güncellemesi yakında başlayacak + Sürüm %s + Güncellemeleri denetle + Merkeze sığdır + Genişliğe sığdır + AMOLED ekranlarda daha az güç kullanır + Yedekle ve geri yükle + Veri yedeği oluştur + Geri yüklendi + Hazırlanıyor… + Dün + Grup + Sessiz + Çöz + Çerezleri temizle + Öntanımlı: %s + Ters + Parola 4 veya daha fazla karakterden oluşmalıdır + Hoş geldiniz + Sıraya alındı + Bölüm eksik + Bu uygulamayı çevirin + Çeviri + Devam ediyor + Tüm kaynaklardaki oturumunuz kapatılacak + Kullanılan kaynaklar + Kullanılabilir kaynaklar + Uygunsuz mangayı geçmişten hariç tut + Numaralı sayfalar + Arama sonuçları + Parolayı tekrarla + Denetleme + Yanlış parola + Geçmişinizin ve favorilerinizin yedeğini oluşturabilir ve bunları geri yükleyebilirsiniz + Uzun zaman önce + Bugün + Güncelleme yok + Tüm favoriler + Okuduklarınızın yeni bölümleri burada gösterilir + Yeni sürüm: %s + Uygulamayı koru + Parolalar eşleşmiyor + Sağdan-sola + Yeni kategori + Dosya bulunamadı + Tüm veriler geri yüklendi + Veriler geri yüklendi, ancak hatalar var + Tekrar denemek için dokunun + İleri + CAPTCHA gerekli + Tüm çerezler kaldırıldı + Seçilen yapılandırma bu manga için hatırlanacak + Tüm güncelleme geçmişi kalıcı olarak silinsin mi\? + Uygulamayı başlatmak için bir parola girin + Tüm son arama sorguları kalıcı olarak kaldırılsın mı\? + Yedek kaydedildi + Türler + Öntanımlı + %s üzerinde oturum açma desteklenmiyor + Daha fazla oku + Bazı aygıtların arka plan görevlerini bozabilecek farklı sistem davranışları vardır. + Ekran görüntüsü politikası + Uygunsuzlarda engelle + Her zaman engelle + İzin ver + Yeni bölümleri denetle + Öneriler + Önerileri etkinleştir + Tercihlerinize göre manga önerileri alın + Tüm veriler sadece bu cihaz üzerinde yerel olarak işlenir ve asla herhangi bir yere satılmaz. + Manga okumaya başladıktan sonra kişiselleştirilmiş öneriler alacaksınız + Uygunsuz manga önerme + Etkin + Devre dışı + Türler listesi yüklenemiyor + Filtreyi sıfırla + Manga okumak istediğiniz dilleri seçin. Daha sonra ayarlardan değiştirebilirsiniz. + Her zaman + Hiçbir zaman + Yalnızca Wi-Fi\'de + Sayfaları önceden yükle + %s olarak oturum açıldı + 18+ + Çeşitli diller + Bölüm bul + Bu mangada bölüm yok + %%%1$s + Öneriler güncelleniyor + Görünüm + Türleri hariç tut + Önerilerde görmek istemediğiniz türleri belirtin + Seçilen ögeler aygıttan kalıcı olarak silinsin mi\? + Kaldırma tamamlandı + Bölümler arka planda kaldırılacak. + İndirmeyi yavaşlat + IP adresinizin engellenmesinden kaçınmanıza yardımcı olur + Kaydedilen manga işleme + Gizle + Yeni manga kaynakları var + Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak + Bildirimleri etkinleştir + Yeni bölümleri denetle ve bildirim gönder + Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız + Favori kategori yok + Ad + Düzenle + Kategoriyi düzenle + Yer imi ekle + Yer imini kaldır + Yer imleri + Yer imi kaldırıldı + Yer imi eklendi + Geri al + Geçmişten kaldırıldı + HTTPS üzerinden DNS + Okuyucu modunu otomatik algıla + Manganın webtoon olup olmadığını otomatik olarak algıla + Öntanımlı mod + Pil iyileştirmesini devre dışı bırak + Arka planda güncelleme denetimlerine yardımcı olur + Bir şeyler yanlış gitti. Düzeltmemize yardımcı olması için lütfen geliştiricilere bir hata bildirimi gönderin. + Gönder + Tümünü devre dışı bırak + Varsa parmak izi kullan + Favorilerinizden mangalar + Son okuduğunuz mangalar + Bildir + İzleme + Oturumu kapat + Okunuyor + Tamamlandı + Okuma ilerleme göstergelerini göster + Verileri sil + Geçmişte ve favorilerde okunma yüzdesini göster + Uygunsuz olarak işaretlenen mangalar asla geçmişe eklenmeyecek ve ilerlemeniz kaydedilmeyecektir + Bazı sorunlarda yardımcı olabilir. Tüm yetkilendirmeler geçersiz kılınacaktır + Beklemede + Bırakıldı + Planlandı + Yeniden okunuyor + Tümünü göster + Geçersiz etki alanı + Aralık seç + İçerik bulunamadı veya kaldırıldı + Manganız burada görüntülenecek + İptal edilmiş + Hesap zaten var + Geri + Senkronizasyon + Verini yedekle + Devam etmek için E-Postanızı girin + Tüm gecmişi temizle + Son 2 saat + Geçmiş temizlendi + Yönet + Yer işareti yok + Manga okurken yer işareti oluşturabilirsiniz + Yer işaretleri kaldırıldı + Manga kaynağı yok + Çevrimiçi manga okumak için manga kaynaklarını aktif edin + Rastgele + Boş + Keşfet + Çıkmak için tekrar Geri tıkla + Çıkmak için iki defa Geri tıkla + Favorilerden kaldırıldı + Çıkış doğrulaması + Çizgi roman arşivi + Hata ayrıntıları:<br><tt>%1$s</tt><br><br>1.Mangayı <a href=%2$s>kaynağında mevcut olduğuna emin olmak için</a> bir web tarayıcısında açın<br>2. <a href=kotatsu://about> Kotatsunun son sürümünü kullandığnızdan emin olun.</a>/br> 3. Mevcutsa, geliştiricilere bir hata reporu gönderin. + «Keşfet» kısmında neler okuyacağınızı bulun + Seçilen favori kategorileri silmek istediğinizden emin misiniz\? \nİçindeki tüm mangalar kaybolur ve bu işlem geri alınamaz. - Yeniden sırala - Sayfa önbelleği - Diğer önbellekler - Depolama kullanımı - Mevcut - %s - %s - Seçenekler - Gizli mod - Bölüm yok - Otomatik kaydır - Böl. %1$d/%2$d Sayf. %3$d/%4$d - Okuyucuda bilgi çubuğu göster - Resimlerle klasör - Manga içe aktarılıyor - İçe aktarım tamamlandı - Yer açmak için orijinal dosyayı depolamadan silebilirsiniz - İçe aktarım birazdan başlayacak - Akış - En son manga kısayollarını göster - Ergonomik okuyucu kontrol - Renk düzeltme - Parlaklık - Kontrast - Sıfırla - Seçilen renk ayarları bu manga için hatırlanacaktır - Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? - Yoksay - Cihazda yer yok - Webtoon yakınlaştırma - Sayfa değiştirme kaydırıcısını göster - Ayrıca yeni bölümler hakkındaki bilgileri temizle - Sıkı - Farklı diller - Ağ kullanılamıyor - Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın - Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin - Kaydedilen mangalar - Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin - Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir - Kaynak devre dışı - İçerik ön yüklemesi - Geçerli olarak işaretle - Dil - Günlükleri paylaş - Günlük kaydını etkinleştir - Hata ayıklama amacıyla bazı eylemleri kaydedin - Şüpheli içeriği göster - Hizmetler - Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. - burada hiçbir şey yok - Dinamik - renk vurgusu - Izgara görünümünde göster - Mamimi - Kanade - UserAgent başlığı - Uygulamanın beta sürümleri için güncellemeler öner - Kararsız güncellemelere izin ver - İndirme başladı - Miku - Asuka - Mion - Rikka - Sakura - Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın - Benzerini bul - Çeviriler - WebView kullanılamıyor: WebView sağlayıcısının kurulu olup olmadığını kontrol edin - Etkinleştir - Hayır teşekkürler - İnternet geçmişini temizle - Eşitleme seçenekleri - Sunucu adresi - "Şirket içinde barındırılan bir eşitleme sunucusu veya varsayılan bir sunucu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin." - Yansıtmalar varsa, hatalarda uzak kaynaklar için etki alanlarını otomatik olarak değiştir - Mobil ağa geçerken indirmeyi durdur - Bitirilenleri kaldır - Hepsini iptal et - Sadece Wi-Fi ile indir - Anladım - Yeniden sıralamak için bir öğeye dokunun ve basılı tutun - Bir veya daha fazla .cbz veya .zip dosyası seçebilirsiniz, her dosya ayrı bir manga olarak tanınacaktır. - Arşivler veya resimler içeren bir dizin seçebilirsiniz. Her arşiv (veya alt dizin) bir bölüm olarak tanınacaktır. - Hız - Kullanıcı verilerinin önceden oluşturulmuş bir yedeğini içe aktarın - Rafta Göster - Mevcut bir hesapta oturum açabilir veya yeni bir hesap oluşturabilirsiniz. - SSL hatalarını görmezden gel - Durdur - Devam et - Durduruldu - Öneri:%s - Bazen manga öneri bildirimlerilerini göster - Daha fazla - Tüm aktif indirmeler iptal edilecek, kısmen indirilen veriler kaybolacak - İndirme geçmişin tamamen silinecek - Hiçbir indirmeniz yok - İndirmeler devam ettirildi - İndirmeler durduruldu - İndirmeler silindi - Aynayı otomatik olarak seç - İndirmeler iptal edildi - Kişiselleştirilmiş manga önerileri almak istiyor musunuz\? - Adres - Tür - %1$s (%2$s) - Menü - Proxy - Geçersiz değer - \ No newline at end of file + Yeniden sırala + Sayfa önbelleği + Diğer önbellekler + Depolama kullanımı + Mevcut + %s - %s + Seçenekler + Gizli mod + Bölüm yok + Otomatik kaydır + Böl. %1$d/%2$d Sayf. %3$d/%4$d + Okuyucuda bilgi çubuğu göster + Resimlerle klasör + Manga içe aktarılıyor + İçe aktarım tamamlandı + Yer açmak için orijinal dosyayı depolamadan silebilirsiniz + İçe aktarım birazdan başlayacak + Akış + En son manga kısayollarını göster + Ergonomik okuyucu kontrol + Renk düzeltme + Parlaklık + Kontrast + Sıfırla + Seçilen renk ayarları bu manga için hatırlanacaktır + Kaydedilmeyen değişiklikler kaydedilsin mi yoksa atılsın mı\? + Yoksay + Cihazda yer yok + Webtoon yakınlaştırma + Sayfa değiştirme kaydırıcısını göster + Ayrıca yeni bölümler hakkındaki bilgileri temizle + Sıkı + Farklı diller + Ağ kullanılamıyor + Çevrim içi manga okumak için Wi-Fi veya mobil ağı açın + Sunucu tarafı hatası (%1$d). Lütfen daha sonra tekrar deneyin + Kaydedilen mangalar + Uygulama simgesine uzun basarak son mangaları kullanılabilir hale getirin + Sağ kenara dokunulduğunda veya sağ tuşa basıldığında her zaman bir sonraki sayfaya geçilir + Kaynak devre dışı + İçerik ön yüklemesi + Geçerli olarak işaretle + Dil + Günlükleri paylaş + Günlük kaydını etkinleştir + Hata ayıklama amacıyla bazı eylemleri kaydedin + Şüpheli içeriği göster + Hizmetler + Okuma ilerlemesini izlemek için manga ayrıntıları ekranında Menü → İzle\'yi seçin. + burada hiçbir şey yok + Dinamik + renk vurgusu + Izgara görünümünde göster + Mamimi + Kanade + UserAgent başlığı + Uygulamanın beta sürümleri için güncellemeler öner + Kararsız güncellemelere izin ver + İndirme başladı + Miku + Asuka + Mion + Rikka + Sakura + Bu değişiklikleri uygulamak için lütfen uygulamayı yeniden başlatın + Benzerini bul + Çeviriler + WebView kullanılamıyor: WebView sağlayıcısının kurulu olup olmadığını kontrol edin + Etkinleştir + Hayır teşekkürler + İnternet geçmişini temizle + Eşitleme seçenekleri + Sunucu adresi + "Şirket içinde barındırılan bir eşitleme sunucusu veya varsayılan bir sunucu kullanabilirsiniz. Ne yaptığınızdan emin değilseniz bunu değiştirmeyin." + Yansıtmalar varsa, hatalarda uzak kaynaklar için etki alanlarını otomatik olarak değiştir + Mobil ağa geçerken indirmeyi durdur + Bitirilenleri kaldır + Hepsini iptal et + Sadece Wi-Fi ile indir + Anladım + Yeniden sıralamak için bir öğeye dokunun ve basılı tutun + Bir veya daha fazla .cbz veya .zip dosyası seçebilirsiniz, her dosya ayrı bir manga olarak tanınacaktır. + Arşivler veya resimler içeren bir dizin seçebilirsiniz. Her arşiv (veya alt dizin) bir bölüm olarak tanınacaktır. + Hız + Kullanıcı verilerinin önceden oluşturulmuş bir yedeğini içe aktarın + Rafta Göster + Mevcut bir hesapta oturum açabilir veya yeni bir hesap oluşturabilirsiniz. + SSL hatalarını görmezden gel + Durdur + Devam et + Durduruldu + Öneri:%s + Bazen manga öneri bildirimlerilerini göster + Daha fazla + Tüm aktif indirmeler iptal edilecek, kısmen indirilen veriler kaybolacak + İndirme geçmişin tamamen silinecek + Hiçbir indirmeniz yok + İndirmeler devam ettirildi + İndirmeler durduruldu + İndirmeler silindi + Aynayı otomatik olarak seç + İndirmeler iptal edildi + Kişiselleştirilmiş manga önerileri almak istiyor musunuz\? + Adres + Tür + %1$s (%2$s) + Menü + Proxy + Geçersiz değer + diff --git a/app/src/main/res/values-uk/plurals.xml b/app/src/main/res/values-uk/plurals.xml index 1db12997c..2219d916a 100644 --- a/app/src/main/res/values-uk/plurals.xml +++ b/app/src/main/res/values-uk/plurals.xml @@ -12,12 +12,6 @@ %1$d хвилин тому %1$d хвилин тому - - Всього %1$d сторінка - Всього %1$d сторінки - Всього %1$d сторінок - Всього %1$d сторінок - %1$d годину тому %1$d години тому diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c9ab878da..e7c74087b 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -1,422 +1,418 @@ - Видалити - Нічого не знайдено - Додати до улюблених - Очистити історію - Історії ще немає - Додати - Зберегти - Локальне сховище - Помилка мережі - Деталі - Спробуйте ще раз - Улюблених ще немає - Нова категорія - Завантажено - Уподобання - Історія - Сталася помилка - Розділи - Список - Детальний список - Режим списку - Налаштування - Джерела манги - Завантаження… - Обчислення… - Розділ %1$d із %2$d - Закрити - Читати - Таблиця - Поділитися - Створити ярлик… - Поділитися %s - Пошук - Пошук манґи - Обробка… - Ім\'я - Популярна - Оновлена - Нова - Рейтинг - Порядок сортування - Фільтр - Тема - Світла - Темна - Сторінки - Очистити всю історію читання перманентно\? - Видалити - \"%s\" видалено з локального сховища - Зберегти сторінку - Збережено - Поділитись зображенням - Ця операція не підтримується - Виберіть файл ZIP або CBZ. - Немає опису - Історія та кеш - Очистити кеш сторінок - Б|кБ|МБ|ГБ|ТБ - Стандартний - Манхва - Режим читання - Розмір сітки - Пошук по %s - Видалити манґу - Видалити \"%s\" з пристрою перманентно\? - Налаштування читача - Перегортання сторінок - Кнопки гучності - Помилка - Очистити кеш мініатюр - Очистити історію пошуку - Очищено - Тільки жести - Внутрішнє сховище - Зовнішнє сховище - Домен - Доступна нова версія застосунку - Ця манґа має %s. Зберегти все це\? - Зберегти - Сповіщення - Увімкнено %1$d з %2$d - Нові розділи - Завантажити - Вібрація - Улюблені категорії - Видалити - Тут якось пусто… - Спробуйте переформулювати запит. - Те, що ви читаєте, буде показано тут - Знайдіть, що читати, у бічному меню. - Спочатку збережіть щось - Збережіть його з онлайн-джерела або імпортуйте файли. - Полиця - Недавні - Анімація перегортання - Тека для завантажень - Інше сховище - Готово - Усі улюблені - Порожня категорія - Прочитати пізніше - Оновлення - Нова версія: %s - Розмір: %s - Очистити стрічку оновлень - Очищено - Повернути екран - Оновити - Оновлення скоро почнеться - Стежити за оновленнями - Не перевіряти - Неправильний пароль - Захистити застосунок - Запитувати пароль під час запуску Kotatsu - Повторіть пароль - Паролі не співпадають - Про застосунок - Версія %s - Перевірити наявність оновлень - Немає доступних оновлень - Нова категорія - Режим масштабування - Вмістити в екран - Підігнати по висоті - Підігнати по ширині - Вихідний розмір - Чорна - Споживає менше енергії на екранах AMOLED - Резервне копіювання та відновлення - Відновлено - Підготовка… - Файл не знайдено - Дані відновлено, але є деякі помилки - Ви можете створити резервну копію своєї історії та уподобань і відновити їх - Тільки що - Торкніться, щоб спробувати ще раз - Обраний режим буде запам\'ятован для цієї манги - Потрібна CAPTCHA - Пройти - Очистити кукі - Всі кукі були видалені - Очистити стрічку - Перевірити нові розділи - В зворотньому порядку - Увійти - Увійдіть, щоб переглянути цей вміст - За замовчуванням: %s - Далі - Введіть пароль для запуску застосунку - Підтвердити - Пароль має містити 4 символи або більше - Ласкаво просимо - Резервна копія збережена - Докладніше - У черзі - Допомогти з перекладом застосунку - Переклад - Авторизація виконана - Вхід на %s не підтримується - Ви вийдете з усіх джерел - Завершена - Триває - Виключити NSFW манґу з історії - Показувати номери сторінок - Включені джерела - Політика щодо знімків екрана - Дозволити - Пропонувати манґу на основі ваших уподобань - Усі дані аналізуються лише локально на цьому пристрої й ніколи нікуди не надсилаються. - Почніть читати манґу, і ви отримаєте персоналізовані пропозиції - Увімкнено - Вимкнено - Скинути фільтр - Знайти жанр - Виберіть мови, якими ви хочете читати манґу. Це можливо змінити пізніше в налаштуваннях. - Тільки по Wi-Fi - Попереднє завантаження сторінок - Ви увійшли як %s - 18+ - Різні мови - Знайти розділ - Немає розділів у цій манзі - %1$s%% - Зміст - Оновлення пропозицій - Видалити вибрані елементи з пристрою назавжди\? - Видалення завершено - Сповільнення завантаження - Обробка збереженої манґи - Приховати - Доступні нові джерела манґи - Завантаження… - Очистити - Завантаження - Як в системі - Завантажте або прочитайте цей відсутній розділ онлайн. - Розділ відсутній - Жанри - За замовчуванням - Завжди - Продовжити - Імпорт - Натискання по краях - Налаштування сповіщень - Відкрити у веб-браузері - Недоступно - Немає доступного сховища - Нові розділи того, що ви читаєте, показано тут - Результати пошуку - Введіть пароль - Звук сповіщень - Світлодіодний індикатор - Учора - Справа наліво (←) - Створити резервну копію - Відновити з резервної копії - Всі дані були відновлені - Групувати - Сьогодні - Без звуку - Давно - Очистити всю історію оновлень назавжди\? - Деякі пристрої мають різну поведінку системи, що може порушити фонові завдання. - Видалити всі останні пошукові запити назавжди\? - Доступні джерела - Блок на NSFW - Завжди блокувати - Пропозиції - Увімкнути пропозиції - Не пропонувати NSFW манґу - Не вдалося завантажити список жанрів - Ніколи - Зовнішній вигляд - Виключити жанри - Укажіть жанри, які ви не хочете бачити в пропозиціях - Допомагає уникнути блокування вашої IP-адреси - Розділи буде видалено у фоновому режимі - Перевіряти наявність нових розділів і повідомляти про них - Ви будете отримувати повідомлення про оновлення манґи, яку ви читаєте - Увімкнути сповіщення - Ви не будете отримувати повідомлення, але нові розділи будуть відображатися у списку - Немає улюблених категорій - Назва - Змінити - Змінити категорію - Додати закладку - Видалити закладку - Закладки - Закладка видалена - Додано закладку - Відмінити - Видалено з історії - DNS через HTTPS - Режим за замовчуванням - Автоматично визначати, чи є манґа вебтуном - Автовизначення режиму читання - Вимкнути оптимізацію акумулятора - Допомагає з перевірками фонових оновлень - Щось пішло не так. Будь ласка, надішліть звіт про помилку розробникам, щоб допомогти нам її виправити. - Надіслати - Вимкнути все - Використовувати відбиток пальця, якщо доступно - Манга з Вашого улюбленого - Манга, яку Ви нещодавно читали - Недійсний домен - Звіт - Відстеження - Вийти - Заплановано - Читаю - Перечитую - Завершено - Відкладено - Занедбано - Показувати індикатори прогресу читання - Видалення даних - Показати відсоток прочитаного в історії та обраному - Манґа, позначена як NSFW, ніколи не буде додана до історії і ваш прогрес не буде збережений - Може допомогти в разі виникнення проблем. Усі авторизації будуть анульовані - Показати всі - Виберіть діапазон - Вміст не знайдено або видалено - Ваша манга буде відображатися тут - Знайдіть, що почитати у розділі «Огляд» - Назад - Введіть свою електронну пошту, щоб продовжити - Історія очищена - Керувати - Закладок ще немає - Ви можете створювати закладки під час читання манґи - Закладки видалено - Немає джерел манґи - Увімкніть джерела манґи, щоб читати онлайн - Випадкова - Ви впевнені, що бажаєте видалити вибрані улюблені категорії\? + Видалити + Нічого не знайдено + Додати до улюблених + Очистити історію + Історії ще немає + Додати + Зберегти + Локальне сховище + Помилка мережі + Деталі + Спробуйте ще раз + Улюблених ще немає + Нова категорія + Завантажено + Уподобання + Історія + Сталася помилка + Розділи + Список + Детальний список + Режим списку + Налаштування + Джерела манги + Завантаження… + Обчислення… + Розділ %1$d із %2$d + Закрити + Читати + Таблиця + Поділитися + Створити ярлик… + Поділитися %s + Пошук + Пошук манґи + Обробка… + Ім\'я + Популярна + Оновлена + Нова + Рейтинг + Порядок сортування + Фільтр + Тема + Світла + Темна + Сторінки + Очистити всю історію читання перманентно\? + Видалити + \"%s\" видалено з локального сховища + Зберегти сторінку + Збережено + Поділитись зображенням + Ця операція не підтримується + Виберіть файл ZIP або CBZ. + Немає опису + Очистити кеш сторінок + Б|кБ|МБ|ГБ|ТБ + Стандартний + Манхва + Режим читання + Розмір сітки + Пошук по %s + Видалити манґу + Видалити \"%s\" з пристрою перманентно\? + Налаштування читача + Перегортання сторінок + Кнопки гучності + Помилка + Очистити кеш мініатюр + Очистити історію пошуку + Очищено + Тільки жести + Внутрішнє сховище + Зовнішнє сховище + Домен + Доступна нова версія застосунку + Ця манґа має %s. Зберегти все це\? + Зберегти + Сповіщення + Увімкнено %1$d з %2$d + Нові розділи + Завантажити + Вібрація + Улюблені категорії + Видалити + Тут якось пусто… + Спробуйте переформулювати запит. + Те, що ви читаєте, буде показано тут + Знайдіть, що читати, у бічному меню. + Спочатку збережіть щось + Збережіть його з онлайн-джерела або імпортуйте файли. + Полиця + Недавні + Анімація перегортання + Тека для завантажень + Інше сховище + Готово + Усі улюблені + Порожня категорія + Прочитати пізніше + Оновлення + Нова версія: %s + Розмір: %s + Очистити стрічку оновлень + Очищено + Повернути екран + Оновити + Оновлення скоро почнеться + Стежити за оновленнями + Не перевіряти + Неправильний пароль + Захистити застосунок + Запитувати пароль під час запуску Kotatsu + Повторіть пароль + Паролі не співпадають + Про застосунок + Версія %s + Перевірити наявність оновлень + Немає доступних оновлень + Нова категорія + Режим масштабування + Вмістити в екран + Підігнати по висоті + Підігнати по ширині + Вихідний розмір + Чорна + Споживає менше енергії на екранах AMOLED + Резервне копіювання та відновлення + Відновлено + Підготовка… + Файл не знайдено + Дані відновлено, але є деякі помилки + Ви можете створити резервну копію своєї історії та уподобань і відновити їх + Тільки що + Торкніться, щоб спробувати ще раз + Обраний режим буде запам\'ятован для цієї манги + Потрібна CAPTCHA + Пройти + Очистити кукі + Всі кукі були видалені + Очистити стрічку + Перевірити нові розділи + В зворотньому порядку + Увійти + Увійдіть, щоб переглянути цей вміст + За замовчуванням: %s + Далі + Введіть пароль для запуску застосунку + Підтвердити + Пароль має містити 4 символи або більше + Ласкаво просимо + Резервна копія збережена + Докладніше + У черзі + Допомогти з перекладом застосунку + Переклад + Авторизація виконана + Вхід на %s не підтримується + Ви вийдете з усіх джерел + Завершена + Триває + Виключити NSFW манґу з історії + Показувати номери сторінок + Включені джерела + Політика щодо знімків екрана + Дозволити + Пропонувати манґу на основі ваших уподобань + Усі дані аналізуються лише локально на цьому пристрої й ніколи нікуди не надсилаються. + Почніть читати манґу, і ви отримаєте персоналізовані пропозиції + Увімкнено + Вимкнено + Скинути фільтр + Виберіть мови, якими ви хочете читати манґу. Це можливо змінити пізніше в налаштуваннях. + Тільки по Wi-Fi + Попереднє завантаження сторінок + Ви увійшли як %s + 18+ + Різні мови + Знайти розділ + Немає розділів у цій манзі + %1$s%% + Оновлення пропозицій + Видалити вибрані елементи з пристрою назавжди\? + Видалення завершено + Сповільнення завантаження + Обробка збереженої манґи + Приховати + Доступні нові джерела манґи + Завантаження… + Очистити + Завантаження + Як в системі + Розділ відсутній + Жанри + За замовчуванням + Завжди + Продовжити + Імпорт + Натискання по краях + Налаштування сповіщень + Відкрити у веб-браузері + Недоступно + Немає доступного сховища + Нові розділи того, що ви читаєте, показано тут + Результати пошуку + Введіть пароль + Звук сповіщень + Світлодіодний індикатор + Учора + Справа наліво (←) + Створити резервну копію + Відновити з резервної копії + Всі дані були відновлені + Групувати + Сьогодні + Без звуку + Давно + Очистити всю історію оновлень назавжди\? + Деякі пристрої мають різну поведінку системи, що може порушити фонові завдання. + Видалити всі останні пошукові запити назавжди\? + Доступні джерела + Блок на NSFW + Завжди блокувати + Пропозиції + Увімкнути пропозиції + Не пропонувати NSFW манґу + Не вдалося завантажити список жанрів + Ніколи + Зовнішній вигляд + Виключити жанри + Укажіть жанри, які ви не хочете бачити в пропозиціях + Допомагає уникнути блокування вашої IP-адреси + Розділи буде видалено у фоновому режимі + Перевіряти наявність нових розділів і повідомляти про них + Ви будете отримувати повідомлення про оновлення манґи, яку ви читаєте + Увімкнути сповіщення + Ви не будете отримувати повідомлення, але нові розділи будуть відображатися у списку + Немає улюблених категорій + Назва + Змінити + Змінити категорію + Додати закладку + Видалити закладку + Закладки + Закладка видалена + Додано закладку + Відмінити + Видалено з історії + DNS через HTTPS + Режим за замовчуванням + Автоматично визначати, чи є манґа вебтуном + Автовизначення режиму читання + Вимкнути оптимізацію акумулятора + Допомагає з перевірками фонових оновлень + Щось пішло не так. Будь ласка, надішліть звіт про помилку розробникам, щоб допомогти нам її виправити. + Надіслати + Вимкнути все + Використовувати відбиток пальця, якщо доступно + Манга з Вашого улюбленого + Манга, яку Ви нещодавно читали + Недійсний домен + Звіт + Відстеження + Вийти + Заплановано + Читаю + Перечитую + Завершено + Відкладено + Занедбано + Показувати індикатори прогресу читання + Видалення даних + Показати відсоток прочитаного в історії та обраному + Манґа, позначена як NSFW, ніколи не буде додана до історії і ваш прогрес не буде збережений + Може допомогти в разі виникнення проблем. Усі авторизації будуть анульовані + Показати всі + Виберіть діапазон + Вміст не знайдено або видалено + Ваша манга буде відображатися тут + Знайдіть, що почитати у розділі «Огляд» + Назад + Введіть свою електронну пошту, щоб продовжити + Історія очищена + Керувати + Закладок ще немає + Ви можете створювати закладки під час читання манґи + Закладки видалено + Немає джерел манґи + Увімкніть джерела манґи, щоб читати онлайн + Випадкова + Ви впевнені, що бажаєте видалити вибрані улюблені категорії\? \nУсю манґу в них буде втрачено, і це неможливо скасувати. - Впорядкувати - Порожньо - Огляд - Збережена манґа - Кеш сторінок - Використання сховища - Доступні - Параметри - Режим інкогніто - Немає розділів - Автоматична прокрутка - Показувати інформаційну панель у режимі читання - Архів коміксів - Папка із зображеннями - Імпорт манґи - Імпорт завершено - Ви можете видалити оригінальний файл зі сховища, щоб заощадити місце - Імпорт почнеться незабаром - Стрічка - Розд. %1$d/%2$d Стор. %3$d/%4$d - Обліковий запис уже існує - Синхронізуйте ваші дані - Скасовано - Натисніть Назад ще раз, щоб вийти - Синхронізація - Очистити всю історію - Останні 2 години - Двічі натисніть Назад, щоб вийти зі застосунку - Підтвердження виходу - Видалено з уподобань - Інший кеш - %s - %s - Деталі помилки:<br><tt>%1$s</tt><br><br>1. Спробуйте <a href=%2$s>відкрити мангу у веб-браузері</a>, щоб переконатися, що вона доступна в джерелі<br>2. Переконайтеся, що ви використовуєте <a href=kotatsu://about>останню версію Kotatsu</a><br>3. Якщо він доступний, надішліть звіт про помилку розробникам. - Показувати ярлики останньої прочитаної манґи - Зробити нещодавно прочитану манґу доступною за довгим натисканням на іконку застосунку - Натискання на правий край або натискання правої клавіші завжди переходить на наступну сторінку - Ергономічне керування режимом читання - Яскравість - Корекція кольору - Контрастність - Скинути - Вибрані параметри кольору будуть запам\'ятовані для цієї манґи - Зберегти чи скасувати незбережені зміни\? - Скасувати - Помилка на стороні сервера (%1$d). Будь ласка спробуйте пізніше - Також очистити інформацію про нові розділи - На пристрої не залишилося вільного місця - Різні мови - Мережа недоступна - Увімкніть Wi-Fi або мобільну мережу, щоб читати манґу онлайн - Масштабування в режимі вебтуну - Відображати повзунок перемикання сторінок - Компактно - Передвчасне завантаження контенту - Джерело відключено - Позначити як актуальне - Мова - Канаде - Служби - Тут нічого нема - Щоб відстежувати прогрес читання, виберіть Меню → Відстежити на екрані деталей манги. - Міку - Аска - Міон - Рікка - Сакура - Поділиться логами - Увімкнути логування - Записувати деякі дії з метою подальшого налагодження - Мамімі - Показувати сумнівний контент - Динамічний - Колірний акцент - Показати у вигляді сітки - Дозволити нестабільні оновлення - Пропонувати оновлення до бета-версій додатку - Завантаження розпочато - Заголовок UserAgent - Перезапустіть програму, щоб застосувати зміни - Зрозумів - Ви можете вибрати один або кілька файлів .cbz або .zip, кожен файл буде розпізнано як окрема манга. - Ви можете вибрати каталог з архівами або зображеннями. Кожен архів (або підкаталог) буде розпізнано як розділ. - Швидкість - Імпортуйте раніше створену резервну копію даних користувача - Показати на полиці - Натисніть і утримуйте елемент, щоб змінити його порядок - Ви можете увійти в існуючий аккаунт, або створити новий - Знайти схожі - Параметри синхронізації - Адреса сервера - Ви можете використовувати власний сервер синхронізації або сервер за замовчуванням. Не змінюйте це, якщо ви не впевнені, що робите. - Ігноруйте помилки SSL - Виберіть дзеркало автоматично - Призупинено - Видалити завершені - Завантажувати тільки через Wi-Fi - Скасувати все - Автоматично перемикайте домени для віддалених джерел у разі помилок, якщо дзеркала доступні - Відновити - Пауза - Зупинити завантаження при переході на мобільну мережу - Увімкнути - Ні, дякую - Пропозиція: %s - Іноді показувати сповіщення з запропонованою мангою - Більше - Усі активні завантаження буде скасовано, частково завантажені дані буде втрачено - Ваша історія завантажень буде остаточно видалена - У вас немає завантажень - Завантаження відновлено - Завантаження призупинено - Завантаження видалено - Завантаження скасовано - Хочете отримувати персоналізовані пропозиції щодо манги\? - WebView недоступний: перевірте, чи встановлено провайдер WebView - Переклади - Очистити мережевий кеш - Порт - Проксі - Тип - Адреса - %1$s (%2$s) - Недійсне значення - \ No newline at end of file + Впорядкувати + Порожньо + Огляд + Збережена манґа + Кеш сторінок + Використання сховища + Доступні + Параметри + Режим інкогніто + Немає розділів + Автоматична прокрутка + Показувати інформаційну панель у режимі читання + Архів коміксів + Папка із зображеннями + Імпорт манґи + Імпорт завершено + Ви можете видалити оригінальний файл зі сховища, щоб заощадити місце + Імпорт почнеться незабаром + Стрічка + Розд. %1$d/%2$d Стор. %3$d/%4$d + Обліковий запис уже існує + Синхронізуйте ваші дані + Скасовано + Натисніть Назад ще раз, щоб вийти + Синхронізація + Очистити всю історію + Останні 2 години + Двічі натисніть Назад, щоб вийти зі застосунку + Підтвердження виходу + Видалено з уподобань + Інший кеш + %s - %s + Деталі помилки:<br><tt>%1$s</tt><br><br>1. Спробуйте <a href=%2$s>відкрити мангу у веб-браузері</a>, щоб переконатися, що вона доступна в джерелі<br>2. Переконайтеся, що ви використовуєте <a href=kotatsu://about>останню версію Kotatsu</a><br>3. Якщо він доступний, надішліть звіт про помилку розробникам. + Показувати ярлики останньої прочитаної манґи + Зробити нещодавно прочитану манґу доступною за довгим натисканням на іконку застосунку + Натискання на правий край або натискання правої клавіші завжди переходить на наступну сторінку + Ергономічне керування режимом читання + Яскравість + Корекція кольору + Контрастність + Скинути + Вибрані параметри кольору будуть запам\'ятовані для цієї манґи + Зберегти чи скасувати незбережені зміни\? + Скасувати + Помилка на стороні сервера (%1$d). Будь ласка спробуйте пізніше + Також очистити інформацію про нові розділи + На пристрої не залишилося вільного місця + Різні мови + Мережа недоступна + Увімкніть Wi-Fi або мобільну мережу, щоб читати манґу онлайн + Масштабування в режимі вебтуну + Відображати повзунок перемикання сторінок + Компактно + Передвчасне завантаження контенту + Джерело відключено + Позначити як актуальне + Мова + Канаде + Служби + Тут нічого нема + Щоб відстежувати прогрес читання, виберіть Меню → Відстежити на екрані деталей манги. + Міку + Аска + Міон + Рікка + Сакура + Поділиться логами + Увімкнути логування + Записувати деякі дії з метою подальшого налагодження + Мамімі + Показувати сумнівний контент + Динамічний + Колірний акцент + Показати у вигляді сітки + Дозволити нестабільні оновлення + Пропонувати оновлення до бета-версій додатку + Завантаження розпочато + Заголовок UserAgent + Перезапустіть програму, щоб застосувати зміни + Зрозумів + Ви можете вибрати один або кілька файлів .cbz або .zip, кожен файл буде розпізнано як окрема манга. + Ви можете вибрати каталог з архівами або зображеннями. Кожен архів (або підкаталог) буде розпізнано як розділ. + Швидкість + Імпортуйте раніше створену резервну копію даних користувача + Показати на полиці + Натисніть і утримуйте елемент, щоб змінити його порядок + Ви можете увійти в існуючий аккаунт, або створити новий + Знайти схожі + Параметри синхронізації + Адреса сервера + Ви можете використовувати власний сервер синхронізації або сервер за замовчуванням. Не змінюйте це, якщо ви не впевнені, що робите. + Ігноруйте помилки SSL + Виберіть дзеркало автоматично + Призупинено + Видалити завершені + Завантажувати тільки через Wi-Fi + Скасувати все + Автоматично перемикайте домени для віддалених джерел у разі помилок, якщо дзеркала доступні + Відновити + Пауза + Зупинити завантаження при переході на мобільну мережу + Увімкнути + Ні, дякую + Пропозиція: %s + Іноді показувати сповіщення з запропонованою мангою + Більше + Усі активні завантаження буде скасовано, частково завантажені дані буде втрачено + Ваша історія завантажень буде остаточно видалена + У вас немає завантажень + Завантаження відновлено + Завантаження призупинено + Завантаження видалено + Завантаження скасовано + Хочете отримувати персоналізовані пропозиції щодо манги\? + WebView недоступний: перевірте, чи встановлено провайдер WebView + Переклади + Очистити мережевий кеш + Порт + Проксі + Тип + Адреса + %1$s (%2$s) + Недійсне значення + diff --git a/app/src/main/res/values-vi/plurals.xml b/app/src/main/res/values-vi/plurals.xml index c2879a4fd..7b7bf3a2b 100644 --- a/app/src/main/res/values-vi/plurals.xml +++ b/app/src/main/res/values-vi/plurals.xml @@ -15,7 +15,4 @@ %1$d ngày trước - - Tổng %1$d trang - diff --git a/app/src/main/res/values-zh-rCN/plurals.xml b/app/src/main/res/values-zh-rCN/plurals.xml index a7acbeee9..dbab8c693 100644 --- a/app/src/main/res/values-zh-rCN/plurals.xml +++ b/app/src/main/res/values-zh-rCN/plurals.xml @@ -18,7 +18,4 @@ %1$d 天前 - - 共 %1$d 页 - diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 6ca5165d3..96957ff20 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,420 +1,416 @@ - 设置 - 本地存储 - 喜欢 - 历史 - 发生了一个错误 - 网络错误 - 章节 - 列表 - 数据被恢复了,但有错误 - 正在处理… - 最新 - 评分 - 已删除所有 cookie - 所有数据都被恢复了 - 无声 - 准备… - 未找到文件 - 昨日 - 你可以创建你的历史和收藏的备份并恢复它 - 现在 - 很久以前 - - 轻点以重试 - 所选择的配置将因这部漫画而被记住 - 需要验证码 - 解决 - 今天 - 清除cookies - 有新的漫画源可用 - 根据你的喜好推荐漫画 - 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 - 从不 - 你会收到你正在阅读的漫画的更新通知 - 18+ - 各种语言 - 查找章节 - 排除流派 - 建议更新 - 检查新的章节并通知有关情况 - 详细内容 - 详细列表 - 网格 - 列表模式 - 漫画源 - 加载中… - 计算中… - %1$d/%2$d章节 - 关闭 - 再试一次 - 清除历史 - 没有发现 - 尚无历史 - 阅读 - 尚无收藏夹 - 收藏此漫画 - 新分类 - 添加 - 保存 - 分享 - 创建快捷方式… - 分享%s - 搜索 - 搜索漫画 - 正在下载… - 已下载 - 下载 - 名称 - 热门 - 更新 - 排序顺序 - 过滤器 - 主题 - 深色 - 浅色 - 跟随系统 - 页数 - 清除 - 永久清除所有阅读历史\? - 删除 - \"%s\"从本地存储中删除 - 保存页面 - 保存 - 分享图片 - 导入 - 删除 - 不支持此操作 - 选择 ZIP 或 CBZ 文件. - 无描述 - 历史和缓存 - 清除页面缓存 - B|kB|MB|GB|TB - 标准 - 条漫 - 阅读模式 - 网格大小 - 在%s上搜索 - 删除漫画 - 从设备中永久删除\"%s\"\? - 阅读器设置 - 切换页面 - 音量按钮 - 继续 - 边缘点击 - 错误 - 清除缩略图缓存 - 清除搜索历史 - 清除 - 仅限手势 - 内部存储 - 外部存储 - 范围 - 新版本应用程序已经推出 - 在网络浏览器中打开 - 这部漫画有%s.全部保存\? - 保存 - 通知 - 新章节 - 下载 - 通知设置 - 通知声音 - LED指示器 - 振动 - 收藏夹分类 - 删除 - 这里有点空… - 尝试重新表述查询。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容. - 先保存内容 - 从在线来源保存或导入文件. - 书架 - 最近 - 页面动画 - 下载文件夹 - 不详 - 没有可用的存储空间 - 其他存储 - 完成 - 所有收藏夹 - 空分类 - 稍后阅读 - 更新 - 你正在阅读的新章节显示在这里 - 搜索结果 - 新版本: %s - 清除更新源 - 已清除 - 旋转屏幕 - 更新 - 源更新即将开始 - 查找更新 - 不要检查 - 输入密码 - 密码错误 - 保护应用程序 - 在启动Kotatsu时要求输入密码 - 重复密码 - 密码不匹配 - 关于 - 版本%s - 检查更新 - 没有更新 - 从右到左 - 新分类 - 缩放模式 - 适应中心 - 适应高度 - 适应宽度 - 从头开始 - 黑色 - 在AMOLED屏幕上使用更少电池 - 备份和还原 - 创建数据备份 - 从备份中恢复 - 恢复 - 清除文件 - 永久地清除所有的更新历史? - 检查新的章节 - 撤销 - 登录 - 登录后可查看此内容 - 默认值: %s - 下一页 - 输入密码以启动应用程序 - 确认 - 密码必须是4个字符或以上 - 永久地删除所有最近的搜索查询? - 欢迎 - 保存备份 - 一些设备有不同的系统行为, 这可能会破坏后台任务. - 阅读更多 - 排队 - 下载或在线阅读这缺失的章节. - 该章缺失 - 翻译此应用程序 - 翻译 - 授权 - 不支持在%s上登录 - 你将退出登录所有来源 - 类型 - 连载中 - 已完结 - 默认 - 将NSFW漫画排除在历史之外 - 页数 - 使用图源 - 现有图源 - 屏幕截图 - 允许 - 禁止18+ - 始终阻止 - 建议 - 启用建议 - 开始阅读漫画,你会得到个性化的建议 - 请勿推荐18+漫画 - 启用 - 禁用 - 无法加载流派列表 - 重置过滤器 - 查找流派 - 选择你想看的漫画的语言. 你可以在以后的设置中改变它. - 只在Wi-Fi上使用 - 总是 - 预加载页面 - 以%s身份登录 - 这部漫画中没有章节 - 外观 - 内容 - 指定您不希望在建议中看到的类型 - 从设备中永久删除所选项目\? - 删除已完成 - 下载速度减慢 - 有助于避免阻断你的IP地址 - 保存的漫画处理 - 章节将在后台被删除 - 隐藏 - 你将不会收到通知但新的章节将在列表中突出显示 - 启用通知 - 命名 - 编辑 - 编辑分类 - 没有收藏夹分类 - 添加书签 - 删除书签 - 书签 - 删除书签 - 添加书签 - 撤销 - 从历史中删除 - DNS over HTTPS - 默认模式 - 自动检测阅读器模式 - 自动检测漫画是否为条漫 - 禁用电池优化 - 帮助进行背景更新检查 - 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. - 发送 - 全部禁用 - 计划 - 暂停 - 报告 - 追踪 - 注销 - 阅读 - 重读 - 完成 - 使用指纹 - 你喜欢的漫画 - 您最近阅读的漫画 - 在历史和收藏夹中显示阅读百分比 - 显示阅读进度指标 - 数据删除 - 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 - 可以在出现一些问题时提供帮助. 所有授权将被视为无效 - 显示全部 - 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 - 无效域名 - 此处将显示你的漫画 - 在【浏览】页面搜索想要阅读的漫画 - %1$s%% - 已取消 - 账号已存在 - 返回 - 同步 - 同步您的数据 - 输入您的邮箱以继续 - 已放弃 - 选择范围 - 清除所有历史 - 过去2小时 - 书签已移除 - 历史已清除 - 管理 - 还没有书签 - 您可以在阅读漫画时创建书签 - 无漫画源 - 启用漫画源以在线阅读漫画 - 随机 - 您确定要删除选定的收藏夹吗? + 设置 + 本地存储 + 喜欢 + 历史 + 发生了一个错误 + 网络错误 + 章节 + 列表 + 数据被恢复了,但有错误 + 正在处理… + 最新 + 评分 + 已删除所有 cookie + 所有数据都被恢复了 + 无声 + 准备… + 未找到文件 + 昨日 + 你可以创建你的历史和收藏的备份并恢复它 + 现在 + 很久以前 + + 轻点以重试 + 所选择的配置将因这部漫画而被记住 + 需要验证码 + 解决 + 今天 + 清除cookies + 有新的漫画源可用 + 根据你的喜好推荐漫画 + 所有的数据都在这个设备上进行本地分析,不会发送到任何地方。 + 从不 + 你会收到你正在阅读的漫画的更新通知 + 18+ + 各种语言 + 查找章节 + 排除流派 + 建议更新 + 检查新的章节并通知有关情况 + 详细内容 + 详细列表 + 网格 + 列表模式 + 漫画源 + 加载中… + 计算中… + %1$d/%2$d章节 + 关闭 + 再试一次 + 清除历史 + 没有发现 + 尚无历史 + 阅读 + 尚无收藏夹 + 收藏此漫画 + 新分类 + 添加 + 保存 + 分享 + 创建快捷方式… + 分享%s + 搜索 + 搜索漫画 + 正在下载… + 已下载 + 下载 + 名称 + 热门 + 更新 + 排序顺序 + 过滤器 + 主题 + 深色 + 浅色 + 跟随系统 + 页数 + 清除 + 永久清除所有阅读历史\? + 删除 + \"%s\"从本地存储中删除 + 保存页面 + 保存 + 分享图片 + 导入 + 删除 + 不支持此操作 + 选择 ZIP 或 CBZ 文件. + 无描述 + 清除页面缓存 + B|kB|MB|GB|TB + 标准 + 条漫 + 阅读模式 + 网格大小 + 在%s上搜索 + 删除漫画 + 从设备中永久删除\"%s\"\? + 阅读器设置 + 切换页面 + 音量按钮 + 继续 + 边缘点击 + 错误 + 清除缩略图缓存 + 清除搜索历史 + 清除 + 仅限手势 + 内部存储 + 外部存储 + 范围 + 新版本应用程序已经推出 + 在网络浏览器中打开 + 这部漫画有%s.全部保存\? + 保存 + 通知 + 新章节 + 下载 + 通知设置 + 通知声音 + LED指示器 + 振动 + 收藏夹分类 + 删除 + 这里有点空… + 尝试重新表述查询。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容. + 先保存内容 + 从在线来源保存或导入文件. + 书架 + 最近 + 页面动画 + 下载文件夹 + 不详 + 没有可用的存储空间 + 其他存储 + 完成 + 所有收藏夹 + 空分类 + 稍后阅读 + 更新 + 你正在阅读的新章节显示在这里 + 搜索结果 + 新版本: %s + 清除更新源 + 已清除 + 旋转屏幕 + 更新 + 源更新即将开始 + 查找更新 + 不要检查 + 输入密码 + 密码错误 + 保护应用程序 + 在启动Kotatsu时要求输入密码 + 重复密码 + 密码不匹配 + 关于 + 版本%s + 检查更新 + 没有更新 + 从右到左 + 新分类 + 缩放模式 + 适应中心 + 适应高度 + 适应宽度 + 从头开始 + 黑色 + 在AMOLED屏幕上使用更少电池 + 备份和还原 + 创建数据备份 + 从备份中恢复 + 恢复 + 清除文件 + 永久地清除所有的更新历史? + 检查新的章节 + 撤销 + 登录 + 登录后可查看此内容 + 默认值: %s + 下一页 + 输入密码以启动应用程序 + 确认 + 密码必须是4个字符或以上 + 永久地删除所有最近的搜索查询? + 欢迎 + 保存备份 + 一些设备有不同的系统行为, 这可能会破坏后台任务. + 阅读更多 + 排队 + 该章缺失 + 翻译此应用程序 + 翻译 + 授权 + 不支持在%s上登录 + 你将退出登录所有来源 + 类型 + 连载中 + 已完结 + 默认 + 将NSFW漫画排除在历史之外 + 页数 + 使用图源 + 现有图源 + 屏幕截图 + 允许 + 禁止18+ + 始终阻止 + 建议 + 启用建议 + 开始阅读漫画,你会得到个性化的建议 + 请勿推荐18+漫画 + 启用 + 禁用 + 无法加载流派列表 + 重置过滤器 + 选择你想看的漫画的语言. 你可以在以后的设置中改变它. + 只在Wi-Fi上使用 + 总是 + 预加载页面 + 以%s身份登录 + 这部漫画中没有章节 + 外观 + 指定您不希望在建议中看到的类型 + 从设备中永久删除所选项目\? + 删除已完成 + 下载速度减慢 + 有助于避免阻断你的IP地址 + 保存的漫画处理 + 章节将在后台被删除 + 隐藏 + 你将不会收到通知但新的章节将在列表中突出显示 + 启用通知 + 命名 + 编辑 + 编辑分类 + 没有收藏夹分类 + 添加书签 + 删除书签 + 书签 + 删除书签 + 添加书签 + 撤销 + 从历史中删除 + DNS over HTTPS + 默认模式 + 自动检测阅读器模式 + 自动检测漫画是否为条漫 + 禁用电池优化 + 帮助进行背景更新检查 + 出了点问题. 请向开发人员提交一份错误报告以帮助我们修复它. + 发送 + 全部禁用 + 计划 + 暂停 + 报告 + 追踪 + 注销 + 阅读 + 重读 + 完成 + 使用指纹 + 你喜欢的漫画 + 您最近阅读的漫画 + 在历史和收藏夹中显示阅读百分比 + 显示阅读进度指标 + 数据删除 + 标记为NSFW的漫画将永远不会被添加到历史中你的进度也不会被保存 + 可以在出现一些问题时提供帮助. 所有授权将被视为无效 + 显示全部 + 错误详情:<br><tt>%1$s</tt><br><br>1.尝试<a href=%2$s>在网络浏览器中打开漫画</a>以确保在其来源中可用<br>2. 请确保您使用的是<a href=kotatsu://about>最新版本的Kotatsu</a><br>3.如果可用,请向开发人员发送错误报告。 + 无效域名 + 此处将显示你的漫画 + 在【浏览】页面搜索想要阅读的漫画 + %1$s%% + 已取消 + 账号已存在 + 返回 + 同步 + 同步您的数据 + 输入您的邮箱以继续 + 已放弃 + 选择范围 + 清除所有历史 + 过去2小时 + 书签已移除 + 历史已清除 + 管理 + 还没有书签 + 您可以在阅读漫画时创建书签 + 无漫画源 + 启用漫画源以在线阅读漫画 + 随机 + 您确定要删除选定的收藏夹吗? \n所有收藏夹中的漫画将丢失且无法恢复。 - 重新排序 - 留空 - 浏览 - 自动滚动 - 在阅读器中显示信息栏 - 漫画压缩包 - 图片文件夹 - 漫画导入中 - Ch. %1$d/%2$d Pg. %3$d/%4$d - %1$d 的 %2$d 启用 - 大小:%s - 再按一次返回键退出 - 按两次返回键退出应用 - 退出确认 - 已保存漫画 - 页面缓存 - 其他缓存 - 存储占用 - 可用 - 从收藏中移除 - 选项 - 隐身模式 - 无章节 - 导入完毕 - 您可以从存储中删除原文件以节省空间 - 即将开始导入 - 订阅源 - %s - %s - 内容未找到或已移除 - 点击屏幕右侧或按下右键翻到下一页 - 高效阅读器控制 - 长按应用图标显示最近阅读的漫画 - 显示最近阅读漫画的快捷方式 - 重置 - 颜色校正 - 亮度 - 对比度 - 所选颜色设置将会应用于此漫画 - 保存还是放弃未保存的更改? - 放弃 - 设备上没有剩余空间 - 显示换页滑块 - Webtoon 缩放 - 不同语言 - 网络不可用 - 打开 Wi-Fi 或移动网络在线阅读漫画 - 同样清除新章节信息 - 服务器端错误 (%1$d)。请稍后再试 - 紧凑 - 已禁用图源 - 内容预加载 - 标为当前 - 语言 - 启用日志记录 - 分享日志 - 出于调试目的记录某些操作 - 显示可疑内容 - 动态 - 颜色方案 - 用网格视图显示 - Miku - Asuka - Mion - Rikka - Sakura - 服务 - Mamimi - Kanade - 这里什么也没有 - 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 - 允许不稳定更新 - 提示更新到测试版 - 已开始下载 - UserAgent 标头 - 要应用这些更改请重启程序 - 点击并长按项目排序 - 知道了 - 速度 - 导入先前创建的用户数据备份 - 在书架上显示 - 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 - 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 - 寻找相似 - 翻译 - WebView不可用:检查是否已安装WebView - 你可以使用自建同步服务器或默认服务器。如果你不知道自己在干什么请不要修改此处。 - 自动选择镜像 - 如果存在可用镜像,在出错时自动切换域名 - 已暂停 - 切换到移动网络时停止下载 - 移除已完成 - 取消所有 - 仅通过Wi-Fi下载 - 启用 - 不,谢谢 - 同步设定 - 服务器地址 - 暂停 - 恢复 - 忽略SSL错误 - 没有下载项 - 下载已经恢复 - 暂停下载 - 下载已被移除 - 下载被取消 - 你想要接收个人漫画推荐吗? - 推荐:%s - 偶尔显示建议漫画通知 - 更多 - 所有进行中的下载都将被取消,未下载完成的数据将丢失 - 你的下载历史将会永久删除 - 你可以登陆一个已有账号或创建新账号 - 地址 - 清除网络缓存 - 代理 - 类型 - 无效值 - \ No newline at end of file + 重新排序 + 留空 + 浏览 + 自动滚动 + 在阅读器中显示信息栏 + 漫画压缩包 + 图片文件夹 + 漫画导入中 + Ch. %1$d/%2$d Pg. %3$d/%4$d + %1$d 的 %2$d 启用 + 大小:%s + 再按一次返回键退出 + 按两次返回键退出应用 + 退出确认 + 已保存漫画 + 页面缓存 + 其他缓存 + 存储占用 + 可用 + 从收藏中移除 + 选项 + 隐身模式 + 无章节 + 导入完毕 + 您可以从存储中删除原文件以节省空间 + 即将开始导入 + 订阅源 + %s - %s + 内容未找到或已移除 + 点击屏幕右侧或按下右键翻到下一页 + 高效阅读器控制 + 长按应用图标显示最近阅读的漫画 + 显示最近阅读漫画的快捷方式 + 重置 + 颜色校正 + 亮度 + 对比度 + 所选颜色设置将会应用于此漫画 + 保存还是放弃未保存的更改? + 放弃 + 设备上没有剩余空间 + 显示换页滑块 + Webtoon 缩放 + 不同语言 + 网络不可用 + 打开 Wi-Fi 或移动网络在线阅读漫画 + 同样清除新章节信息 + 服务器端错误 (%1$d)。请稍后再试 + 紧凑 + 已禁用图源 + 内容预加载 + 标为当前 + 语言 + 启用日志记录 + 分享日志 + 出于调试目的记录某些操作 + 显示可疑内容 + 动态 + 颜色方案 + 用网格视图显示 + Miku + Asuka + Mion + Rikka + Sakura + 服务 + Mamimi + Kanade + 这里什么也没有 + 要跟踪阅读进度,在漫画详情屏幕上选中“菜单→ 跟踪。 + 允许不稳定更新 + 提示更新到测试版 + 已开始下载 + UserAgent 标头 + 要应用这些更改请重启程序 + 点击并长按项目排序 + 知道了 + 速度 + 导入先前创建的用户数据备份 + 在书架上显示 + 您可以选择一个或多个cbz或zip文件,每个文件都将识别为一个单独的漫画。 + 您可以选择一个包含压缩包或图片的文件夹。每个压缩包(或子文件夹)都会被识别为一个章节。 + 寻找相似 + 翻译 + WebView不可用:检查是否已安装WebView + 你可以使用自建同步服务器或默认服务器。如果你不知道自己在干什么请不要修改此处。 + 自动选择镜像 + 如果存在可用镜像,在出错时自动切换域名 + 已暂停 + 切换到移动网络时停止下载 + 移除已完成 + 取消所有 + 仅通过Wi-Fi下载 + 启用 + 不,谢谢 + 同步设定 + 服务器地址 + 暂停 + 恢复 + 忽略SSL错误 + 没有下载项 + 下载已经恢复 + 暂停下载 + 下载已被移除 + 下载被取消 + 你想要接收个人漫画推荐吗? + 推荐:%s + 偶尔显示建议漫画通知 + 更多 + 所有进行中的下载都将被取消,未下载完成的数据将丢失 + 你的下载历史将会永久删除 + 你可以登陆一个已有账号或创建新账号 + 地址 + 清除网络缓存 + 代理 + 类型 + 无效值 + diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 830fe30b2..f0858f20f 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,104 +1,103 @@ - 你将不会收到通知,但新的章节将在列表中突出显示 - 计算… - 再试一次 - 尚无历史记录 - 不支持这种操作 - 在 \"探索 \"部分找到要读的内容 - 从在线来源保存或导入文件。 - 你所读的内容将在这里显示 - 在侧面菜单中找到要读的内容。 - 你的漫画将显示在这里 - 这里有点空… - 饲料更新将很快开始 - 所选择的配置将因这部漫画而被记住 - 数据被恢复了,但有错误 - 在AMOLED屏幕上使用更少的电力 - 登录后可查看此内容 - 永久地删除所有最近的搜索查询? - 永久地清除所有的更新历史? - 你将从所有来源中注销 - 從歷史中排除NSFW漫畫 - 开始阅读漫画,你会得到个性化的建议 - 根据你的喜好推荐漫画 - 指定您不希望在建议中看到的体裁 - 从设备中永久删除选定的项目? - 无法加载流派列表 - 章节将在后台被删除。这可能需要一些时间 - 检查新的章节并通知有关情况 - 有助于避免阻断你的IP地址 - 输入你的电子邮件以继续 - 有了新的漫画来源 - 自动检测漫画是否为网络漫画 - 在历史和收藏夹中显示阅读百分比 - 再次按 \"返回 \"键退出 - 本地存储 - 轻敲右边缘或按右键总是切换到下一页 - 你有未保存的修改,你想保存还是丢弃它们? - 您可以從儲存中刪除原始檔案以節省空間 - 最爱 - 章节 - 列表 - 栅格 - 设置 - 没有发现 - 选择你想看的漫画的语言。你可以在以后的设置中改变它。 - 可以在出现一些问题时提供帮助。所有授权将被视为无效 - 历史 - 发生了一个错误 - 无法连接到互联网 - 详情 - 第%1$d 。%2$d - 详细列表 - 列表模式 - 远程资源 - 正在加载… - 关闭 - 清除历史 - 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 - 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 - 你可以创建你的历史和收藏的备份并恢复它 - 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 - 所选择的颜色设置将被铭记在这部漫画中 - 要么选择ZIP或CBZ文件。 - 你可以在阅读漫画时创建书签 - 你会收到你正在阅读的漫画的更新通知 - 一些设备有不同的系统行为,这可能会破坏后台任务。 - 输入密码以启动应用程序 - 下载或在线阅读这缺失的章节。 - 在启动Kotatsu时要求输入密码 - 这部漫画中没有章节 - 你正在阅读的新章节显示在这里 - 通过长按应用程序图标来提供最近的漫画 - 这部漫画有%s 。全部保存? - 新版本的应用程序已经推出 - 密码必须是4个字符或以上 - 不支持在%s 上登录 - \"%s\" 从本地存储中删除 - 按两次 \"返回 \"键,退出应用程序 - 启用漫画来源,在线阅读漫画 - 永久清除所有阅读历史? - 从设备中永久删除 \"%s\"? - 尝试重新表述查询。 - 帮助进行背景更新检查 - 请勿推荐NSFW漫画 - 新类别 - 阅读 - 暂时没有喜欢的人 - 最喜欢这个 - 添加 - 存儲 - 分享 %s - 搜尋 - 下載中…… - 已下載 - 過濾器 - 主題 - 淺色 - 清除 - 刪除 - 分享圖片 - 刪除 - 清除頁面快取 - \ No newline at end of file + 你将不会收到通知,但新的章节将在列表中突出显示 + 计算… + 再试一次 + 尚无历史记录 + 不支持这种操作 + 在 \"探索 \"部分找到要读的内容 + 从在线来源保存或导入文件。 + 你所读的内容将在这里显示 + 在侧面菜单中找到要读的内容。 + 你的漫画将显示在这里 + 这里有点空… + 饲料更新将很快开始 + 所选择的配置将因这部漫画而被记住 + 数据被恢复了,但有错误 + 在AMOLED屏幕上使用更少的电力 + 登录后可查看此内容 + 永久地删除所有最近的搜索查询? + 永久地清除所有的更新历史? + 你将从所有来源中注销 + 從歷史中排除NSFW漫畫 + 开始阅读漫画,你会得到个性化的建议 + 根据你的喜好推荐漫画 + 指定您不希望在建议中看到的体裁 + 从设备中永久删除选定的项目? + 无法加载流派列表 + 章节将在后台被删除。这可能需要一些时间 + 检查新的章节并通知有关情况 + 有助于避免阻断你的IP地址 + 输入你的电子邮件以继续 + 有了新的漫画来源 + 自动检测漫画是否为网络漫画 + 在历史和收藏夹中显示阅读百分比 + 再次按 \"返回 \"键退出 + 本地存储 + 轻敲右边缘或按右键总是切换到下一页 + 你有未保存的修改,你想保存还是丢弃它们? + 您可以從儲存中刪除原始檔案以節省空間 + 最爱 + 章节 + 列表 + 栅格 + 设置 + 没有发现 + 选择你想看的漫画的语言。你可以在以后的设置中改变它。 + 可以在出现一些问题时提供帮助。所有授权将被视为无效 + 历史 + 发生了一个错误 + 无法连接到互联网 + 详情 + 第%1$d 。%2$d + 详细列表 + 列表模式 + 远程资源 + 正在加载… + 关闭 + 清除历史 + 所有的数据都在这个设备上进行本地分析。您的个人数据不会被转移到任何服务机构。 + 标记为NSFW的漫画将永远不会被添加到历史中,你的进度也不会被保存 + 你可以创建你的历史和收藏的备份并恢复它 + 出了点问题。请向开发人员提交一份错误报告,以帮助我们修复它。 + 所选择的颜色设置将被铭记在这部漫画中 + 要么选择ZIP或CBZ文件。 + 你可以在阅读漫画时创建书签 + 你会收到你正在阅读的漫画的更新通知 + 一些设备有不同的系统行为,这可能会破坏后台任务。 + 输入密码以启动应用程序 + 在启动Kotatsu时要求输入密码 + 这部漫画中没有章节 + 你正在阅读的新章节显示在这里 + 通过长按应用程序图标来提供最近的漫画 + 这部漫画有%s 。全部保存? + 新版本的应用程序已经推出 + 密码必须是4个字符或以上 + 不支持在%s 上登录 + \"%s\" 从本地存储中删除 + 按两次 \"返回 \"键,退出应用程序 + 启用漫画来源,在线阅读漫画 + 永久清除所有阅读历史? + 从设备中永久删除 \"%s\"? + 尝试重新表述查询。 + 帮助进行背景更新检查 + 请勿推荐NSFW漫画 + 新类别 + 阅读 + 暂时没有喜欢的人 + 最喜欢这个 + 添加 + 存儲 + 分享 %s + 搜尋 + 下載中…… + 已下載 + 過濾器 + 主題 + 淺色 + 清除 + 刪除 + 分享圖片 + 刪除 + 清除頁面快取 + diff --git a/app/src/main/res/values/plurals.xml b/app/src/main/res/values/plurals.xml index a70ca5e6a..5c87de9f0 100644 --- a/app/src/main/res/values/plurals.xml +++ b/app/src/main/res/values/plurals.xml @@ -1,9 +1,5 @@ - - Total %1$d page - Total %1$d pages - %1$d item %1$d items diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bd61d47ac..a110477a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,7 +62,6 @@ This operation is not supported Either pick a ZIP or CBZ file. No description - History and cache Clear page cache B|kB|MB|GB|TB Standard @@ -187,7 +186,6 @@ Some devices have different system behavior, which may break background tasks. Read more Queued - Download or read this missing chapter online. The chapter is missing Translate this app Translation @@ -216,7 +214,6 @@ Disabled Unable to load genres list Reset filter - Find genre Select languages which you want to read manga. You can change it later in settings. Never Only on Wi-Fi @@ -229,7 +226,6 @@ No chapters in this manga %1$s%% Appearance - Content Suggestions updating Exclude genres Specify genres that you do not want to see in the suggestions diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index df869a46e..d73894979 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -2,10 +2,6 @@ - - -