Compare commits

...

20 Commits

Author SHA1 Message Date
Koitharu
fc2820ec11 Update version to v3.3 2022-05-20 19:12:58 +03:00
Zakhar Timoshenko
312fb033e0 Fix weird toolbar in category edit activity 2022-05-20 18:40:53 +03:00
Koitharu
18bc4dc739 Merge branch 'devel' of github.com:nv95/Kotatsu into devel 2022-05-20 12:16:22 +03:00
Artem
2b61b27271 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (297 of 297 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (8 of 8 strings)

Co-authored-by: Artem <artem@molotov.work>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/plurals/uk/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/
Translation: Kotatsu/Strings
Translation: Kotatsu/plurals
2022-05-20 12:15:03 +03:00
Koitharu
58c9f75b91 Fix tags order in filter 2022-05-20 12:14:23 +03:00
Koitharu
790f1fb8a3 Update parsers 2022-05-20 12:06:26 +03:00
Zakhar Timoshenko
5c4f3f7fe4 Revert onCreateDialog method
This thing is really needed
2022-05-18 23:35:58 +03:00
Zakhar Timoshenko
86ead09080 Revert accidentally removed style 2022-05-18 22:20:54 +03:00
Zakhar Timoshenko
0932507346 Bottom sheet improvements 2022-05-18 22:14:14 +03:00
Koitharu
21f7b7120a Use collator for tags sorting 2022-05-18 11:27:07 +03:00
Koitharu
473135bfc5 Apply theme changing without restarting 2022-05-17 16:26:04 +03:00
Koitharu
ce7960e5e9 Recreate all activities on theme changed 2022-05-17 13:23:03 +03:00
Koitharu
17c440ee43 Fix marking sources as new 2022-05-17 11:31:06 +03:00
Koitharu
5d881ca154 New global search activity 2022-05-17 11:19:55 +03:00
Koitharu
e4b29b3ff9 Cleanup strings 2022-05-15 17:11:40 +03:00
Luiz-bro
046aaa0649 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (297 of 297 strings)

Co-authored-by: Luiz-bro <luiznneto1@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/pt_BR/
Translation: Kotatsu/Strings
2022-05-15 17:04:21 +03:00
Dpper
f653c74ce8 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (284 of 284 strings)

Co-authored-by: Dpper <ruslan20020401@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/uk/
Translation: Kotatsu/Strings
2022-05-15 17:04:21 +03:00
kuragehime
0c73c55b9d Translated using Weblate (Japanese)
Currently translated at 100.0% (297 of 297 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (287 of 287 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (284 of 284 strings)

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

Translated using Weblate (Turkish)

Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (284 of 284 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/tr/
Translation: Kotatsu/Strings
2022-05-15 17:04:21 +03:00
J. Lavoie
859ae966c8 Translated using Weblate (Finnish)
Currently translated at 99.6% (296 of 297 strings)

Translated using Weblate (French)

Currently translated at 100.0% (297 of 297 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (297 of 297 strings)

Translated using Weblate (German)

Currently translated at 100.0% (297 of 297 strings)

Translated using Weblate (Finnish)

Currently translated at 99.6% (294 of 295 strings)

Translated using Weblate (French)

Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (German)

Currently translated at 100.0% (295 of 295 strings)

Translated using Weblate (Finnish)

Currently translated at 99.6% (287 of 288 strings)

Translated using Weblate (French)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (German)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (French)

Currently translated at 100.0% (284 of 284 strings)

Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/de/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fi/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/fr/
Translate-URL: https://hosted.weblate.org/projects/kotatsu/strings/it/
Translation: Kotatsu/Strings
2022-05-15 17:04:21 +03:00
77 changed files with 929 additions and 329 deletions

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@
/.idea/dictionaries /.idea/dictionaries
/.idea/modules.xml /.idea/modules.xml
/.idea/misc.xml /.idea/misc.xml
/.idea/discord.xml
/.idea/workspace.xml /.idea/workspace.xml
/.idea/navEditor.xml /.idea/navEditor.xml
/.idea/assetWizardSettings.xml /.idea/assetWizardSettings.xml

View File

@@ -14,8 +14,8 @@ android {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 32 targetSdkVersion 32
versionCode 408 versionCode 409
versionName '3.3-beta1' versionName '3.3'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -66,7 +66,7 @@ android {
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation('com.github.nv95:kotatsu-parsers:05a93e2380') { implementation('com.github.nv95:kotatsu-parsers:f46c5add46') {
exclude group: 'org.json', module: 'json' exclude group: 'org.json', module: 'json'
} }
@@ -103,7 +103,7 @@ dependencies {
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2' implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation 'io.insert-koin:koin-android:3.2.0' implementation 'io.insert-koin:koin-android:3.2.0'
implementation 'io.coil-kt:coil-base:2.0.0' implementation 'io.coil-kt:coil-base:2.1.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0' implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.solkin:disk-lru-cache:1.4' implementation 'com.github.solkin:disk-lru-cache:1.4'

View File

@@ -88,6 +88,9 @@
<activity <activity
android:name="org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity" android:name="org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity"
android:label="@string/search" /> android:label="@string/search" />
<activity
android:name="org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity"
android:label="@string/search" />
<activity <activity
android:name="org.koitharu.kotatsu.main.ui.protect.ProtectActivity" android:name="org.koitharu.kotatsu.main.ui.protect.ProtectActivity"
android:noHistory="true" android:noHistory="true"

View File

@@ -7,6 +7,7 @@ import androidx.fragment.app.strictmode.FragmentStrictMode
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import org.koitharu.kotatsu.base.ui.util.ActivityRecreationHandle
import org.koitharu.kotatsu.bookmarks.bookmarksModule import org.koitharu.kotatsu.bookmarks.bookmarksModule
import org.koitharu.kotatsu.core.db.databaseModule import org.koitharu.kotatsu.core.db.databaseModule
import org.koitharu.kotatsu.core.github.githubModule import org.koitharu.kotatsu.core.github.githubModule
@@ -43,6 +44,7 @@ class KotatsuApp : Application() {
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext)) Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
AppCompatDelegate.setDefaultNightMode(get<AppSettings>().theme) AppCompatDelegate.setDefaultNightMode(get<AppSettings>().theme)
registerActivityLifecycleCallbacks(get<AppProtectHelper>()) registerActivityLifecycleCallbacks(get<AppProtectHelper>())
registerActivityLifecycleCallbacks(get<ActivityRecreationHandle>())
val widgetUpdater = WidgetUpdater(applicationContext) val widgetUpdater = WidgetUpdater(applicationContext)
widgetUpdater.subscribeToFavourites(get()) widgetUpdater.subscribeToFavourites(get())
widgetUpdater.subscribeToHistory(get()) widgetUpdater.subscribeToHistory(get())

View File

@@ -43,9 +43,13 @@ abstract class BaseActivity<B : ViewBinding> :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val settings = get<AppSettings>() val settings = get<AppSettings>()
val isAmoled = settings.isAmoledTheme
val isDynamic = settings.isDynamicTheme
// TODO support DialogWhenLarge theme
when { when {
settings.isAmoledTheme -> setTheme(R.style.ThemeOverlay_Kotatsu_AMOLED) isAmoled && isDynamic -> setTheme(R.style.Theme_Kotatsu_Monet_Amoled)
settings.isDynamicTheme -> setTheme(R.style.Theme_Kotatsu_Monet) isAmoled -> setTheme(R.style.Theme_Kotatsu_Amoled)
isDynamic -> setTheme(R.style.Theme_Kotatsu_Monet)
} }
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)

View File

@@ -2,11 +2,11 @@ package org.koitharu.kotatsu.base.ui
import android.app.Dialog import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams import android.view.ViewGroup.LayoutParams
import androidx.appcompat.app.AppCompatDialog
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
@@ -14,6 +14,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.dialog.AppBottomSheetDialog import org.koitharu.kotatsu.base.ui.dialog.AppBottomSheetDialog
import org.koitharu.kotatsu.utils.ext.displayCompat
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() { abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
@@ -33,6 +34,20 @@ abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
): View { ): View {
val binding = onInflateView(inflater, container) val binding = onInflateView(inflater, container)
viewBinding = binding viewBinding = binding
// Enforce max width for tablets
val width = resources.getDimensionPixelSize(R.dimen.bottom_sheet_width)
if (width > 0) {
behavior?.maxWidth = width
}
// Set peek height to 50% display height
requireContext().displayCompat?.let {
val metrics = DisplayMetrics()
it.getRealMetrics(metrics)
behavior?.peekHeight = metrics.heightPixels / 2
}
return binding.root return binding.root
} }
@@ -42,11 +57,7 @@ abstract class BaseBottomSheet<B : ViewBinding> : BottomSheetDialogFragment() {
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return if (resources.getBoolean(R.bool.is_tablet)) { return AppBottomSheetDialog(requireContext(), theme)
AppCompatDialog(context, R.style.Theme_Kotatsu_Dialog)
} else {
AppBottomSheetDialog(requireContext(), theme)
}
} }
protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B protected abstract fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): B

View File

@@ -21,7 +21,7 @@ class AppBottomSheetDialog(context: Context, theme: Int) : BottomSheetDialog(con
if (drawEdgeToEdge) { if (drawEdgeToEdge) {
// Copied from super.onAttachedToWindow: // Copied from super.onAttachedToWindow:
val edgeToEdgeFlags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE val edgeToEdgeFlags = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
// Fix super-class's window flag bug by respecting the intial system UI visibility: // Fix super-class's window flag bug by respecting the initial system UI visibility:
window.decorView.systemUiVisibility = edgeToEdgeFlags or initialSystemUiVisibility window.decorView.systemUiVisibility = edgeToEdgeFlags or initialSystemUiVisibility
} }
} }

View File

@@ -0,0 +1,34 @@
package org.koitharu.kotatsu.base.ui.util
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import java.util.*
class ActivityRecreationHandle : ActivityLifecycleCallbacks {
private val activities = WeakHashMap<Activity, Unit>()
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
activities[activity] = Unit
}
override fun onActivityStarted(activity: Activity) = Unit
override fun onActivityResumed(activity: Activity) = Unit
override fun onActivityPaused(activity: Activity) = Unit
override fun onActivityStopped(activity: Activity) = Unit
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
override fun onActivityDestroyed(activity: Activity) {
activities.remove(activity)
}
fun recreateAll() {
val snapshot = activities.keys.toList()
snapshot.forEach { it.recreate() }
}
}

View File

@@ -3,9 +3,9 @@ package org.koitharu.kotatsu.core.db.entity
import java.util.* import java.util.*
import org.koitharu.kotatsu.core.model.TrackingLogItem import org.koitharu.kotatsu.core.model.TrackingLogItem
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.longHashCode
import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.mapToSet
import org.koitharu.kotatsu.parsers.util.toTitleCase import org.koitharu.kotatsu.parsers.util.toTitleCase
import org.koitharu.kotatsu.utils.ext.longHashCode
// Entity to model // Entity to model

View File

@@ -4,7 +4,6 @@ import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.Uri import android.net.Uri
import android.os.Build
import android.provider.Settings import android.provider.Settings
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.arraySetOf import androidx.collection.arraySetOf
@@ -52,7 +51,7 @@ class AppSettings(context: Context) {
get() = prefs.getString(KEY_THEME, null)?.toIntOrNull() ?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM get() = prefs.getString(KEY_THEME, null)?.toIntOrNull() ?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
val isDynamicTheme: Boolean val isDynamicTheme: Boolean
get() = prefs.getBoolean(KEY_DYNAMIC_THEME, false) get() = DynamicColors.isDynamicColorAvailable() && prefs.getBoolean(KEY_DYNAMIC_THEME, false)
val isAmoledTheme: Boolean val isAmoledTheme: Boolean
get() = prefs.getBoolean(KEY_THEME_AMOLED, false) get() = prefs.getBoolean(KEY_THEME_AMOLED, false)
@@ -152,7 +151,7 @@ class AppSettings(context: Context) {
} }
fun markKnownSources(sources: Collection<MangaSource>) { fun markKnownSources(sources: Collection<MangaSource>) {
sourcesOrder = sourcesOrder + sources.map { it.name } sourcesOrder = (sourcesOrder + sources.map { it.name }).distinct()
} }
val isPagesNumbersEnabled: Boolean val isPagesNumbersEnabled: Boolean
@@ -324,12 +323,5 @@ class AppSettings(context: Context) {
private const val NETWORK_NEVER = 0 private const val NETWORK_NEVER = 0
private const val NETWORK_ALWAYS = 1 private const val NETWORK_ALWAYS = 1
private const val NETWORK_NON_METERED = 2 private const val NETWORK_NON_METERED = 2
val isDynamicColorAvailable: Boolean
get() = DynamicColors.isDynamicColorAvailable() ||
(isSamsung && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
private val isSamsung
get() = Build.MANUFACTURER.equals("samsung", ignoreCase = true)
} }
} }

View File

@@ -44,7 +44,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity import org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity
import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getDisplayMessage
@@ -208,7 +208,7 @@ class DetailsActivity :
} }
R.id.action_related -> { R.id.action_related -> {
viewModel.manga.value?.let { viewModel.manga.value?.let {
startActivity(GlobalSearchActivity.newIntent(this, it.title)) startActivity(MultiSearchActivity.newIntent(this, it.title))
} }
true true
} }

View File

@@ -6,10 +6,12 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf import org.koin.core.parameter.parametersOf
@@ -84,9 +86,9 @@ class FavouritesCategoryEditActivity : BaseActivity<ActivityCategoryEditBinding>
right = insets.right, right = insets.right,
bottom = insets.bottom, bottom = insets.bottom,
) )
binding.toolbar.updatePadding( binding.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
top = insets.top, topMargin = insets.top
) }
} }
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.list.ui.adapter package org.koitharu.kotatsu.list.ui.adapter
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader import coil.ImageLoader
import coil.request.Disposable import coil.request.Disposable
@@ -13,6 +14,7 @@ import org.koitharu.kotatsu.databinding.ItemMangaGridBinding
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaGridModel import org.koitharu.kotatsu.list.ui.model.MangaGridModel
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.search.ui.multi.adapter.ItemSizeResolver
import org.koitharu.kotatsu.utils.ext.enqueueWith import org.koitharu.kotatsu.utils.ext.enqueueWith
import org.koitharu.kotatsu.utils.ext.newImageRequest import org.koitharu.kotatsu.utils.ext.newImageRequest
import org.koitharu.kotatsu.utils.ext.referer import org.koitharu.kotatsu.utils.ext.referer
@@ -21,6 +23,7 @@ fun mangaGridItemAD(
coil: ImageLoader, coil: ImageLoader,
lifecycleOwner: LifecycleOwner, lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<Manga>, clickListener: OnListItemClickListener<Manga>,
sizeResolver: ItemSizeResolver?,
) = adapterDelegateViewBinding<MangaGridModel, ListModel, ItemMangaGridBinding>( ) = adapterDelegateViewBinding<MangaGridModel, ListModel, ItemMangaGridBinding>(
{ inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) } { inflater, parent -> ItemMangaGridBinding.inflate(inflater, parent, false) }
) { ) {
@@ -34,6 +37,11 @@ fun mangaGridItemAD(
itemView.setOnLongClickListener { itemView.setOnLongClickListener {
clickListener.onItemLongClick(item.manga, it) clickListener.onItemLongClick(item.manga, it)
} }
if (sizeResolver != null) {
itemView.updateLayoutParams {
width = sizeResolver.cellWidth
}
}
bind { bind {
binding.textViewTitle.text = item.title binding.textViewTitle.text = item.title

View File

@@ -18,7 +18,7 @@ class MangaListAdapter(
delegatesManager delegatesManager
.addDelegate(ITEM_TYPE_MANGA_LIST, mangaListItemAD(coil, lifecycleOwner, listener)) .addDelegate(ITEM_TYPE_MANGA_LIST, mangaListItemAD(coil, lifecycleOwner, listener))
.addDelegate(ITEM_TYPE_MANGA_LIST_DETAILED, mangaListDetailedItemAD(coil, lifecycleOwner, listener)) .addDelegate(ITEM_TYPE_MANGA_LIST_DETAILED, mangaListDetailedItemAD(coil, lifecycleOwner, listener))
.addDelegate(ITEM_TYPE_MANGA_GRID, mangaGridItemAD(coil, lifecycleOwner, listener)) .addDelegate(ITEM_TYPE_MANGA_GRID, mangaGridItemAD(coil, lifecycleOwner, listener, null))
.addDelegate(ITEM_TYPE_LOADING_FOOTER, loadingFooterAD()) .addDelegate(ITEM_TYPE_LOADING_FOOTER, loadingFooterAD())
.addDelegate(ITEM_TYPE_LOADING_STATE, loadingStateAD()) .addDelegate(ITEM_TYPE_LOADING_STATE, loadingStateAD())
.addDelegate(ITEM_TYPE_DATE, relatedDateItemAD()) .addDelegate(ITEM_TYPE_DATE, relatedDateItemAD())

View File

@@ -1,7 +1,7 @@
package org.koitharu.kotatsu.list.ui.filter package org.koitharu.kotatsu.list.ui.filter
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import java.util.* import androidx.lifecycle.LiveData
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -13,6 +13,8 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
import java.text.Collator
import java.util.*
class FilterCoordinator( class FilterCoordinator(
private val repository: RemoteMangaRepository, private val repository: RemoteMangaRepository,
@@ -27,7 +29,7 @@ class FilterCoordinator(
} }
private var availableTagsDeferred = loadTagsAsync() private var availableTagsDeferred = loadTagsAsync()
val items = getItemsFlow() val items: LiveData<List<FilterItem>> = getItemsFlow()
.asLiveDataDistinct(coroutineScope.coroutineContext + Dispatchers.Default) .asLiveDataDistinct(coroutineScope.coroutineContext + Dispatchers.Default)
init { init {
@@ -104,7 +106,7 @@ class FilterCoordinator(
query: String, query: String,
): List<FilterItem> { ): List<FilterItem> {
val sortOrders = repository.sortOrders.sortedBy { it.ordinal } val sortOrders = repository.sortOrders.sortedBy { it.ordinal }
val tags = mergeTags(state.tags, allTags.tags).sortedBy { it.title } val tags = mergeTags(state.tags, allTags.tags).toList()
val list = ArrayList<FilterItem>(tags.size + sortOrders.size + 3) val list = ArrayList<FilterItem>(tags.size + sortOrders.size + 3)
if (query.isEmpty()) { if (query.isEmpty()) {
if (sortOrders.isNotEmpty()) { if (sortOrders.isNotEmpty()) {
@@ -158,7 +160,7 @@ class FilterCoordinator(
} }
private fun mergeTags(primary: Set<MangaTag>, secondary: Set<MangaTag>): Set<MangaTag> { private fun mergeTags(primary: Set<MangaTag>, secondary: Set<MangaTag>): Set<MangaTag> {
val result = TreeSet(TagTitleComparator()) val result = TreeSet(TagTitleComparator(repository.source.locale))
result.addAll(secondary) result.addAll(secondary)
result.addAll(primary) result.addAll(primary)
return result return result
@@ -191,11 +193,14 @@ class FilterCoordinator(
} }
} }
private class TagTitleComparator : Comparator<MangaTag> { private class TagTitleComparator(lc: String?) : Comparator<MangaTag> {
override fun compare(o1: MangaTag, o2: MangaTag) = compareValues( private val collator = lc?.let { Collator.getInstance(Locale(it)) }
o1.title.lowercase(),
o2.title.lowercase(), override fun compare(o1: MangaTag, o2: MangaTag): Int {
) val t1 = o1.title.lowercase()
val t2 = o2.title.lowercase()
return collator?.compare(t1, t2) ?: compareValues(t1, t2)
}
} }
} }

View File

@@ -40,7 +40,7 @@ fun Manga.toGridModel(counter: Int) = MangaGridModel(
suspend fun List<Manga>.toUi( suspend fun List<Manga>.toUi(
mode: ListMode, mode: ListMode,
countersProvider: CountersProvider, countersProvider: CountersProvider,
): List<ListModel> = when (mode) { ): List<MangaItemModel> = when (mode) {
ListMode.LIST -> map { it.toListModel(countersProvider.getCounter(it.id)) } ListMode.LIST -> map { it.toListModel(countersProvider.getCounter(it.id)) }
ListMode.DETAILED_LIST -> map { it.toListDetailedModel(countersProvider.getCounter(it.id)) } ListMode.DETAILED_LIST -> map { it.toListDetailedModel(countersProvider.getCounter(it.id)) }
ListMode.GRID -> map { it.toGridModel(countersProvider.getCounter(it.id)) } ListMode.GRID -> map { it.toGridModel(countersProvider.getCounter(it.id)) }
@@ -58,7 +58,7 @@ suspend fun <C : MutableCollection<ListModel>> List<Manga>.toUi(
fun List<Manga>.toUi( fun List<Manga>.toUi(
mode: ListMode, mode: ListMode,
): List<ListModel> = when (mode) { ): List<MangaItemModel> = when (mode) {
ListMode.LIST -> map { it.toListModel(0) } ListMode.LIST -> map { it.toListModel(0) }
ListMode.DETAILED_LIST -> map { it.toListDetailedModel(0) } ListMode.DETAILED_LIST -> map { it.toListDetailedModel(0) }
ListMode.GRID -> map { it.toGridModel(0) } ListMode.GRID -> map { it.toGridModel(0) }

View File

@@ -2,13 +2,13 @@ package org.koitharu.kotatsu.local.data
import android.content.Context import android.content.Context
import com.tomclaw.cache.DiskLruCache import com.tomclaw.cache.DiskLruCache
import java.io.File
import java.io.InputStream
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import org.koitharu.kotatsu.parsers.util.longHashCode
import org.koitharu.kotatsu.utils.FileSize import org.koitharu.kotatsu.utils.FileSize
import org.koitharu.kotatsu.utils.ext.longHashCode
import org.koitharu.kotatsu.utils.ext.subdir import org.koitharu.kotatsu.utils.ext.subdir
import org.koitharu.kotatsu.utils.ext.takeIfReadable import org.koitharu.kotatsu.utils.ext.takeIfReadable
import java.io.File
import java.io.InputStream
class PagesCache(context: Context) { class PagesCache(context: Context) {

View File

@@ -15,11 +15,11 @@ import org.koitharu.kotatsu.local.data.LocalStorageManager
import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.local.data.MangaIndex
import org.koitharu.kotatsu.local.data.TempFileFilter import org.koitharu.kotatsu.local.data.TempFileFilter
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.longHashCode
import org.koitharu.kotatsu.parsers.util.toCamelCase import org.koitharu.kotatsu.parsers.util.toCamelCase
import org.koitharu.kotatsu.utils.AlphanumComparator import org.koitharu.kotatsu.utils.AlphanumComparator
import org.koitharu.kotatsu.utils.CompositeMutex import org.koitharu.kotatsu.utils.CompositeMutex
import org.koitharu.kotatsu.utils.ext.deleteAwait import org.koitharu.kotatsu.utils.ext.deleteAwait
import org.koitharu.kotatsu.utils.ext.longHashCode
import org.koitharu.kotatsu.utils.ext.readText import org.koitharu.kotatsu.utils.ext.readText
import org.koitharu.kotatsu.utils.ext.resolveName import org.koitharu.kotatsu.utils.ext.resolveName
import java.io.File import java.io.File

View File

@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.main
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module import org.koin.dsl.module
import org.koitharu.kotatsu.base.ui.util.ActivityRecreationHandle
import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.core.os.ShortcutsRepository
import org.koitharu.kotatsu.main.ui.MainViewModel import org.koitharu.kotatsu.main.ui.MainViewModel
import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper
@@ -11,6 +12,7 @@ import org.koitharu.kotatsu.main.ui.protect.ProtectViewModel
val mainModule val mainModule
get() = module { get() = module {
single { AppProtectHelper(get()) } single { AppProtectHelper(get()) }
single { ActivityRecreationHandle() }
factory { ShortcutsRepository(androidContext(), get(), get(), get()) } factory { ShortcutsRepository(androidContext(), get(), get(), get()) }
viewModel { MainViewModel(get(), get()) } viewModel { MainViewModel(get(), get()) }
viewModel { ProtectViewModel(get(), get()) } viewModel { ProtectViewModel(get(), get()) }

View File

@@ -45,7 +45,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
import org.koitharu.kotatsu.search.ui.MangaListActivity import org.koitharu.kotatsu.search.ui.MangaListActivity
import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.search.ui.SearchActivity
import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity import org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionFragment import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionFragment
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel
@@ -233,6 +233,8 @@ class MainActivity :
} }
binding.toolbarCard.updateLayoutParams<MarginLayoutParams> { binding.toolbarCard.updateLayoutParams<MarginLayoutParams> {
topMargin = insets.top + bottomMargin topMargin = insets.top + bottomMargin
leftMargin = insets.left
rightMargin = insets.right
} }
binding.root.updatePadding( binding.root.updatePadding(
left = insets.left, left = insets.left,
@@ -268,7 +270,7 @@ class MainActivity :
if (source != null) { if (source != null) {
startActivity(SearchActivity.newIntent(this, source, query)) startActivity(SearchActivity.newIntent(this, source, query))
} else { } else {
startActivity(GlobalSearchActivity.newIntent(this, query)) startActivity(MultiSearchActivity.newIntent(this, query))
} }
searchSuggestionViewModel.saveQuery(query) searchSuggestionViewModel.saveQuery(query)
} }

View File

@@ -5,10 +5,10 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter
fun Manga.filterChapters(branch: String?): Manga { fun Manga.filterChapters(branch: String?): Manga {
if (chapters.isNullOrEmpty()) return this if (chapters.isNullOrEmpty()) return this
return copy(chapters = chapters?.filter { it.branch == branch }) return withChapters(chapters = chapters?.filter { it.branch == branch })
} }
private fun Manga.copy(chapters: List<MangaChapter>?) = Manga( private fun Manga.withChapters(chapters: List<MangaChapter>?) = Manga(
id = id, id = id,
title = title, title = title,
altTitle = altTitle, altTitle = altTitle,

View File

@@ -7,7 +7,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.search.domain.MangaSearchRepository import org.koitharu.kotatsu.search.domain.MangaSearchRepository
import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider import org.koitharu.kotatsu.search.ui.MangaSuggestionsProvider
import org.koitharu.kotatsu.search.ui.SearchViewModel import org.koitharu.kotatsu.search.ui.SearchViewModel
import org.koitharu.kotatsu.search.ui.global.GlobalSearchViewModel import org.koitharu.kotatsu.search.ui.multi.MultiSearchViewModel
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel
val searchModule val searchModule
@@ -16,11 +16,7 @@ val searchModule
factory { MangaSearchRepository(get(), get(), androidContext(), get()) } factory { MangaSearchRepository(get(), get(), androidContext(), get()) }
factory { MangaSuggestionsProvider.createSuggestions(androidContext()) } factory { MangaSuggestionsProvider.createSuggestions(androidContext()) }
viewModel { params -> viewModel { params -> SearchViewModel(MangaRepository(params[0]), params[1], get()) }
SearchViewModel(MangaRepository(params[0]), params[1], get())
}
viewModel { query ->
GlobalSearchViewModel(query.get(), get(), get())
}
viewModel { SearchSuggestionViewModel(get(), get()) } viewModel { SearchSuggestionViewModel(get(), get()) }
viewModel { params -> MultiSearchViewModel(params[0], get()) }
} }

View File

@@ -14,16 +14,16 @@ import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaTags import org.koitharu.kotatsu.core.model.parcelable.ParcelableMangaTags
import org.koitharu.kotatsu.databinding.ActivitySearchGlobalBinding import org.koitharu.kotatsu.databinding.ActivityContainerBinding
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
import org.koitharu.kotatsu.remotelist.ui.RemoteListViewModel import org.koitharu.kotatsu.remotelist.ui.RemoteListViewModel
class MangaListActivity : BaseActivity<ActivitySearchGlobalBinding>() { class MangaListActivity : BaseActivity<ActivityContainerBinding>() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivitySearchGlobalBinding.inflate(layoutInflater)) setContentView(ActivityContainerBinding.inflate(layoutInflater))
val tags = intent.getParcelableExtra<ParcelableMangaTags>(EXTRA_TAGS)?.tags ?: run { val tags = intent.getParcelableExtra<ParcelableMangaTags>(EXTRA_TAGS)?.tags ?: run {
finishAfterTransition() finishAfterTransition()
return return

View File

@@ -1,55 +0,0 @@
package org.koitharu.kotatsu.search.ui.global
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.databinding.ActivitySearchGlobalBinding
class GlobalSearchActivity : BaseActivity<ActivitySearchGlobalBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivitySearchGlobalBinding.inflate(layoutInflater))
val query = intent.getStringExtra(EXTRA_QUERY)
if (query == null) {
finishAfterTransition()
return
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
title = query
supportActionBar?.subtitle = getString(R.string.search_results)
supportFragmentManager
.beginTransaction()
.replace(R.id.container, GlobalSearchFragment.newInstance(query))
.commit()
}
override fun onWindowInsetsChanged(insets: Insets) {
with(binding.toolbar) {
updatePadding(
left = insets.left,
right = insets.right
)
updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
}
companion object {
private const val EXTRA_QUERY = "query"
fun newIntent(context: Context, query: String) =
Intent(context, GlobalSearchActivity::class.java)
.putExtra(EXTRA_QUERY, query)
}
}

View File

@@ -1,35 +0,0 @@
package org.koitharu.kotatsu.search.ui.global
import android.view.Menu
import androidx.appcompat.view.ActionMode
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.list.ui.MangaListFragment
import org.koitharu.kotatsu.utils.ext.stringArgument
import org.koitharu.kotatsu.utils.ext.withArgs
class GlobalSearchFragment : MangaListFragment() {
override val viewModel by viewModel<GlobalSearchViewModel> {
parametersOf(query)
}
private val query by stringArgument(ARG_QUERY)
override fun onScrolledToEnd() = Unit
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.mode_remote, menu)
return super.onCreateActionMode(mode, menu)
}
companion object {
private const val ARG_QUERY = "query"
fun newInstance(query: String) = GlobalSearchFragment().withArgs(1) {
putString(ARG_QUERY, query)
}
}
}

View File

@@ -1,87 +0,0 @@
package org.koitharu.kotatsu.search.ui.global
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.*
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.search.domain.MangaSearchRepository
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.onFirst
class GlobalSearchViewModel(
private val query: String,
private val repository: MangaSearchRepository,
settings: AppSettings
) : MangaListViewModel(settings) {
private val mangaList = MutableStateFlow<List<Manga>?>(null)
private val hasNextPage = MutableStateFlow(false)
private val listError = MutableStateFlow<Throwable?>(null)
private var searchJob: Job? = null
override val content = combine(
mangaList,
createListModeFlow(),
listError,
hasNextPage
) { list, mode, error, hasNext ->
when {
list.isNullOrEmpty() && error != null -> listOf(error.toErrorState(canRetry = true))
list == null -> listOf(LoadingState)
list.isEmpty() -> listOf(
EmptyState(
icon = R.drawable.ic_book_search,
textPrimary = R.string.nothing_found,
textSecondary = R.string.text_search_holder_secondary,
actionStringRes = 0,
)
)
else -> {
val result = ArrayList<ListModel>(list.size + 1)
list.toUi(result, mode)
when {
error != null -> result += error.toErrorFooter()
hasNext -> result += LoadingFooter
}
result
}
}
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
init {
onRefresh()
}
override fun onRetry() {
onRefresh()
}
override fun onRefresh() {
searchJob?.cancel()
searchJob = repository.globalSearch(query)
.catch { e ->
listError.value = e
loadingCounter.reset()
}.onStart {
mangaList.value = null
listError.value = null
loadingCounter.increment()
hasNextPage.value = true
}.onEmpty {
mangaList.value = emptyList()
}.onCompletion {
loadingCounter.reset()
hasNextPage.value = false
}.onFirst {
loadingCounter.reset()
}.onEach {
mangaList.value = mangaList.value?.plus(it) ?: listOf(it)
}.launchIn(viewModelScope + Dispatchers.Default)
}
}

View File

@@ -0,0 +1,183 @@
package org.koitharu.kotatsu.search.ui.multi
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.RecyclerView
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.databinding.ActivitySearchMultiBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.download.ui.service.DownloadService
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesBottomSheet
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.search.ui.SearchActivity
import org.koitharu.kotatsu.search.ui.multi.adapter.ItemSizeResolver
import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter
import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.findViewsByType
class MultiSearchActivity : BaseActivity<ActivitySearchMultiBinding>(), MangaListListener, ActionMode.Callback {
private val viewModel by viewModel<MultiSearchViewModel> {
parametersOf(intent.getStringExtra(EXTRA_QUERY).orEmpty())
}
private lateinit var adapter: MultiSearchAdapter
private lateinit var selectionDecoration: MangaSelectionDecoration
private var actionMode: ActionMode? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivitySearchMultiBinding.inflate(layoutInflater))
val itemCLickListener = object : OnListItemClickListener<MultiSearchListModel> {
override fun onItemClick(item: MultiSearchListModel, view: View) {
startActivity(SearchActivity.newIntent(view.context, item.source, viewModel.query.value))
}
}
val sizeResolver = ItemSizeResolver(resources, get())
selectionDecoration = MangaSelectionDecoration(this)
adapter = MultiSearchAdapter(
lifecycleOwner = this,
coil = get(),
listener = this,
itemClickListener = itemCLickListener,
sizeResolver = sizeResolver,
selectionDecoration = selectionDecoration,
)
binding.recyclerView.adapter = adapter
binding.recyclerView.setHasFixedSize(true)
supportActionBar?.run {
setDisplayHomeAsUpEnabled(true)
setSubtitle(R.string.search_results)
}
viewModel.query.observe(this) { title = it }
viewModel.list.observe(this) { adapter.items = it }
}
override fun onWindowInsetsChanged(insets: Insets) {
with(binding.toolbar) {
updatePadding(
left = insets.left,
right = insets.right,
)
updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.top
}
}
binding.recyclerView.updatePadding(
bottom = insets.bottom,
left = insets.left,
right = insets.right,
)
}
override fun onItemClick(item: Manga, view: View) {
if (selectionDecoration.checkedItemsCount != 0) {
selectionDecoration.toggleItemChecked(item.id)
if (selectionDecoration.checkedItemsCount == 0) {
actionMode?.finish()
} else {
actionMode?.invalidate()
invalidateItemDecorations()
}
return
}
val intent = DetailsActivity.newIntent(this, item)
startActivity(intent)
}
override fun onItemLongClick(item: Manga, view: View): Boolean {
if (actionMode == null) {
actionMode = startSupportActionMode(this)
}
return actionMode?.also {
selectionDecoration.setItemIsChecked(item.id, true)
invalidateItemDecorations()
it.invalidate()
} != null
}
override fun onRetryClick(error: Throwable) {
viewModel.doSearch(viewModel.query.value.orEmpty())
}
override fun onTagRemoveClick(tag: MangaTag) = Unit
override fun onFilterClick() = Unit
override fun onEmptyActionClick() = Unit
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.mode_remote, menu)
return true
}
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.title = selectionDecoration.checkedItemsCount.toString()
return true
}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_share -> {
ShareHelper(this).shareMangaLinks(collectSelectedItems())
mode.finish()
true
}
R.id.action_favourite -> {
FavouriteCategoriesBottomSheet.show(supportFragmentManager, collectSelectedItems())
mode.finish()
true
}
R.id.action_save -> {
DownloadService.confirmAndStart(this, collectSelectedItems())
mode.finish()
true
}
else -> false
}
}
override fun onDestroyActionMode(mode: ActionMode) {
selectionDecoration.clearSelection()
invalidateItemDecorations()
actionMode = null
}
private fun collectSelectedItems(): Set<Manga> {
return viewModel.getItems(selectionDecoration.checkedItemsIds)
}
private fun invalidateItemDecorations() {
binding.recyclerView.findViewsByType(RecyclerView::class.java).forEach {
it.invalidateItemDecorations()
}
}
companion object {
private const val EXTRA_QUERY = "query"
fun newIntent(context: Context, query: String) =
Intent(context, MultiSearchActivity::class.java)
.putExtra(EXTRA_QUERY, query)
}
}

View File

@@ -0,0 +1,29 @@
package org.koitharu.kotatsu.search.ui.multi
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
import org.koitharu.kotatsu.parsers.model.MangaSource
class MultiSearchListModel(
val source: MangaSource,
val list: List<MangaItemModel>,
) : ListModel {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MultiSearchListModel
if (source != other.source) return false
if (list != other.list) return false
return true
}
override fun hashCode(): Int {
var result = source.hashCode()
result = 31 * result + list.hashCode()
return result
}
}

View File

@@ -0,0 +1,112 @@
package org.koitharu.kotatsu.search.ui.multi
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
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.parser.MangaRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.list.ui.model.*
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.printStackTraceDebug
private const val MAX_PARALLELISM = 4
class MultiSearchViewModel(
initialQuery: String,
private val settings: AppSettings,
) : BaseViewModel() {
private var searchJob: Job? = null
private val listData = MutableStateFlow<List<MultiSearchListModel>>(emptyList())
private val loadingData = MutableStateFlow(false)
private var listError = MutableStateFlow<Throwable?>(null)
val query = MutableLiveData(initialQuery)
val list: LiveData<List<ListModel>> = combine(
listData,
loadingData,
listError,
) { list, loading, error ->
when {
list.isEmpty() -> listOf(
when {
loading -> LoadingState
error != null -> error.toErrorState(canRetry = true)
else -> EmptyState(
icon = R.drawable.ic_book_search,
textPrimary = R.string.nothing_found,
textSecondary = R.string.text_search_holder_secondary,
actionStringRes = 0,
)
}
)
loading -> list + LoadingFooter
else -> list
}
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(LoadingState))
init {
doSearch(initialQuery)
}
fun getItems(ids: Set<Long>): Set<Manga> {
val result = HashSet<Manga>(ids.size)
listData.value.forEach { x ->
for (item in x.list) {
if (item.id in ids) {
result.add(item.manga)
}
}
}
return result
}
fun doSearch(q: String) {
val prevJob = searchJob
searchJob = launchJob(Dispatchers.Default) {
prevJob?.cancelAndJoin()
try {
listError.value = null
listData.value = emptyList()
loadingData.value = true
query.postValue(q)
val errors = searchImpl(q)
listError.value = errors.firstOrNull()
} catch (e: Throwable) {
listError.value = e
} finally {
loadingData.value = false
}
}
}
private suspend fun searchImpl(q: String): List<Throwable> {
val sources = settings.getMangaSources(includeHidden = false)
val dispatcher = Dispatchers.Default.limitedParallelism(MAX_PARALLELISM)
return coroutineScope {
sources.map { source ->
async(dispatcher) {
runCatching {
val list = MangaRepository(source).getList(offset = 0, query = q)
// .sortedBy { x -> x.title.levenshteinDistance(q) }
.toUi(ListMode.GRID)
if (list.isNotEmpty()) {
val item = MultiSearchListModel(source, list)
listData.update { x -> x + item }
}
}.onFailure {
it.printStackTraceDebug()
}.exceptionOrNull()
}
}
}.awaitAll().filterNotNull()
}
}

View File

@@ -0,0 +1,15 @@
package org.koitharu.kotatsu.search.ui.multi.adapter
import android.content.res.Resources
import kotlin.math.roundToInt
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings
class ItemSizeResolver(resources: Resources, settings: AppSettings) {
private val scaleFactor = settings.gridSize / 100f
private val gridWidth = resources.getDimension(R.dimen.preferred_grid_width)
val cellWidth: Int
get() = (gridWidth * scaleFactor).roundToInt()
}

View File

@@ -0,0 +1,59 @@
package org.koitharu.kotatsu.search.ui.multi.adapter
import androidx.lifecycle.LifecycleOwner
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.list.ui.MangaSelectionDecoration
import org.koitharu.kotatsu.list.ui.adapter.*
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.search.ui.multi.MultiSearchListModel
import kotlin.jvm.internal.Intrinsics
class MultiSearchAdapter(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
listener: MangaListListener,
itemClickListener: OnListItemClickListener<MultiSearchListModel>,
sizeResolver: ItemSizeResolver,
selectionDecoration: MangaSelectionDecoration,
) : AsyncListDifferDelegationAdapter<ListModel>(DiffCallback()) {
init {
val pool = RecycledViewPool()
delegatesManager
.addDelegate(
searchResultsAD(
sharedPool = pool,
lifecycleOwner = lifecycleOwner,
coil = coil,
sizeResolver = sizeResolver,
selectionDecoration = selectionDecoration,
listener = listener,
itemClickListener = itemClickListener,
)
)
.addDelegate(loadingStateAD())
.addDelegate(loadingFooterAD())
.addDelegate(emptyStateListAD(listener))
.addDelegate(errorStateListAD(listener))
}
private class DiffCallback : DiffUtil.ItemCallback<ListModel>() {
override fun areItemsTheSame(oldItem: ListModel, newItem: ListModel): Boolean {
return when {
oldItem is MultiSearchListModel && newItem is MultiSearchListModel -> {
oldItem.source == newItem.source
}
else -> oldItem.javaClass == newItem.javaClass
}
}
override fun areContentsTheSame(oldItem: ListModel, newItem: ListModel): Boolean {
return Intrinsics.areEqual(oldItem, newItem)
}
}
}

View File

@@ -0,0 +1,47 @@
package org.koitharu.kotatsu.search.ui.multi.adapter
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
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.databinding.ItemListGroupBinding
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
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.search.ui.multi.MultiSearchListModel
fun searchResultsAD(
sharedPool: RecycledViewPool,
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
sizeResolver: ItemSizeResolver,
selectionDecoration: MangaSelectionDecoration,
listener: OnListItemClickListener<Manga>,
itemClickListener: OnListItemClickListener<MultiSearchListModel>,
) = adapterDelegateViewBinding<MultiSearchListModel, ListModel, ItemListGroupBinding>(
{ layoutInflater, parent -> ItemListGroupBinding.inflate(layoutInflater, parent, false) }
) {
binding.recyclerView.setRecycledViewPool(sharedPool)
val adapter = ListDelegationAdapter(
mangaGridItemAD(coil, lifecycleOwner, listener, sizeResolver)
)
binding.recyclerView.addItemDecoration(selectionDecoration)
binding.recyclerView.adapter = adapter
val spacing = context.resources.getDimensionPixelOffset(R.dimen.grid_spacing)
binding.recyclerView.addItemDecoration(SpacingItemDecoration(spacing))
val eventListener = AdapterDelegateClickListenerAdapter(this, itemClickListener)
itemView.setOnClickListener(eventListener)
bind {
binding.textViewTitle.text = item.source.title
adapter.items = item.list
adapter.notifyDataSetChanged()
}
}

View File

@@ -5,11 +5,15 @@ import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.postDelayed
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.TwoStatePreference import androidx.preference.TwoStatePreference
import com.google.android.material.color.DynamicColors
import org.koin.android.ext.android.get
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BasePreferenceFragment 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.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.parsers.util.names import org.koitharu.kotatsu.parsers.util.names
@@ -36,7 +40,7 @@ class AppearanceSettingsFragment :
entryValues = ListMode.values().names() entryValues = ListMode.values().names()
setDefaultValueCompat(ListMode.GRID.name) setDefaultValueCompat(ListMode.GRID.name)
} }
findPreference<Preference>(AppSettings.KEY_DYNAMIC_THEME)?.isVisible = AppSettings.isDynamicColorAvailable findPreference<Preference>(AppSettings.KEY_DYNAMIC_THEME)?.isVisible = DynamicColors.isDynamicColorAvailable()
findPreference<ListPreference>(AppSettings.KEY_DATE_FORMAT)?.run { findPreference<ListPreference>(AppSettings.KEY_DATE_FORMAT)?.run {
entryValues = resources.getStringArray(R.array.date_formats) entryValues = resources.getStringArray(R.array.date_formats)
val now = Date().time val now = Date().time
@@ -71,10 +75,10 @@ class AppearanceSettingsFragment :
AppCompatDelegate.setDefaultNightMode(settings.theme) AppCompatDelegate.setDefaultNightMode(settings.theme)
} }
AppSettings.KEY_DYNAMIC_THEME -> { AppSettings.KEY_DYNAMIC_THEME -> {
findPreference<Preference>(key)?.setSummary(R.string.restart_required) postRestart()
} }
AppSettings.KEY_THEME_AMOLED -> { AppSettings.KEY_THEME_AMOLED -> {
findPreference<Preference>(key)?.setSummary(R.string.restart_required) postRestart()
} }
AppSettings.KEY_APP_PASSWORD -> { AppSettings.KEY_APP_PASSWORD -> {
findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP) findPreference<TwoStatePreference>(AppSettings.KEY_PROTECT_APP)
@@ -98,4 +102,10 @@ class AppearanceSettingsFragment :
else -> super.onPreferenceTreeClick(preference) else -> super.onPreferenceTreeClick(preference)
} }
} }
private fun postRestart() {
view?.postDelayed(400) {
get<ActivityRecreationHandle>().recreateAll()
}
}
} }

View File

@@ -33,7 +33,7 @@ class SettingsHeadersFragment : PreferenceHeaderFragmentCompat(), SlidingPaneLay
fun setTitle(title: CharSequence?) { fun setTitle(title: CharSequence?) {
currentTitle = title currentTitle = title
if (slidingPaneLayout.isSlideable && slidingPaneLayout.isOpen) { if (slidingPaneLayout.isOpen) {
activity?.title = title activity?.title = title
} }
} }

View File

@@ -21,7 +21,8 @@ import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigAdapter
import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener import org.koitharu.kotatsu.settings.sources.adapter.SourceConfigListener
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
class SourcesSettingsFragment : BaseFragment<FragmentSettingsSourcesBinding>(), class SourcesSettingsFragment :
BaseFragment<FragmentSettingsSourcesBinding>(),
SourceConfigListener, SourceConfigListener,
SearchView.OnQueryTextListener, SearchView.OnQueryTextListener,
MenuItem.OnActionExpandListener, MenuItem.OnActionExpandListener,
@@ -53,7 +54,6 @@ class SourcesSettingsFragment : BaseFragment<FragmentSettingsSourcesBinding>(),
val sourcesAdapter = SourceConfigAdapter(this, get(), viewLifecycleOwner) val sourcesAdapter = SourceConfigAdapter(this, get(), viewLifecycleOwner)
with(binding.recyclerView) { with(binding.recyclerView) {
setHasFixedSize(true) setHasFixedSize(true)
// addItemDecoration(SourceConfigItemDecoration(view.context))
adapter = sourcesAdapter adapter = sourcesAdapter
reorderHelper = ItemTouchHelper(SourcesReorderCallback()).also { reorderHelper = ItemTouchHelper(SourcesReorderCallback()).also {
it.attachToRecyclerView(this) it.attachToRecyclerView(this)

View File

@@ -51,6 +51,9 @@ class SourcesSettingsViewModel(
} else { } else {
settings.hiddenSources + source.name settings.hiddenSources + source.name
} }
if (isEnabled) {
settings.markKnownSources(setOf(source))
}
buildList() buildList()
} }

View File

@@ -1,15 +0,0 @@
package org.koitharu.kotatsu.settings.sources.adapter
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import org.koitharu.kotatsu.base.ui.list.decor.AbstractDividerItemDecoration
class SourceConfigItemDecoration(context: Context) : AbstractDividerItemDecoration(context) {
override fun shouldDrawDivider(
above: RecyclerView.ViewHolder,
below: RecyclerView.ViewHolder,
): Boolean {
return above.itemViewType != 0 && below.itemViewType != 0
}
}

View File

@@ -0,0 +1,15 @@
package org.koitharu.kotatsu.utils.ext
import android.content.Context
import android.os.Build
import android.view.Display
import android.view.WindowManager
import androidx.core.content.getSystemService
val Context.displayCompat: Display?
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
display
} else {
@Suppress("DEPRECATION")
getSystemService<WindowManager>()?.defaultDisplay
}

View File

@@ -2,4 +2,13 @@ package org.koitharu.kotatsu.utils.ext
inline fun String?.ifNullOrEmpty(defaultValue: () -> String): String { inline fun String?.ifNullOrEmpty(defaultValue: () -> String): String {
return if (this.isNullOrEmpty()) defaultValue() else this return if (this.isNullOrEmpty()) defaultValue() else this
}
fun String.longHashCode(): Long {
var h = 1125899906842597L
val len: Int = this.length
for (i in 0 until len) {
h = 31 * h + this[i].code
}
return h
} }

View File

@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.utils.ext
import android.app.Activity import android.app.Activity
import android.graphics.Rect import android.graphics.Rect
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.core.view.children import androidx.core.view.children
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@@ -138,4 +139,19 @@ val RecyclerView.isScrolledToTop: Boolean
} }
val holder = findViewHolderForAdapterPosition(0) val holder = findViewHolderForAdapterPosition(0)
return holder != null && holder.itemView.top >= 0 return holder != null && holder.itemView.top >= 0
} }
fun <T : View> ViewGroup.findViewsByType(clazz: Class<T>): Sequence<T> {
if (childCount == 0) {
return emptySequence()
}
return sequence {
for (view in children) {
if (clazz.isInstance(view)) {
yield(clazz.cast(view)!!)
} else if (view is ViewGroup && view.childCount != 0) {
yieldAll(view.findViewsByType(clazz))
}
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in">
<translate
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:interpolator/fast_out_slow_in">
<translate
android:fromYDelta="0"
android:toYDelta="100%p" />
</set>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape>
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="?android:attr/divider" />
</shape>
</item>
</layer-list>

View File

@@ -11,6 +11,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:indeterminate="true" android:indeterminate="true"
app:indicatorSize="@dimen/list_footer_height_inner" /> app:indicatorSize="24dp"/>
</FrameLayout> </FrameLayout>

View File

@@ -10,7 +10,7 @@
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="?attr/actionBarSize" />
<ScrollView <ScrollView
android:id="@+id/scrollView" android:id="@+id/scrollView"

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:orientation="vertical"
android:paddingVertical="@dimen/grid_spacing_outer">
<TextView
android:id="@+id/textView_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/grid_spacing"
android:gravity="center_vertical|start"
android:padding="@dimen/grid_spacing"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.Kotatsu.SectionHeader"
tools:text="@tools:sample/lorem[2]" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/grid_spacing"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>

View File

@@ -9,6 +9,7 @@
android:layout_width="@dimen/list_footer_height_inner" android:layout_width="@dimen/list_footer_height_inner"
android:layout_height="@dimen/list_footer_height_inner" android:layout_height="@dimen/list_footer_height_inner"
android:layout_gravity="center" android:layout_gravity="center"
android:indeterminate="true" /> android:indeterminate="true"
android:padding="8dp"/>
</FrameLayout> </FrameLayout>

View File

@@ -27,8 +27,9 @@
android:id="@+id/textView_title" android:id="@+id/textView_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:elegantTextHeight="false"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:lines="2"
android:padding="8dp" android:padding="8dp"
android:textAppearance="?attr/textAppearanceTitleSmall" android:textAppearance="?attr/textAppearanceTitleSmall"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"

View File

@@ -10,7 +10,8 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar" android:id="@+id/appbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"> android:layout_height="?attr/actionBarSize"
android:background="@drawable/sheet_toolbar_background">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"

View File

@@ -10,7 +10,8 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar" android:id="@+id/appbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"> android:layout_height="?attr/actionBarSize"
android:background="@drawable/sheet_toolbar_background">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"

View File

@@ -10,7 +10,8 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar" android:id="@+id/appbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"> android:layout_height="?attr/actionBarSize"
android:background="@drawable/sheet_toolbar_background">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"

View File

@@ -153,8 +153,6 @@
<string name="update_check_failed">Памылка пры праверцы абнаўленняў</string> <string name="update_check_failed">Памылка пры праверцы абнаўленняў</string>
<string name="no_update_available">Няма даступных абнаўленняў</string> <string name="no_update_available">Няма даступных абнаўленняў</string>
<string name="right_to_left">Справа налева</string> <string name="right_to_left">Справа налева</string>
<string name="prefer_rtl_reader">Аддаваць перавагу рэжыму справа налева</string>
<string name="prefer_rtl_reader_summary">Вы можаце наладзіць рэжым чытання для кожнай мангі асобна</string>
<string name="create_category">Стварыць катэгорыю</string> <string name="create_category">Стварыць катэгорыю</string>
<string name="report_github">Пачаць абмеркаванне праблемы на GitHub</string> <string name="report_github">Пачаць абмеркаванне праблемы на GitHub</string>
<string name="scale_mode">Маштабаванне</string> <string name="scale_mode">Маштабаванне</string>
@@ -164,7 +162,6 @@
<string name="zoom_mode_keep_start">Зыходны памер</string> <string name="zoom_mode_keep_start">Зыходны памер</string>
<string name="black_dark_theme">Чорная цёмная тэма</string> <string name="black_dark_theme">Чорная цёмная тэма</string>
<string name="black_dark_theme_summary">Карысна для AMOLED экранаў</string> <string name="black_dark_theme_summary">Карысна для AMOLED экранаў</string>
<string name="restart_required">Патрэбны перазапуск</string>
<string name="backup_restore">Рэзервовае капіяванне і аднаўленне</string> <string name="backup_restore">Рэзервовае капіяванне і аднаўленне</string>
<string name="create_backup">Стварыць рэзервовую копію</string> <string name="create_backup">Стварыць рэзервовую копію</string>
<string name="restore_backup">Аднавіць данныя</string> <string name="restore_backup">Аднавіць данныя</string>

View File

@@ -85,10 +85,7 @@
<string name="zoom_mode_fit_height">An Höhe anpassen</string> <string name="zoom_mode_fit_height">An Höhe anpassen</string>
<string name="black_dark_theme_summary">Nützlich für AMOLED-Bildschirme</string> <string name="black_dark_theme_summary">Nützlich für AMOLED-Bildschirme</string>
<string name="black_dark_theme">Schwarzer dunkler Modus</string> <string name="black_dark_theme">Schwarzer dunkler Modus</string>
<string name="restart_required">Neustart erforderlich</string>
<string name="prefer_rtl_reader_summary">Du kannst den Lesemodus für jeden Manga separat einrichten</string>
<string name="right_to_left">Von rechts nach links</string> <string name="right_to_left">Von rechts nach links</string>
<string name="prefer_rtl_reader">Von rechts nach links-Lesemodus bevorzugen</string>
<string name="create_category">Neue Kategorie</string> <string name="create_category">Neue Kategorie</string>
<string name="backup_restore">Sicherung und Wiederherstellung</string> <string name="backup_restore">Sicherung und Wiederherstellung</string>
<string name="data_restored">Daten wiederhergestellt</string> <string name="data_restored">Daten wiederhergestellt</string>
@@ -278,4 +275,23 @@
<string name="chapters_will_removed_background">Die Kapitel werden im Hintergrund entfernt. Das kann einige Zeit dauern</string> <string name="chapters_will_removed_background">Die Kapitel werden im Hintergrund entfernt. Das kann einige Zeit dauern</string>
<string name="hide">Ausblenden</string> <string name="hide">Ausblenden</string>
<string name="new_sources_text">Neue Manga-Quellen sind verfügbar</string> <string name="new_sources_text">Neue Manga-Quellen sind verfügbar</string>
<string name="check_new_chapters_title">Nach neuen Kapiteln suchen und darüber informieren</string>
<string name="show_notification_new_chapters_on">Sie erhalten Benachrichtigungen über Aktualisierungen der Manga, die Sie lesen</string>
<string name="notifications_enable">Benachrichtigungen einschalten</string>
<string name="empty_favourite_categories">Keine bevorzugten Kategorien</string>
<string name="name">Name</string>
<string name="edit">Bearbeiten</string>
<string name="show_notification_new_chapters_off">Sie werden keine Benachrichtigungen erhalten, aber neue Kapitel werden in den Listen hervorgehoben</string>
<string name="edit_category">Kategorie bearbeiten</string>
<string name="bookmark_add">Lesezeichen hinzufügen</string>
<string name="bookmarks">Lesezeichen</string>
<string name="bookmark_removed">Lesezeichen entfernt</string>
<string name="removed_from_history">Aus dem Verlauf entfernt</string>
<string name="bookmark_remove">Lesezeichen entfernen</string>
<string name="bookmark_added">Lesezeichen hinzugefügt</string>
<string name="undo">Rückgängig</string>
<string name="dns_over_https">DNS über HTTPS</string>
<string name="default_mode">Standard-Modus</string>
<string name="detect_reader_mode">Automatische Erkennung des Lesegerätmodus</string>
<string name="detect_reader_mode_summary">Automatisch erkennen, ob ein Manga ein Webtoon ist</string>
</resources> </resources>

View File

@@ -153,8 +153,6 @@
<string name="update_check_failed">Fallo en la comprobación de actualizaciones</string> <string name="update_check_failed">Fallo en la comprobación de actualizaciones</string>
<string name="no_update_available">No hay actualizaciones disponibles</string> <string name="no_update_available">No hay actualizaciones disponibles</string>
<string name="right_to_left">Derecha a izquierda (←)</string> <string name="right_to_left">Derecha a izquierda (←)</string>
<string name="prefer_rtl_reader">Preferir lector de derecha a izquierda (←)</string>
<string name="prefer_rtl_reader_summary">Puedes configurar el modo de lectura para cada manga por separado</string>
<string name="create_category">Nueva categoría</string> <string name="create_category">Nueva categoría</string>
<string name="report_github">Crear incidencia en GitHub</string> <string name="report_github">Crear incidencia en GitHub</string>
<string name="scale_mode">Modo de escala</string> <string name="scale_mode">Modo de escala</string>
@@ -164,7 +162,6 @@
<string name="zoom_mode_keep_start">Mantener al iniciar</string> <string name="zoom_mode_keep_start">Mantener al iniciar</string>
<string name="black_dark_theme">Tema oscuro auténtico</string> <string name="black_dark_theme">Tema oscuro auténtico</string>
<string name="black_dark_theme_summary">Útil para pantallas AMOLED</string> <string name="black_dark_theme_summary">Útil para pantallas AMOLED</string>
<string name="restart_required">Se requiere reinicio</string>
<string name="backup_restore">Respaldo y restauración</string> <string name="backup_restore">Respaldo y restauración</string>
<string name="create_backup">Crear copia de seguridad de datos</string> <string name="create_backup">Crear copia de seguridad de datos</string>
<string name="restore_backup">Restaurar desde la copia de seguridad</string> <string name="restore_backup">Restaurar desde la copia de seguridad</string>

View File

@@ -53,7 +53,6 @@
<string name="restore_backup">Palauta varmuuskopiosta</string> <string name="restore_backup">Palauta varmuuskopiosta</string>
<string name="create_backup">Luo tietojen varmuuskopio</string> <string name="create_backup">Luo tietojen varmuuskopio</string>
<string name="backup_restore">Varmuuskopiointi ja palautus</string> <string name="backup_restore">Varmuuskopiointi ja palautus</string>
<string name="restart_required">Uudelleenkäynnistys vaaditaan</string>
<string name="black_dark_theme_summary">Hyödyllinen AMOLED-näytöille</string> <string name="black_dark_theme_summary">Hyödyllinen AMOLED-näytöille</string>
<string name="black_dark_theme">Musta tumma teema</string> <string name="black_dark_theme">Musta tumma teema</string>
<string name="zoom_mode_keep_start">Pidä alussa</string> <string name="zoom_mode_keep_start">Pidä alussa</string>
@@ -63,8 +62,6 @@
<string name="scale_mode">Skaalaustila</string> <string name="scale_mode">Skaalaustila</string>
<string name="report_github">Luo ongelma GitHubissa</string> <string name="report_github">Luo ongelma GitHubissa</string>
<string name="create_category">Uusi luokka</string> <string name="create_category">Uusi luokka</string>
<string name="prefer_rtl_reader_summary">Voit määrittää lukutilan jokaiselle mangalle erikseen</string>
<string name="prefer_rtl_reader">Mieluummin oikealta vasemmalle lukutila</string>
<string name="right_to_left">Oikealta vasemmalle</string> <string name="right_to_left">Oikealta vasemmalle</string>
<string name="no_update_available">Ei päivityksiä saatavilla</string> <string name="no_update_available">Ei päivityksiä saatavilla</string>
<string name="update_check_failed">Päivityksen tarkistus epäonnistui</string> <string name="update_check_failed">Päivityksen tarkistus epäonnistui</string>
@@ -278,4 +275,23 @@
<string name="local_manga_processing">Tallennettujen mangojen käsittely</string> <string name="local_manga_processing">Tallennettujen mangojen käsittely</string>
<string name="hide">Piilota</string> <string name="hide">Piilota</string>
<string name="new_sources_text">Uusia mangalähteitä on saatavilla</string> <string name="new_sources_text">Uusia mangalähteitä on saatavilla</string>
<string name="check_new_chapters_title">Tarkista uudet luvut ja ilmoita siitä</string>
<string name="notifications_enable">Ota ilmoitukset käyttöön</string>
<string name="empty_favourite_categories">Ei suosikkiluokkia</string>
<string name="name">Nimi</string>
<string name="edit">Muokkaa</string>
<string name="edit_category">Muokkaa luokkaa</string>
<string name="show_notification_new_chapters_off">Et saa ilmoituksia, mutta uudet luvut korostetaan luetteloissa</string>
<string name="show_notification_new_chapters_on">Saat ilmoituksia lukemasi mangan päivityksistä</string>
<string name="bookmark_add">Lisää kirjanmerkki</string>
<string name="bookmark_remove">Poista kirjanmerkki</string>
<string name="bookmarks">Kirjanmerkit</string>
<string name="bookmark_removed">Kirjanmerkki poistettu</string>
<string name="bookmark_added">Kirjanmerkki lisätty</string>
<string name="undo">Kumoa</string>
<string name="removed_from_history">Poistettu historiasta</string>
<string name="dns_over_https">DNS HTTPS:n kautta</string>
<string name="detect_reader_mode">Lukijan automaattinen tunnistaminen</string>
<string name="detect_reader_mode_summary">Tunnista automaattisesti, onko manga webtoon</string>
<string name="default_mode">Oletustila</string>
</resources> </resources>

View File

@@ -42,7 +42,6 @@
<string name="restore_backup">Restaurer à partir d\'une sauvegarde</string> <string name="restore_backup">Restaurer à partir d\'une sauvegarde</string>
<string name="create_backup">Créer une sauvegarde des données</string> <string name="create_backup">Créer une sauvegarde des données</string>
<string name="backup_restore">Sauvegarde et restauration</string> <string name="backup_restore">Sauvegarde et restauration</string>
<string name="restart_required">Redémarrage nécessaire</string>
<string name="black_dark_theme_summary">Utilise moins d\'énergie pour les écrans AMOLED</string> <string name="black_dark_theme_summary">Utilise moins d\'énergie pour les écrans AMOLED</string>
<string name="black_dark_theme">Noir</string> <string name="black_dark_theme">Noir</string>
<string name="zoom_mode_keep_start">Garder au début</string> <string name="zoom_mode_keep_start">Garder au début</string>
@@ -52,8 +51,6 @@
<string name="scale_mode">Mode mise à l\'échelle</string> <string name="scale_mode">Mode mise à l\'échelle</string>
<string name="report_github">Signaler un problème sur GitHub</string> <string name="report_github">Signaler un problème sur GitHub</string>
<string name="create_category">Nouvelle catégorie</string> <string name="create_category">Nouvelle catégorie</string>
<string name="prefer_rtl_reader_summary">Le mode de lecture peut être configuré séparément pour chaque série</string>
<string name="prefer_rtl_reader">Préférer le lecteur de droite à gauche (←)</string>
<string name="right_to_left">De droite à gauche (←)</string> <string name="right_to_left">De droite à gauche (←)</string>
<string name="no_update_available">Aucune mise à jour disponible</string> <string name="no_update_available">Aucune mise à jour disponible</string>
<string name="update_check_failed">Échec de la recherche de mise à jour</string> <string name="update_check_failed">Échec de la recherche de mise à jour</string>
@@ -278,4 +275,23 @@
<string name="local_manga_processing">Traitement des mangas sauvegardés</string> <string name="local_manga_processing">Traitement des mangas sauvegardés</string>
<string name="hide">Masquer</string> <string name="hide">Masquer</string>
<string name="new_sources_text">De nouvelles sources de mangas sont disponibles</string> <string name="new_sources_text">De nouvelles sources de mangas sont disponibles</string>
<string name="check_new_chapters_title">Vérifier les nouveaux chapitres et les notifier</string>
<string name="notifications_enable">Activer les notifications</string>
<string name="show_notification_new_chapters_on">Vous recevrez des notifications sur les mises à jour des mangas que vous lisez</string>
<string name="show_notification_new_chapters_off">Vous ne recevrez pas de notifications mais les nouveaux chapitres seront mis en évidence dans les listes</string>
<string name="empty_favourite_categories">Pas de catégories préférées</string>
<string name="name">Nom</string>
<string name="edit">Modifier</string>
<string name="edit_category">Modifier la catégorie</string>
<string name="bookmark_add">Ajouter un marque-page</string>
<string name="bookmark_remove">Retirer le marque-page</string>
<string name="bookmarks">Marque-pages</string>
<string name="bookmark_added">Marque-page ajouté</string>
<string name="bookmark_removed">Marque-page retiré</string>
<string name="undo">Annuler</string>
<string name="removed_from_history">Retiré de l\'historique</string>
<string name="dns_over_https">DNS sur HTTPS</string>
<string name="default_mode">Mode par défaut</string>
<string name="detect_reader_mode">Mode de détection automatique du lecteur</string>
<string name="detect_reader_mode_summary">Détecter automatiquement si un manga est un webtoon</string>
</resources> </resources>

View File

@@ -91,13 +91,10 @@
<string name="restore_backup">Ripristina da un backup</string> <string name="restore_backup">Ripristina da un backup</string>
<string name="create_backup">Crea un backup dei dati</string> <string name="create_backup">Crea un backup dei dati</string>
<string name="backup_restore">Backup e ripristino</string> <string name="backup_restore">Backup e ripristino</string>
<string name="restart_required">Riavvio richiesto</string>
<string name="black_dark_theme_summary">Utile per gli schermi AMOLED</string> <string name="black_dark_theme_summary">Utile per gli schermi AMOLED</string>
<string name="black_dark_theme">Tema nero scuro</string> <string name="black_dark_theme">Tema nero scuro</string>
<string name="report_github">Segnala un problema su GitHub</string> <string name="report_github">Segnala un problema su GitHub</string>
<string name="create_category">Nuova categoria</string> <string name="create_category">Nuova categoria</string>
<string name="prefer_rtl_reader_summary">Puoi impostare la modalità di lettura per ogni manga separatamente</string>
<string name="prefer_rtl_reader">Preferisci la lettura da destra a sinistra</string>
<string name="right_to_left">Da destra a sinistra</string> <string name="right_to_left">Da destra a sinistra</string>
<string name="no_update_available">Nessun aggiornamento disponibile</string> <string name="no_update_available">Nessun aggiornamento disponibile</string>
<string name="update_check_failed">Controllo dell\'aggiornamento fallito</string> <string name="update_check_failed">Controllo dell\'aggiornamento fallito</string>
@@ -278,4 +275,23 @@
<string name="download_slowdown_summary">Aiuta ad evitare il blocco del tuo indirizzo IP</string> <string name="download_slowdown_summary">Aiuta ad evitare il blocco del tuo indirizzo IP</string>
<string name="hide">Nascondi</string> <string name="hide">Nascondi</string>
<string name="new_sources_text">Sono disponibili nuove fonti di manga</string> <string name="new_sources_text">Sono disponibili nuove fonti di manga</string>
<string name="show_notification_new_chapters_on">Riceverai notifiche sugli aggiornamenti del manga che stai leggendo</string>
<string name="notifications_enable">Abilita le notifiche</string>
<string name="show_notification_new_chapters_off">Non riceverai notifiche ma i nuovi capitoli saranno evidenziati nelle liste</string>
<string name="empty_favourite_categories">Nessuna categoria preferita</string>
<string name="name">Nome</string>
<string name="edit">Modifica</string>
<string name="edit_category">Modifica la categoria</string>
<string name="check_new_chapters_title">Controlla i nuovi capitoli e notificarli</string>
<string name="bookmarks">Segnalibri</string>
<string name="removed_from_history">Rimosso dalla cronologia</string>
<string name="bookmark_remove">Rimuovi il segnalibro</string>
<string name="bookmark_add">Aggiungi un segnalibro</string>
<string name="bookmark_removed">Segnalibro rimosso</string>
<string name="bookmark_added">Segnalibro aggiunto</string>
<string name="undo">Annulla</string>
<string name="default_mode">Modalità predefinita</string>
<string name="detect_reader_mode">Modalità di lettura a rilevamento automatico</string>
<string name="dns_over_https">DNS su HTTPS</string>
<string name="detect_reader_mode_summary">Rileva automaticamente se il manga è un webtoon</string>
</resources> </resources>

View File

@@ -159,7 +159,6 @@
<string name="update_check_failed">アップデートを確認する事が出来ませんでした</string> <string name="update_check_failed">アップデートを確認する事が出来ませんでした</string>
<string name="no_update_available">利用可能なアップデートはありません</string> <string name="no_update_available">利用可能なアップデートはありません</string>
<string name="right_to_left">右から左(←)</string> <string name="right_to_left">右から左(←)</string>
<string name="prefer_rtl_reader">右から左(←)の読書を好む</string>
<string name="about_feedback">フィードバック</string> <string name="about_feedback">フィードバック</string>
<string name="about_feedback_4pda">4PDAに関する話題</string> <string name="about_feedback_4pda">4PDAに関する話題</string>
<string name="auth_complete">承認済み</string> <string name="auth_complete">承認済み</string>
@@ -222,8 +221,6 @@
<string name="exclude_nsfw_from_history">NSFW漫画を履歴から除外する</string> <string name="exclude_nsfw_from_history">NSFW漫画を履歴から除外する</string>
<string name="queued">キュー</string> <string name="queued">キュー</string>
<string name="cookies_cleared">全てのCookieが削除されました</string> <string name="cookies_cleared">全てのCookieが削除されました</string>
<string name="prefer_rtl_reader_summary">読み取りモードはシリーズごとに設定できます</string>
<string name="restart_required">再起動が必要です</string>
<string name="tracker_warning">一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。</string> <string name="tracker_warning">一部のデバイスはシステムでの動作が異なり、バックグラウンドタスクが中断される可能性があります。</string>
<string name="genres">ジャンル</string> <string name="genres">ジャンル</string>
<string name="scale_mode">スケールモード</string> <string name="scale_mode">スケールモード</string>
@@ -278,4 +275,23 @@
<string name="chapters_will_removed_background">チャプターはバックグラウンドで削除されます。時間がかかる場合があります</string> <string name="chapters_will_removed_background">チャプターはバックグラウンドで削除されます。時間がかかる場合があります</string>
<string name="hide">隠す</string> <string name="hide">隠す</string>
<string name="new_sources_text">新しいマンガソースが利用可能になりました</string> <string name="new_sources_text">新しいマンガソースが利用可能になりました</string>
<string name="check_new_chapters_title">新着チャプターの確認とお知らせ</string>
<string name="show_notification_new_chapters_on">読んでいるマンガの更新情報をお知らせします</string>
<string name="notifications_enable">通知を有効にする</string>
<string name="show_notification_new_chapters_off">通知はありませんが、新しいチャプターはリストでハイライト表示されます</string>
<string name="name">名称</string>
<string name="edit">編集</string>
<string name="edit_category">カテゴリーを編集する</string>
<string name="empty_favourite_categories">お気に入りのカテゴリーはありません</string>
<string name="bookmarks">ブックマーク</string>
<string name="bookmark_removed">ブックマーク削除</string>
<string name="undo">元に戻す</string>
<string name="removed_from_history">履歴から削除</string>
<string name="bookmark_add">ブックマークの追加</string>
<string name="bookmark_remove">ブックマークの削除</string>
<string name="bookmark_added">ブックマークを追加</string>
<string name="dns_over_https">HTTPS 経由の DNS</string>
<string name="detect_reader_mode">リーダーモードの自動検出</string>
<string name="default_mode">デフォルトモード</string>
<string name="detect_reader_mode_summary">マンガがウェブトゥーンかどうかを自動判定</string>
</resources> </resources>

View File

@@ -26,9 +26,7 @@
<string name="zoom_mode_fit_center">Tilpass sentrum</string> <string name="zoom_mode_fit_center">Tilpass sentrum</string>
<string name="scale_mode">Skaleringsmodus</string> <string name="scale_mode">Skaleringsmodus</string>
<string name="report_github">Opprett feilrapport på GitHub</string> <string name="report_github">Opprett feilrapport på GitHub</string>
<string name="prefer_rtl_reader_summary">Lesemodus kan settes opp for hver serie</string>
<string name="right_to_left">Høyre-til-venstre (←)</string> <string name="right_to_left">Høyre-til-venstre (←)</string>
<string name="prefer_rtl_reader">Foretrekk høyre-til-venstre (←)-leser</string>
<string name="no_update_available">Ingen tilgjengelige oppdateringer</string> <string name="no_update_available">Ingen tilgjengelige oppdateringer</string>
<string name="update_check_failed">Kunne ikke se etter oppdateringer</string> <string name="update_check_failed">Kunne ikke se etter oppdateringer</string>
<string name="checking_for_updates">Ser etter oppdateringer …</string> <string name="checking_for_updates">Ser etter oppdateringer …</string>
@@ -104,7 +102,6 @@
<string name="data_restored">Data gjenopprettet</string> <string name="data_restored">Data gjenopprettet</string>
<string name="restore_backup">Gjenopprett fra sikkerhetskopi</string> <string name="restore_backup">Gjenopprett fra sikkerhetskopi</string>
<string name="create_backup">Opprett sikkerhetskopi</string> <string name="create_backup">Opprett sikkerhetskopi</string>
<string name="restart_required">Omstart kreves</string>
<string name="black_dark_theme_summary">Bruker mindre strøm på AMOLED-skjermer</string> <string name="black_dark_theme_summary">Bruker mindre strøm på AMOLED-skjermer</string>
<string name="black_dark_theme">Svart</string> <string name="black_dark_theme">Svart</string>
<string name="create_category">Ny kategori</string> <string name="create_category">Ny kategori</string>

View File

@@ -7,5 +7,6 @@
<color name="onErrorContainer">#FFDAD4</color> <color name="onErrorContainer">#FFDAD4</color>
<color name="scrollbar">#66FFFFFF</color> <color name="scrollbar">#66FFFFFF</color>
<color name="selector_foreground">#29FFFFFF</color> <color name="selector_foreground">#29FFFFFF</color>
<color name="divider_default">#1FFFFFFF</color>
</resources> </resources>

View File

@@ -3,9 +3,12 @@
<style name="ThemeOverlay.Kotatsu" parent="ThemeOverlay.Material3.Dark" /> <style name="ThemeOverlay.Kotatsu" parent="ThemeOverlay.Material3.Dark" />
<!--== AMOLED Mode Overlay ==--> <style name="Theme.Kotatsu.Amoled">
<style name="ThemeOverlay.Kotatsu.AMOLED" parent=""> <item name="colorSurface">@color/surface_amoled</item>
<!-- Theme Colors --> <item name="android:colorBackground">@color/background_amoled</item>
</style>
<style name="Theme.Kotatsu.Monet.Amoled">
<item name="colorSurface">@color/surface_amoled</item> <item name="colorSurface">@color/surface_amoled</item>
<item name="android:colorBackground">@color/background_amoled</item> <item name="android:colorBackground">@color/background_amoled</item>
</style> </style>

View File

@@ -140,8 +140,6 @@
<string name="about">Sobre</string> <string name="about">Sobre</string>
<string name="checking_for_updates">Verificando atualizações…</string> <string name="checking_for_updates">Verificando atualizações…</string>
<string name="update_check_failed">Não foi possível procurar atualizações</string> <string name="update_check_failed">Não foi possível procurar atualizações</string>
<string name="prefer_rtl_reader">Prefira o leitor da direita para a esquerda (←)</string>
<string name="prefer_rtl_reader_summary">O modo de leitura pode ser configurado separadamente para cada série</string>
<string name="backup_information">Você pode criar backup de seu histórico e favoritos e restaurá-lo</string> <string name="backup_information">Você pode criar backup de seu histórico e favoritos e restaurá-lo</string>
<string name="just_now">Agora mesmo</string> <string name="just_now">Agora mesmo</string>
<string name="yesterday">Ontem</string> <string name="yesterday">Ontem</string>
@@ -242,7 +240,6 @@
<string name="create_backup">Criar backup de dados</string> <string name="create_backup">Criar backup de dados</string>
<string name="text_local_holder_secondary">Salve-o de fontes online ou importe arquivos.</string> <string name="text_local_holder_secondary">Salve-o de fontes online ou importe arquivos.</string>
<string name="check_for_updates">Verifique se há atualizações</string> <string name="check_for_updates">Verifique se há atualizações</string>
<string name="restart_required">É necessário reiniciar</string>
<string name="text_feed_holder">Novos capítulos do que você está lendo são mostrados aqui</string> <string name="text_feed_holder">Novos capítulos do que você está lendo são mostrados aqui</string>
<string name="app_version">Versão %s</string> <string name="app_version">Versão %s</string>
<string name="zoom_mode_fit_width">Ajustar à largura</string> <string name="zoom_mode_fit_width">Ajustar à largura</string>
@@ -278,4 +275,23 @@
<string name="chapters_will_removed_background">Os capítulos serão removidos em segundo plano. Pode levar algum tempo</string> <string name="chapters_will_removed_background">Os capítulos serão removidos em segundo plano. Pode levar algum tempo</string>
<string name="parallel_downloads">Downloads paralelos</string> <string name="parallel_downloads">Downloads paralelos</string>
<string name="new_sources_text">Novas fontes de mangá estão disponíveis</string> <string name="new_sources_text">Novas fontes de mangá estão disponíveis</string>
<string name="check_new_chapters_title">Verifique se há novos capítulos e notifique sobre isso</string>
<string name="show_notification_new_chapters_on">Você receberá notificações sobre atualizações do mangá que está lendo</string>
<string name="edit_category">Editar categoria</string>
<string name="empty_favourite_categories">Nenhuma categoria favorita</string>
<string name="bookmark_add">Adicionar marcador</string>
<string name="bookmark_remove">Remover marcador</string>
<string name="bookmarks">Marcadores</string>
<string name="bookmark_added">Marcador adicionado</string>
<string name="show_notification_new_chapters_off">Você não receberá notificações, mas novos capítulos serão destacados nas listas</string>
<string name="notifications_enable">Ativar notificações</string>
<string name="name">Nome</string>
<string name="edit">Editar</string>
<string name="bookmark_removed">Marcador removido</string>
<string name="undo">Desfazer</string>
<string name="removed_from_history">Removido do histórico</string>
<string name="dns_over_https">DNS sobre HTTPS</string>
<string name="default_mode">Modo padrão</string>
<string name="detect_reader_mode">Detecção automática do modo de leitura</string>
<string name="detect_reader_mode_summary">Detectar automaticamente se o mangá é webtoon</string>
</resources> </resources>

View File

@@ -139,7 +139,6 @@
<string name="scale_mode">Modo de escala</string> <string name="scale_mode">Modo de escala</string>
<string name="zoom_mode_fit_center">Centro de ajuste</string> <string name="zoom_mode_fit_center">Centro de ajuste</string>
<string name="zoom_mode_fit_width">Ajustar à largura</string> <string name="zoom_mode_fit_width">Ajustar à largura</string>
<string name="restart_required">É necessário reiniciar</string>
<string name="backup_restore">Backup e restauração</string> <string name="backup_restore">Backup e restauração</string>
<string name="create_backup">Criar backup de dados</string> <string name="create_backup">Criar backup de dados</string>
<string name="restore_backup">Restaurar do backup</string> <string name="restore_backup">Restaurar do backup</string>
@@ -201,7 +200,6 @@
<string name="recent_manga">Recente</string> <string name="recent_manga">Recente</string>
<string name="other_storage">Outro armazenamento</string> <string name="other_storage">Outro armazenamento</string>
<string name="text_search_holder_secondary">Tente reformular a consulta.</string> <string name="text_search_holder_secondary">Tente reformular a consulta.</string>
<string name="prefer_rtl_reader">Prefira o leitor da direita para a esquerda (←)</string>
<string name="not_available">Não disponível</string> <string name="not_available">Não disponível</string>
<string name="size_s">Tamanho: %s</string> <string name="size_s">Tamanho: %s</string>
<string name="text_history_holder_primary">O que você ler será exibido aqui</string> <string name="text_history_holder_primary">O que você ler será exibido aqui</string>
@@ -228,7 +226,6 @@
<string name="text_clear_search_history_prompt">Remover todas as consultas de pesquisa recentes permanentemente\?</string> <string name="text_clear_search_history_prompt">Remover todas as consultas de pesquisa recentes permanentemente\?</string>
<string name="auth_required">Faça login para ver este conteúdo</string> <string name="auth_required">Faça login para ver este conteúdo</string>
<string name="text_categories_holder">Você pode usar categorias para organizar seus favoritos. Pressione «+» para criar uma categoria</string> <string name="text_categories_holder">Você pode usar categorias para organizar seus favoritos. Pressione «+» para criar uma categoria</string>
<string name="prefer_rtl_reader_summary">O modo de leitura pode ser configurado separadamente para cada série</string>
<string name="manga_save_location">Pasta para downloads</string> <string name="manga_save_location">Pasta para downloads</string>
<string name="exclude_nsfw_from_history">Excluir mangá NSFW do histórico</string> <string name="exclude_nsfw_from_history">Excluir mangá NSFW do histórico</string>
<string name="date_format">Formato da data</string> <string name="date_format">Formato da data</string>

View File

@@ -159,8 +159,6 @@
<string name="update_check_failed">Не удалось проверить обновления</string> <string name="update_check_failed">Не удалось проверить обновления</string>
<string name="no_update_available">Нет доступных обновлений</string> <string name="no_update_available">Нет доступных обновлений</string>
<string name="right_to_left">Справа налево (←)</string> <string name="right_to_left">Справа налево (←)</string>
<string name="prefer_rtl_reader">Предпочитать читать справа налево (←)</string>
<string name="prefer_rtl_reader_summary">Режим чтения может быть настроен отдельно для каждой серии</string>
<string name="create_category">Создать категорию</string> <string name="create_category">Создать категорию</string>
<string name="scale_mode">Масштабирование</string> <string name="scale_mode">Масштабирование</string>
<string name="zoom_mode_fit_center">Вписать в экран</string> <string name="zoom_mode_fit_center">Вписать в экран</string>
@@ -169,7 +167,6 @@
<string name="zoom_mode_keep_start">Исходный размер</string> <string name="zoom_mode_keep_start">Исходный размер</string>
<string name="black_dark_theme">Чёрная</string> <string name="black_dark_theme">Чёрная</string>
<string name="black_dark_theme_summary">Потребляет меньше энергии на экранах AMOLED</string> <string name="black_dark_theme_summary">Потребляет меньше энергии на экранах AMOLED</string>
<string name="restart_required">Требуется перезапуск</string>
<string name="backup_restore">Резервное копирование и восстановление</string> <string name="backup_restore">Резервное копирование и восстановление</string>
<string name="create_backup">Создать резервную копию</string> <string name="create_backup">Создать резервную копию</string>
<string name="restore_backup">Восстановить данные</string> <string name="restore_backup">Восстановить данные</string>

View File

@@ -129,7 +129,7 @@
<string name="sign_in">Logga in</string> <string name="sign_in">Logga in</string>
<string name="auth_required">Logga in för att visa innehåll</string> <string name="auth_required">Logga in för att visa innehåll</string>
<string name="default_s">Standard: %s</string> <string name="default_s">Standard: %s</string>
<string name="_and_x_more">...och %1$d till</string> <string name="_and_x_more">och %1$d till</string>
<string name="next">Nästa</string> <string name="next">Nästa</string>
<string name="password_length_hint">Lösenordet måste vara minst 4 tecken</string> <string name="password_length_hint">Lösenordet måste vara minst 4 tecken</string>
<string name="search_only_on_s">Sök endast på %s</string> <string name="search_only_on_s">Sök endast på %s</string>
@@ -243,13 +243,10 @@
<string name="zoom_mode_fit_center">Centrera</string> <string name="zoom_mode_fit_center">Centrera</string>
<string name="zoom_mode_fit_height">Anpassa mot höjd</string> <string name="zoom_mode_fit_height">Anpassa mot höjd</string>
<string name="zoom_mode_keep_start">Anpassa till start</string> <string name="zoom_mode_keep_start">Anpassa till start</string>
<string name="prefer_rtl_reader">Föredra höger-till-vänster (←) läsare</string>
<string name="preparing_">Förbereder…</string> <string name="preparing_">Förbereder…</string>
<string name="prefer_rtl_reader_summary">Läsläge kan sättas up separat för varje serie</string>
<string name="zoom_mode_fit_width">Anpassa mot bredd</string> <string name="zoom_mode_fit_width">Anpassa mot bredd</string>
<string name="black_dark_theme">Svart</string> <string name="black_dark_theme">Svart</string>
<string name="black_dark_theme_summary">Använder mindre ström på AMOLED-skärmar</string> <string name="black_dark_theme_summary">Använder mindre ström på AMOLED-skärmar</string>
<string name="restart_required">Omstart krävs</string>
<string name="backup_restore">Säkerhetskopiering och återställning</string> <string name="backup_restore">Säkerhetskopiering och återställning</string>
<string name="create_backup">Skapa säkerhetskopia</string> <string name="create_backup">Skapa säkerhetskopia</string>
<string name="data_restored">Återställd</string> <string name="data_restored">Återställd</string>

View File

@@ -32,7 +32,7 @@
<string name="processing_">İşleniyor…</string> <string name="processing_">İşleniyor…</string>
<string name="download_complete">İndirildi</string> <string name="download_complete">İndirildi</string>
<string name="downloads">İndirilenler</string> <string name="downloads">İndirilenler</string>
<string name="by_name">İsim</string> <string name="by_name">Ad</string>
<string name="updated">Güncellenme</string> <string name="updated">Güncellenme</string>
<string name="newest">Yeniler</string> <string name="newest">Yeniler</string>
<string name="by_rating">Puanlama</string> <string name="by_rating">Puanlama</string>
@@ -121,7 +121,6 @@
<string name="clear_search_history">Arama geçmişini temizle</string> <string name="clear_search_history">Arama geçmişini temizle</string>
<string name="text_empty_holder_primary">Burası biraz boş…</string> <string name="text_empty_holder_primary">Burası biraz boş…</string>
<string name="rotate_screen">Ekranı döndür</string> <string name="rotate_screen">Ekranı döndür</string>
<string name="prefer_rtl_reader_summary">Okuma modu her seri için ayrı bir şekilde ayarlanabilir</string>
<string name="scale_mode">Ölçek modu</string> <string name="scale_mode">Ölçek modu</string>
<string name="zoom_mode_fit_height">Yüksekliğe sığdır</string> <string name="zoom_mode_fit_height">Yüksekliğe sığdır</string>
<string name="black_dark_theme">Siyah</string> <string name="black_dark_theme">Siyah</string>
@@ -203,7 +202,6 @@
<string name="long_ago">Uzun zaman önce</string> <string name="long_ago">Uzun zaman önce</string>
<string name="today">Bugün</string> <string name="today">Bugün</string>
<string name="no_update_available">Güncelleme yok</string> <string name="no_update_available">Güncelleme yok</string>
<string name="restart_required">Yeniden başlatma gerekli</string>
<string name="chapters_checking_progress">Yeni bölümler denetleniyor: %1$d / %2$d</string> <string name="chapters_checking_progress">Yeni bölümler denetleniyor: %1$d / %2$d</string>
<string name="dynamic_theme">Dinamik tema</string> <string name="dynamic_theme">Dinamik tema</string>
<string name="text_categories_holder">Favorilerinizi düzenlemek için kategorileri kullanabilirsiniz. Kategori oluşturmak için «+» düğmesine basın</string> <string name="text_categories_holder">Favorilerinizi düzenlemek için kategorileri kullanabilirsiniz. Kategori oluşturmak için «+» düğmesine basın</string>
@@ -278,4 +276,23 @@
<string name="local_manga_processing">Kaydedilen manga işleme</string> <string name="local_manga_processing">Kaydedilen manga işleme</string>
<string name="hide">Gizle</string> <string name="hide">Gizle</string>
<string name="new_sources_text">Yeni manga kaynakları var</string> <string name="new_sources_text">Yeni manga kaynakları var</string>
<string name="show_notification_new_chapters_off">Bildirim almayacaksınız ancak yeni bölümler listelerde vurgulanacak</string>
<string name="notifications_enable">Bildirimleri etkinleştir</string>
<string name="check_new_chapters_title">Yeni bölümleri denetle ve bildirim gönder</string>
<string name="show_notification_new_chapters_on">Okuduğunuz manga güncellemeleri hakkında bildirim alacaksınız</string>
<string name="empty_favourite_categories">Favori kategori yok</string>
<string name="name">Ad</string>
<string name="edit">Düzenle</string>
<string name="edit_category">Kategoriyi düzenle</string>
<string name="bookmark_add">Yer imi ekle</string>
<string name="bookmark_remove">Yer imini kaldır</string>
<string name="bookmarks">Yer imleri</string>
<string name="bookmark_removed">Yer imi kaldırıldı</string>
<string name="bookmark_added">Yer imi eklendi</string>
<string name="undo">Geri al</string>
<string name="removed_from_history">Geçmişten kaldırıldı</string>
<string name="dns_over_https">HTTPS üzerinden DNS</string>
<string name="detect_reader_mode">Okuyucu modunu otomatik algıla</string>
<string name="detect_reader_mode_summary">Manganın webtoon olup olmadığını otomatik olarak algıla</string>
<string name="default_mode">Öntanımlı mod</string>
</resources> </resources>

View File

@@ -2,7 +2,7 @@
<resources> <resources>
<plurals name="new_chapters"> <plurals name="new_chapters">
<item quantity="one">%1$d новий розділ</item> <item quantity="one">%1$d новий розділ</item>
<item quantity="few">%1$d нових розділи</item> <item quantity="few">%1$d нові розділи</item>
<item quantity="many">%1$d нових розділів</item> <item quantity="many">%1$d нових розділів</item>
<item quantity="other">%1$d нових розділів</item> <item quantity="other">%1$d нових розділів</item>
</plurals> </plurals>

View File

@@ -64,7 +64,7 @@
<string name="cache">Кеш</string> <string name="cache">Кеш</string>
<string name="text_file_sizes">Б|кБ|МБ|ГБ|ТБ</string> <string name="text_file_sizes">Б|кБ|МБ|ГБ|ТБ</string>
<string name="standard">Стандартний</string> <string name="standard">Стандартний</string>
<string name="webtoon">Манхва</string> <string name="webtoon">Вебтун</string>
<string name="read_mode">Режим читання</string> <string name="read_mode">Режим читання</string>
<string name="grid_size">Розмір сітки</string> <string name="grid_size">Розмір сітки</string>
<string name="search_on_s">Пошук по %s</string> <string name="search_on_s">Пошук по %s</string>
@@ -89,7 +89,6 @@
<string name="notifications">Сповіщення</string> <string name="notifications">Сповіщення</string>
<string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Увімкнено %1$d з %2$d</string> <string name="enabled_d_of_d" tools:ignore="PluralsCandidate">Увімкнено %1$d з %2$d</string>
<string name="new_chapters">Нові розділи</string> <string name="new_chapters">Нові розділи</string>
<string name="show_notification_new_chapters">Повідомляти про оновлення манґи, яку Ви читаєте</string>
<string name="download">Завантажити</string> <string name="download">Завантажити</string>
<string name="read_from_start">Читати з початку</string> <string name="read_from_start">Читати з початку</string>
<string name="restart">Перезавантажити</string> <string name="restart">Перезавантажити</string>
@@ -136,7 +135,6 @@
<string name="checking_for_updates">Перевірка наявності оновлень…</string> <string name="checking_for_updates">Перевірка наявності оновлень…</string>
<string name="update_check_failed">Не вдалося перевірити оновлення</string> <string name="update_check_failed">Не вдалося перевірити оновлення</string>
<string name="no_update_available">Немає доступних оновлень</string> <string name="no_update_available">Немає доступних оновлень</string>
<string name="prefer_rtl_reader">Віддавати перевагу читанню справа наліво (←)</string>
<string name="create_category">Нова категорія</string> <string name="create_category">Нова категорія</string>
<string name="scale_mode">Режим масштабування</string> <string name="scale_mode">Режим масштабування</string>
<string name="zoom_mode_fit_center">Вмістити в екран</string> <string name="zoom_mode_fit_center">Вмістити в екран</string>
@@ -145,7 +143,6 @@
<string name="zoom_mode_keep_start">Вихідний розмір</string> <string name="zoom_mode_keep_start">Вихідний розмір</string>
<string name="black_dark_theme">Чорна</string> <string name="black_dark_theme">Чорна</string>
<string name="black_dark_theme_summary">Споживає менше енергії на екранах AMOLED</string> <string name="black_dark_theme_summary">Споживає менше енергії на екранах AMOLED</string>
<string name="restart_required">Потрібен перезапуск</string>
<string name="backup_restore">Резервне копіювання та відновлення</string> <string name="backup_restore">Резервне копіювання та відновлення</string>
<string name="data_restored">Відновлено</string> <string name="data_restored">Відновлено</string>
<string name="preparing_">Підготовка…</string> <string name="preparing_">Підготовка…</string>
@@ -166,7 +163,7 @@
<string name="sign_in">Увійти</string> <string name="sign_in">Увійти</string>
<string name="auth_required">Увійдіть, щоб переглянути цей вміст</string> <string name="auth_required">Увійдіть, щоб переглянути цей вміст</string>
<string name="default_s">За замовчуванням: %s</string> <string name="default_s">За замовчуванням: %s</string>
<string name="_and_x_more">...і ще %1$d</string> <string name="_and_x_more">і ще %1$d</string>
<string name="next">Далі</string> <string name="next">Далі</string>
<string name="protect_application_subtitle">Введіть пароль для запуску програми</string> <string name="protect_application_subtitle">Введіть пароль для запуску програми</string>
<string name="confirm">Підтвердити</string> <string name="confirm">Підтвердити</string>
@@ -252,7 +249,6 @@
<string name="text_categories_holder">Ви можете використовувати категорії для впорядкування своїх уподобань. Натисніть «+», щоб створити категорію</string> <string name="text_categories_holder">Ви можете використовувати категорії для впорядкування своїх уподобань. Натисніть «+», щоб створити категорію</string>
<string name="yesterday">Учора</string> <string name="yesterday">Учора</string>
<string name="right_to_left">Справа наліво (←)</string> <string name="right_to_left">Справа наліво (←)</string>
<string name="prefer_rtl_reader_summary">Режим читання можна налаштувати окремо для кожної серії</string>
<string name="create_backup">Створити резервну копію</string> <string name="create_backup">Створити резервну копію</string>
<string name="restore_backup">Відновити з резервної копії</string> <string name="restore_backup">Відновити з резервної копії</string>
<string name="data_restored_success">Всі дані були відновлені</string> <string name="data_restored_success">Всі дані були відновлені</string>
@@ -279,4 +275,23 @@
<string name="suggestions_excluded_genres_summary">Укажіть жанри, які ви не хочете бачити в пропозиціях</string> <string name="suggestions_excluded_genres_summary">Укажіть жанри, які ви не хочете бачити в пропозиціях</string>
<string name="download_slowdown_summary">Допомагає уникнути блокування вашої IP-адреси</string> <string name="download_slowdown_summary">Допомагає уникнути блокування вашої IP-адреси</string>
<string name="chapters_will_removed_background">Розділи будуть видалені у фоновому режимі. Це може зайняти деякий час</string> <string name="chapters_will_removed_background">Розділи будуть видалені у фоновому режимі. Це може зайняти деякий час</string>
<string name="check_new_chapters_title">Перевіряти наявність нових розділів і повідомляти про них</string>
<string name="show_notification_new_chapters_on">Ви будете отримувати повідомлення про оновлення манґи, яку ви читаєте</string>
<string name="notifications_enable">Увімкнути сповіщення</string>
<string name="show_notification_new_chapters_off">Ви не будете отримувати повідомлення, але нові розділи будуть відображатися у списку</string>
<string name="empty_favourite_categories">Немає улюблених категорій</string>
<string name="name">Назва</string>
<string name="edit">Змінити</string>
<string name="edit_category">Змінити категорію</string>
<string name="bookmark_add">Додати закладку</string>
<string name="bookmark_remove">Видалити закладку</string>
<string name="bookmarks">Закладки</string>
<string name="bookmark_removed">Закладка видалена</string>
<string name="bookmark_added">Додано закладку</string>
<string name="undo">Скасувати</string>
<string name="removed_from_history">Видалено з історії</string>
<string name="dns_over_https">DNS через HTTPS</string>
<string name="default_mode">Типовий режим</string>
<string name="detect_reader_mode_summary">Автоматично визначати, чи є манга вебтуном</string>
<string name="detect_reader_mode">Автовизначення режиму читання</string>
</resources> </resources>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.DayNight.BottomSheetDialog">
<item name="android:navigationBarColor">@color/navigation_bar_scrim</item>
<item name="android:windowLightNavigationBar">@bool/light_navigation_bar</item>
<item name="colorControlHighlight">?colorSecondary</item>
</style>
</resources>

View File

@@ -3,4 +3,5 @@
<dimen name="grid_spacing">6dp</dimen> <dimen name="grid_spacing">6dp</dimen>
<dimen name="grid_spacing_outer">2dp</dimen> <dimen name="grid_spacing_outer">2dp</dimen>
<dimen name="preferred_grid_width">140dp</dimen> <dimen name="preferred_grid_width">140dp</dimen>
<dimen name="bottom_sheet_width">420dp</dimen>
</resources> </resources>

View File

@@ -20,5 +20,6 @@
<color name="dim">#99000000</color> <color name="dim">#99000000</color>
<color name="scrollbar">#66000000</color> <color name="scrollbar">#66000000</color>
<color name="selector_foreground">#29000000</color> <color name="selector_foreground">#29000000</color>
<color name="divider_default">#1F000000</color>
</resources> </resources>

View File

@@ -26,4 +26,7 @@
<dimen name="search_suggestions_manga_height">124dp</dimen> <dimen name="search_suggestions_manga_height">124dp</dimen>
<dimen name="search_suggestions_manga_spacing">4dp</dimen> <dimen name="search_suggestions_manga_spacing">4dp</dimen>
<dimen name="bottom_sheet_width">0dp</dimen>
<dimen name="dialog_radius">8dp</dimen>
</resources> </resources>

View File

@@ -168,7 +168,6 @@
<string name="zoom_mode_keep_start">Keep at start</string> <string name="zoom_mode_keep_start">Keep at start</string>
<string name="black_dark_theme">Black</string> <string name="black_dark_theme">Black</string>
<string name="black_dark_theme_summary">Uses less power on AMOLED screens</string> <string name="black_dark_theme_summary">Uses less power on AMOLED screens</string>
<string name="restart_required">Restart required</string>
<string name="backup_restore">Backup and restore</string> <string name="backup_restore">Backup and restore</string>
<string name="create_backup">Create data backup</string> <string name="create_backup">Create data backup</string>
<string name="restore_backup">Restore from backup</string> <string name="restore_backup">Restore from backup</string>

View File

@@ -22,9 +22,26 @@
<!-- Bottom sheet --> <!-- Bottom sheet -->
<style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.DayNight.BottomSheetDialog"> <style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
<item name="android:statusBarColor">@color/dim</item> <item name="bottomSheetStyle">@style/Widget.Kotatsu.BottomSheet.Modal</item>
<item name="colorControlHighlight">?colorSecondary</item> <item name="android:windowAnimationStyle">@style/Animation.Kotatsu.BottomSheetDialog</item>
</style>
<style name="Widget.Kotatsu.BottomSheet.Modal" parent="Widget.Material3.BottomSheet.Modal">
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay.Kotatsu.BottomSheet</item>
</style>
<style name="ShapeAppearanceOverlay.Kotatsu.BottomSheet" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">@dimen/dialog_radius</item>
<item name="cornerSizeTopLeft">@dimen/dialog_radius</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
<style name="Animation.Kotatsu.BottomSheetDialog" parent="Animation.AppCompat.Dialog">
<item name="android:windowEnterAnimation">@anim/bottom_sheet_slide_in</item>
<item name="android:windowExitAnimation">@anim/bottom_sheet_slide_out</item>
</style> </style>
<!-- Widget styles --> <!-- Widget styles -->

View File

@@ -35,6 +35,8 @@
<item name="colorErrorContainer">@color/errorContainer</item> <item name="colorErrorContainer">@color/errorContainer</item>
<item name="colorOnErrorContainer">@color/onErrorContainer</item> <item name="colorOnErrorContainer">@color/onErrorContainer</item>
<item name="android:divider">@color/divider_default</item>
<!-- Ripples --> <!-- Ripples -->
<item name="colorControlHighlight">?attr/colorSurfaceVariant</item> <item name="colorControlHighlight">?attr/colorSurfaceVariant</item>
@@ -86,9 +88,11 @@
<!-- Monet theme only support S+ --> <!-- Monet theme only support S+ -->
<style name="Theme.Kotatsu.Monet" /> <style name="Theme.Kotatsu.Monet" />
<style name="ThemeOverlay.Kotatsu" parent="ThemeOverlay.Material3.Light" /> <style name="Theme.Kotatsu.Amoled" />
<style name="ThemeOverlay.Kotatsu.AMOLED" parent="" /> <style name="Theme.Kotatsu.Monet.Amoled" />
<style name="ThemeOverlay.Kotatsu" parent="ThemeOverlay.Material3.Light" />
<style name="Theme.Kotatsu.Dialog" parent=""> <style name="Theme.Kotatsu.Dialog" parent="">
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>