Misc fixes

This commit is contained in:
Koitharu
2020-12-16 17:48:26 +02:00
parent 113cde2f07
commit 0931e4e0e6
30 changed files with 130 additions and 420 deletions

View File

@@ -16,7 +16,7 @@ android {
minSdkVersion 21
targetSdkVersion 30
versionCode gitCommits
versionName '1.0-a1'
versionName '1.0-b1'
kapt {
arguments {

View File

@@ -31,7 +31,6 @@ abstract class BaseFullscreenActivity<B : ViewBinding> : BaseActivity<B>() {
protected fun hideSystemUI() {
insetsControllerCompat.hide(WindowInsetsCompat.Type.systemBars())
}
protected fun showSystemUI() {

View File

@@ -27,6 +27,8 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.MangaIntent
import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.browser.BrowserActivity
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.databinding.ActivityDetailsBinding
@@ -71,12 +73,19 @@ class DetailsActivity : BaseActivity<ActivityDetailsBinding>(),
}
private fun onError(e: Throwable) {
if (viewModel.manga.value == null) {
Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
finishAfterTransition()
} else {
Snackbar.make(binding.pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG)
.show()
when {
e is CloudFlareProtectedException -> {
CloudFlareDialog.newInstance(e.url)
.show(supportFragmentManager, CloudFlareDialog.TAG)
}
viewModel.manga.value == null -> {
Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
finishAfterTransition()
}
else -> {
Snackbar.make(binding.pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG)
.show()
}
}
}

View File

@@ -51,9 +51,9 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
(savedInstanceState?.getParcelable(KEY_ADAPTER_STATE) ?: adapterState)?.let {
(binding.pager.adapter as FavouritesPagerAdapter).restoreState(it)
}
// (savedInstanceState?.getParcelable(KEY_ADAPTER_STATE) ?: adapterState)?.let {
// (binding.pager.adapter as FavouritesPagerAdapter).restoreState(it)
// }
}
override fun onDestroyView() {

View File

@@ -30,7 +30,7 @@ class CategoriesEditDelegate(
.setHint(R.string.enter_category_name)
.setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
.setNegativeButton(android.R.string.cancel)
.setMaxLength(12, false)
.setMaxLength(MAX_TITLE_LENGTH, false)
.setPositiveButton(R.string.rename) { _, name ->
callback.onRenameCategory(category, name)
}.create()
@@ -43,7 +43,7 @@ class CategoriesEditDelegate(
.setHint(R.string.enter_category_name)
.setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
.setNegativeButton(android.R.string.cancel)
.setMaxLength(12, false)
.setMaxLength(MAX_TITLE_LENGTH, false)
.setPositiveButton(R.string.add) { _, name ->
callback.onCreateCategory(name)
}.create()
@@ -58,4 +58,9 @@ class CategoriesEditDelegate(
fun onCreateCategory(name: String)
}
private companion object {
const val MAX_TITLE_LENGTH = 24
}
}

View File

@@ -1,217 +0,0 @@
package org.koitharu.kotatsu.list.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.snackbar.Snackbar
import org.koin.android.ext.android.get
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener
import org.koitharu.kotatsu.base.ui.list.decor.SpacingItemDecoration
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.databinding.SheetListBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.utils.ext.*
abstract class MangaListSheet : BaseBottomSheet<SheetListBinding>(),
PaginationScrollListener.Callback, OnListItemClickListener<Manga>,
Toolbar.OnMenuItemClickListener {
private var listAdapter: MangaListAdapter? = null
private var paginationListener: PaginationScrollListener? = null
private val spanResolver = MangaListSpanResolver()
private val spanSizeLookup = SpanSizeLookup()
open val isSwipeRefreshEnabled = true
protected abstract val viewModel: MangaListViewModel
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetListBinding {
return SheetListBinding.inflate(inflater, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listAdapter = MangaListAdapter(get(), viewLifecycleOwner, this) {
viewModel.onRetry()
}
paginationListener = PaginationScrollListener(4, this)
with(binding.recyclerView) {
setHasFixedSize(true)
adapter = listAdapter
addOnScrollListener(paginationListener!!)
}
with(binding.toolbar) {
inflateMenu(R.menu.opt_list_sheet)
setOnMenuItemClickListener(this@MangaListSheet)
setNavigationOnClickListener {
dismiss()
}
}
if (dialog !is BottomSheetDialog) {
binding.toolbar.isVisible = true
binding.textViewTitle.isVisible = false
binding.appbar.elevation = resources.getDimension(R.dimen.elevation_large)
}
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
viewModel.onError.observe(viewLifecycleOwner, ::onError)
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
viewModel.listMode.observe(viewLifecycleOwner, ::onListModeChanged)
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged)
}
override fun onDestroyView() {
listAdapter = null
paginationListener = null
spanSizeLookup.invalidateCache()
super.onDestroyView()
}
protected fun setTitle(title: CharSequence) {
binding.toolbar.title = title
binding.textViewTitle.text = title
}
protected fun setSubtitle(subtitle: CharSequence) {
binding.toolbar.subtitle = subtitle
}
override fun onCreateDialog(savedInstanceState: Bundle?) =
super.onCreateDialog(savedInstanceState).also {
val behavior = (it as? BottomSheetDialog)?.behavior ?: return@also
behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
private val elevation = resources.getDimension(R.dimen.elevation_large)
override fun onSlide(bottomSheet: View, slideOffset: Float) = Unit
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
binding.toolbar.isVisible = true
binding.textViewTitle.isVisible = false
binding.appbar.elevation = elevation
} else {
binding.toolbar.isVisible = false
binding.textViewTitle.isVisible = true
binding.appbar.elevation = 0f
}
}
})
}
override fun onMenuItemClick(item: MenuItem) = when (item.itemId) {
R.id.action_list_mode -> {
ListModeSelectDialog.show(childFragmentManager)
true
}
else -> false
}
override fun onItemClick(item: Manga, view: View) {
startActivity(DetailsActivity.newIntent(context ?: return, item))
}
private fun onListChanged(list: List<ListModel>) {
spanSizeLookup.invalidateCache()
listAdapter?.items = list
}
private fun onError(e: Throwable) {
if (e is CloudFlareProtectedException) {
CloudFlareDialog.newInstance(e.url).show(childFragmentManager, CloudFlareDialog.TAG)
} else {
Snackbar.make(
binding.recyclerView,
e.getDisplayMessage(resources),
Snackbar.LENGTH_SHORT
).show()
}
}
private fun onLoadingStateChanged(isLoading: Boolean) {
binding.progressBar.isVisible =
isLoading && !binding.recyclerView.hasItems
}
private fun onGridScaleChanged(scale: Float) {
spanSizeLookup.invalidateCache()
spanResolver.setGridSize(scale, binding.recyclerView)
}
private fun onListModeChanged(mode: ListMode) {
spanSizeLookup.invalidateCache()
with(binding.recyclerView) {
clearItemDecorations()
removeOnLayoutChangeListener(spanResolver)
when (mode) {
ListMode.LIST -> {
layoutManager = LinearLayoutManager(context)
addItemDecoration(
DividerItemDecoration(
context,
RecyclerView.VERTICAL
)
)
}
ListMode.DETAILED_LIST -> {
layoutManager = LinearLayoutManager(context)
addItemDecoration(
SpacingItemDecoration(
resources.getDimensionPixelOffset(R.dimen.grid_spacing)
)
)
}
ListMode.GRID -> {
layoutManager = GridLayoutManager(context, spanResolver.spanCount).also {
it.spanSizeLookup = spanSizeLookup
}
addItemDecoration(
SpacingItemDecoration(
resources.getDimensionPixelOffset(R.dimen.grid_spacing)
)
)
addOnLayoutChangeListener(spanResolver)
}
}
}
}
private inner class SpanSizeLookup : GridLayoutManager.SpanSizeLookup() {
init {
isSpanIndexCacheEnabled = true
isSpanGroupIndexCacheEnabled = true
}
override fun getSpanSize(position: Int): Int {
val total =
(binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1
return when (listAdapter?.getItemViewType(position)) {
MangaListAdapter.ITEM_TYPE_MANGA_GRID -> 1
else -> total
}
}
fun invalidateCache() {
invalidateSpanGroupIndexCache()
invalidateSpanIndexCache()
}
}
}

View File

@@ -52,6 +52,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (protectHelper.check(this)) {
finish()
return
}
setContentView(ActivityMainBinding.inflate(layoutInflater))
drawerToggle =
ActionBarDrawerToggle(
@@ -76,10 +80,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
} ?: run {
openDefaultSection()
}
if (protectHelper.check(this)) {
finish()
return
}
TrackWorker.setup(applicationContext)
AppUpdateChecker(this).launchIfNeeded()

View File

@@ -60,7 +60,7 @@ class PageLoader(
"Null response"
}
cache.put(url) { out ->
body.byteStream().copyTo(out)
body.byteStream().use { it.copyTo(out) }
}
}
}

View File

@@ -34,7 +34,6 @@ import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.databinding.ActivityReaderBinding
import org.koitharu.kotatsu.reader.ReaderControlDelegate
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState
import org.koitharu.kotatsu.reader.ui.pager.reversed.ReversedReaderFragment
@@ -63,6 +62,10 @@ class ReaderActivity : BaseFullscreenActivity<ActivityReaderBinding>(),
private lateinit var touchHelper: GridTouchHelper
private lateinit var orientationHelper: ScreenOrientationHelper
private lateinit var controlDelegate: ReaderControlDelegate
private val permissionsRequest = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
this
)
private var gestureInsets: Insets = Insets.NONE
private val reader
@@ -184,10 +187,7 @@ class ReaderActivity : BaseFullscreenActivity<ActivityReaderBinding>(),
) {
onActivityResult(true)
} else {
registerForActivityResult(
ActivityResultContracts.RequestPermission(),
this
).launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
permissionsRequest.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
} else {
showWaitWhileLoading()
@@ -273,6 +273,7 @@ class ReaderActivity : BaseFullscreenActivity<ActivityReaderBinding>(),
}
override fun onReaderModeChanged(mode: ReaderMode) {
viewModel.saveCurrentState(reader?.getCurrentState())
viewModel.switchMode(mode)
}

View File

@@ -1,4 +1,4 @@
package org.koitharu.kotatsu.reader
package org.koitharu.kotatsu.reader.ui
import android.view.KeyEvent
import androidx.lifecycle.LifecycleCoroutineScope

View File

@@ -39,7 +39,7 @@ class ReaderViewModel(
) : BaseViewModel() {
private var loadingJob: Job? = null
private val currentState = MutableStateFlow(state)
private val currentState = MutableStateFlow<ReaderState?>(null)
private val mangaData = MutableStateFlow<Manga?>(intent.manga)
private val chapters = LongSparseArray<MangaChapter>()
@@ -98,14 +98,12 @@ class ReaderViewModel(
newMode
} ?: error("There are no chapters in this manga")
// obtain state
if (state == null) {
currentState.value = historyRepository.getOne(manga)?.let {
ReaderState.from(it)
} ?: ReaderState.initial(manga)
}
currentState.value = state ?: historyRepository.getOne(manga)?.let {
ReaderState.from(it)
} ?: ReaderState.initial(manga)
readerMode.postValue(mode)
val pages = loadChapter(checkNotNull(manga.chapters?.firstOrNull()).id)
val pages = loadChapter(requireNotNull(currentState.value).chapterId)
content.postValue(ReaderContent(pages, currentState.value))
}
}
@@ -118,10 +116,18 @@ class ReaderViewModel(
mode = newMode
)
readerMode.value = newMode
content.value?.run {
content.value = copy(
state = getCurrentState()
)
}
}
}
fun saveCurrentState(state: ReaderState? = null) {
if (state != null) {
currentState.value = state
}
saveState(
mangaData.value ?: return,
state ?: currentState.value ?: return
@@ -184,17 +190,14 @@ class ReaderViewModel(
currentState.value = currentValue.copy(chapterId = it.chapterId)
}
}
when {
loadingJob?.isActive == true -> return
pages.isEmpty() -> return
position <= BOUNDS_PAGE_OFFSET -> {
val chapterId = pages.first().chapterId
loadPrevNextChapter(chapterId, -1)
}
position >= pages.size - BOUNDS_PAGE_OFFSET -> {
val chapterId = pages.last().chapterId
loadPrevNextChapter(chapterId, 1)
}
if (pages.isEmpty() || loadingJob?.isActive == true) {
return
}
if (position <= BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.first().chapterId, -1)
}
if (position >= pages.size - BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.last().chapterId, 1)
}
}

View File

@@ -4,13 +4,17 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.coroutines.async
import org.koin.android.ext.android.get
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
import org.koitharu.kotatsu.utils.ext.callOnPageChaneListeners
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
import org.koitharu.kotatsu.utils.ext.swapAdapter
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
@@ -29,6 +33,15 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
offscreenPageLimit = 2
doOnPageChanged(::notifyPageChanged)
}
viewModel.readerAnimation.observe(viewLifecycleOwner) {
val transformer = if (it) ReversedPageAnimTransformer() else null
binding.pager.setPageTransformer(transformer)
}
viewModel.onZoomChanged.observe(viewLifecycleOwner) {
pagerAdapter = ReversedPagesAdapter(loader, get())
binding.pager.swapAdapter(pagerAdapter)
}
}
override fun onDestroyView() {
@@ -47,13 +60,24 @@ class ReversedReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
}
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
pagerAdapter?.setItems(pages.asReversed()) {
val reversedPages = pages.asReversed()
viewLifecycleScope.launchWhenCreated {
val items = async {
pagerAdapter?.setItems(reversedPages)
}
if (pendingState != null) {
val position = pages.indexOfFirst {
val position = reversedPages.indexOfLast {
it.chapterId == pendingState.chapterId && it.index == pendingState.page
}
if (position == -1) return@setItems
binding.pager.setCurrentItem(position, false)
items.await() ?: return@launchWhenCreated
if (position != -1) {
binding.pager.setCurrentItem(position, false)
}
} else {
items.await()
}
binding.pager.post {
bindingOrNull()?.pager?.callOnPageChaneListeners()
}
}
}

View File

@@ -11,6 +11,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
import org.koitharu.kotatsu.utils.ext.callOnPageChaneListeners
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
import org.koitharu.kotatsu.utils.ext.swapAdapter
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
@@ -64,6 +65,9 @@ class PagerReaderFragment : BaseReader<FragmentReaderStandardBinding>() {
} else {
items.await()
}
binding.pager.post {
bindingOrNull()?.pager?.callOnPageChaneListeners()
}
}
}

View File

@@ -12,10 +12,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.pager.BaseReader
import org.koitharu.kotatsu.reader.ui.pager.BaseReaderAdapter
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
import org.koitharu.kotatsu.utils.ext.doOnCurrentItemChanged
import org.koitharu.kotatsu.utils.ext.findCenterViewPosition
import org.koitharu.kotatsu.utils.ext.firstItem
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import org.koitharu.kotatsu.utils.ext.*
class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
@@ -51,14 +48,20 @@ class WebtoonReaderFragment : BaseReader<FragmentReaderWebtoonBinding>() {
}
setItems.await() ?: return@launchWhenCreated
if (position != -1) {
binding.recyclerView.firstItem = position
// TODO check
(binding.recyclerView.findViewHolderForAdapterPosition(position) as? WebtoonHolder)
?.restoreScroll(pendingState.scroll)
with(binding.recyclerView) {
firstItem = position
post {
(findViewHolderForAdapterPosition(position) as? WebtoonHolder)
?.restoreScroll(pendingState.scroll)
}
}
}
} else {
setItems.await()
}
binding.recyclerView.post {
binding.recyclerView.callOnScrollListeners()
}
}
}

View File

@@ -96,9 +96,12 @@ class RemoteListViewModel(
fun applyFilter(newFilter: MangaFilter) {
appliedFilter = newFilter
mangaList.value = emptyList()
mangaList.value = null
hasNextPage.value = false
loadList(false)
filter.value?.run {
filter.value = copy(currentFilter = newFilter)
}
}
private fun loadFilter() {

View File

@@ -1,50 +0,0 @@
package org.koitharu.kotatsu.search.ui
import android.os.Bundle
import android.view.View
import androidx.fragment.app.FragmentManager
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.list.ui.MangaListSheet
import org.koitharu.kotatsu.utils.ext.parcelableArgument
import org.koitharu.kotatsu.utils.ext.stringArgument
import org.koitharu.kotatsu.utils.ext.withArgs
class MangaSearchSheet : MangaListSheet() {
override val viewModel by viewModel<SearchViewModel> {
parametersOf(source, query)
}
private val query by stringArgument(ARG_QUERY)
private val source by parcelableArgument<MangaSource>(ARG_SOURCE)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setTitle(query.orEmpty())
setSubtitle(getString(R.string.search_results_on_s, source.title))
}
override fun onScrolledToEnd() {
viewModel.loadNextPage()
}
companion object {
private const val ARG_SOURCE = "source"
private const val ARG_QUERY = "query"
private const val TAG = "MangaSearchSheet"
@Deprecated("Not ready for use")
fun show(fm: FragmentManager, source: MangaSource, query: String) {
MangaSearchSheet().withArgs(2) {
putParcelable(ARG_SOURCE, source)
putString(ARG_QUERY, query)
}.show(fm, TAG)
}
}
}

View File

@@ -52,8 +52,6 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
MultiSummaryProvider(R.string.gestures_only)
findPreference<MultiSelectListPreference>(AppSettings.KEY_TRACK_SOURCES)?.summaryProvider =
MultiSummaryProvider(R.string.dont_check)
findPreference<Preference>(AppSettings.KEY_GRID_SIZE)?.isEnabled =
settings.listMode == ListMode.GRID
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -93,10 +91,6 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
?: getString(R.string.not_available)
}
}
AppSettings.KEY_LIST_MODE -> {
findPreference<Preference>(AppSettings.KEY_GRID_SIZE)?.isEnabled =
settings.listMode == ListMode.GRID
}
}
}

View File

@@ -17,9 +17,10 @@ class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notif
private val ringtonePickContract = registerForActivityResult(
RingtonePickContract(get<Context>().getString(R.string.notification_sound))
) { uri ->
settings.notificationSound = uri?.toString().orEmpty()
settings.notificationSound = uri?.toString() ?: return@registerForActivityResult
findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SOUND)?.run {
summary = RingtoneManager.getRingtone(context, uri).getTitle(context)
summary = RingtoneManager.getRingtone(context, uri)?.getTitle(context)
?: getString(R.string.silent)
}
}
@@ -31,7 +32,8 @@ class NotificationSettingsLegacyFragment : BasePreferenceFragment(R.string.notif
super.onViewCreated(view, savedInstanceState)
findPreference<Preference>(AppSettings.KEY_NOTIFICATIONS_SOUND)?.run {
val uri = settings.notificationSound.toUriOrNull()
summary = RingtoneManager.getRingtone(context, uri).getTitle(context)
summary = RingtoneManager.getRingtone(context, uri)?.getTitle(context)
?: getString(R.string.silent)
}
}

View File

@@ -19,7 +19,7 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme" />

View File

@@ -16,7 +16,7 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_height="wrap_content"
app:popupTheme="@style/AppPopupTheme" />
</com.google.android.material.appbar.AppBarLayout>

View File

@@ -15,7 +15,7 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme">

View File

@@ -15,7 +15,7 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme" />

View File

@@ -15,7 +15,7 @@
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme" />

View File

@@ -1,77 +0,0 @@
<?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:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?android:windowBackground"
android:elevation="0dp"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/Widget.MaterialComponents.Toolbar.Surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="0dp"
android:outlineProvider="@null"
android:visibility="gone"
app:elevation="0dp"
app:navigationIcon="@drawable/ic_cross"
tools:visibility="visible" />
<TextView
android:id="@+id/textView_title"
style="@style/MaterialAlertDialog.MaterialComponents.Title.Text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="16dp"
android:textColor="?android:textColorSecondary"
tools:visibility="gone" />
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="120dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_manga_list" />
<TextView
android:id="@+id/textView_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorSecondary"
tools:text="@tools:sample/lorem[3]" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="blue_primary">#1565C0</color>
<color name="blue_primary_dark">#283593</color>
<color name="blue_primary">#1976D2</color>
<color name="blue_primary_dark">#0D47A1</color>
<color name="blue_primary_darker">#1A237E</color>
<color name="red_accent">#FF8A65</color>
<color name="dim">#99000000</color>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme.Amoled">
<item name="colorPrimary">@color/blue_primary_dark</item>
<item name="colorPrimary">@color/blue_primary</item>
<item name="colorPrimaryDark">@color/blue_primary_darker</item>
<item name="android:windowBackground">@android:color/black</item>
</style>

View File

@@ -179,12 +179,13 @@
<string name="file_not_found">Файл не найден</string>
<string name="data_restored_success">Все данные успешно восстановлены</string>
<string name="data_restored_with_errors">Данные восстановлены, но возникли некоторые ошибки</string>
<string name="backup_information">You can create backup of your history and favourites and restore it</string>
<string name="backup_information">Вы можете создать резервную копию избранного и истории и потом восстановить их</string>
<string name="just_now">Только что</string>
<string name="yesterday">Вчера</string>
<string name="long_ago">Давно</string>
<string name="group">Группировать</string>
<string name="today">Сегодня</string>
<string name="tap_to_try_again">Tap to try again</string>
<string name="reader_mode_hint">Chosen configuration will be remembered for this manga</string>
<string name="tap_to_try_again">Попробовать ещё раз</string>
<string name="reader_mode_hint">Выбранный режим будет сохранён для текущей манги</string>
<string name="silent">Без звука</string>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="grid_spacing">8dp</dimen>
<dimen name="preferred_grid_width">140dp</dimen>
</resources>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="grid_spacing">5dp</dimen>
<dimen name="grid_spacing">6dp</dimen>
<dimen name="manga_list_item_height">84dp</dimen>
<dimen name="manga_list_details_item_height">120dp</dimen>
<dimen name="chapter_list_item_height">46dp</dimen>

View File

@@ -189,4 +189,5 @@
<string name="today">Today</string>
<string name="tap_to_try_again">Tap to try again</string>
<string name="reader_mode_hint">Chosen configuration will be remembered for this manga</string>
<string name="silent">Silent</string>
</resources>