diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt index c14d81151..a6fc2c466 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt @@ -31,7 +31,7 @@ abstract class BaseActivity : AppCompatActivity(), OnApplyWindo @Suppress("LeakingThis") protected val exceptionResolver = ExceptionResolver(this) - private var lastInsets: Insets = Insets.NONE + private var lastInsets: Insets? = null override fun onCreate(savedInstanceState: Bundle?) { val settings = get() diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt index d65e031fa..b2146c3ba 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt @@ -42,7 +42,7 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return if (resources.getBoolean(R.bool.is_tablet)) { - AppCompatDialog(context, theme) + AppCompatDialog(context, R.style.Theme_Kotatsu_Dialog) } else super.onCreateDialog(savedInstanceState) } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt index 0e7c863bb..68b1ffe42 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseFragment.kt @@ -8,6 +8,7 @@ import androidx.core.graphics.Insets import androidx.core.view.OnApplyWindowInsetsListener import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import androidx.core.view.doOnNextLayout import androidx.fragment.app.Fragment import androidx.viewbinding.ViewBinding import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver @@ -22,7 +23,7 @@ abstract class BaseFragment : Fragment(), OnApplyWindowInsetsLi @Suppress("LeakingThis") protected val exceptionResolver = ExceptionResolver(this) - private var lastInsets: Insets = Insets.NONE + private var lastInsets: Insets? = null override fun onCreateView( inflater: LayoutInflater, @@ -36,12 +37,18 @@ abstract class BaseFragment : Fragment(), OnApplyWindowInsetsLi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - lastInsets = Insets.NONE ViewCompat.setOnApplyWindowInsetsListener(view, this) + view.doOnNextLayout { + // Listener may not be called + if (lastInsets == null) { + onWindowInsetsChanged(Insets.NONE) + } + } } override fun onDestroyView() { viewBinding = null + lastInsets = null super.onDestroyView() } diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index e28a0613f..d2812d4a6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -4,6 +4,7 @@ import android.app.ActivityOptions import android.os.Bundle import android.view.* import android.widget.AdapterView +import android.widget.Spinner import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode import androidx.core.graphics.Insets @@ -24,6 +25,7 @@ import org.koitharu.kotatsu.download.ui.service.DownloadService import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.reader.ui.ReaderActivity import org.koitharu.kotatsu.reader.ui.ReaderState +import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback class ChaptersFragment : BaseFragment(), OnListItemClickListener, @@ -56,21 +58,9 @@ class ChaptersFragment : BaseFragment(), setHasFixedSize(true) adapter = chaptersAdapter } - val branchesAdapter = BranchesAdapter() - binding.spinnerBranches.adapter = branchesAdapter - binding.spinnerBranches.onItemSelectedListener = this - + binding.spinnerBranches?.let(::initSpinner) viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged) viewModel.chapters.observe(viewLifecycleOwner, this::onChaptersChanged) - viewModel.branches.observe(viewLifecycleOwner) { - branchesAdapter.setItems(it) - binding.spinnerBranches.isVisible = it.size > 1 - } - viewModel.selectedBranchIndex.observe(viewLifecycleOwner) { - if (it != -1 && it != binding.spinnerBranches.selectedItemPosition) { - binding.spinnerBranches.setSelection(it) - } - } viewModel.isChaptersReversed.observe(viewLifecycleOwner) { activity?.invalidateOptionsMenu() } @@ -79,7 +69,7 @@ class ChaptersFragment : BaseFragment(), override fun onDestroyView() { chaptersAdapter = null selectionDecoration = null - binding.spinnerBranches.adapter = null + binding.spinnerBranches?.adapter = null super.onDestroyView() } @@ -166,7 +156,8 @@ class ChaptersFragment : BaseFragment(), } override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - viewModel.setSelectedBranch(binding.spinnerBranches.selectedItem as String?) + val spinner = binding.spinnerBranches ?: return + viewModel.setSelectedBranch(spinner.selectedItem as String?) } override fun onNothingSelected(parent: AdapterView<*>?) = Unit @@ -201,14 +192,37 @@ class ChaptersFragment : BaseFragment(), override fun onWindowInsetsChanged(insets: Insets) { binding.recyclerViewChapters.updatePadding( - left = insets.left, - right = insets.right, - bottom = insets.bottom + binding.spinnerBranches.height + bottom = insets.bottom + (binding.spinnerBranches?.height ?: 0), ) } + private fun initSpinner(spinner: Spinner) { + val branchesAdapter = BranchesAdapter() + spinner.adapter = branchesAdapter + spinner.onItemSelectedListener = this + viewModel.branches.observe(viewLifecycleOwner) { + branchesAdapter.setItems(it) + spinner.isVisible = it.size > 1 + } + viewModel.selectedBranchIndex.observe(viewLifecycleOwner) { + if (it != -1 && it != spinner.selectedItemPosition) { + spinner.setSelection(it) + } + } + } + private fun onChaptersChanged(list: List) { - chaptersAdapter?.items = list + val adapter = chaptersAdapter ?: return + if (adapter.itemCount == 0) { + val position = list.indexOfFirst { it.hasFlag(ChapterListItem.FLAG_CURRENT) } - 1 + if (position > 0) { + adapter.setItems(list, RecyclerViewScrollCallback(binding.recyclerViewChapters, position)) + } else { + adapter.items = list + } + } else { + adapter.items = list + } } private fun onLoadingStateChanged(isLoading: Boolean) { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 8c99b0ef5..be4b2316d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -6,25 +6,26 @@ import android.net.Uri import android.os.Bundle import android.view.Menu import android.view.MenuItem +import android.view.View import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.Spinner import android.widget.Toast import androidx.appcompat.view.ActionMode -import androidx.appcompat.widget.Toolbar import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.Insets import androidx.core.net.toFile +import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.lifecycle.lifecycleScope import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import kotlinx.coroutines.launch 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.BuildConfig import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.base.ui.BaseActivity @@ -34,6 +35,7 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.databinding.ActivityDetailsBinding +import org.koitharu.kotatsu.details.ui.adapter.BranchesAdapter import org.koitharu.kotatsu.download.ui.service.DownloadService import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource @@ -43,8 +45,8 @@ import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ext.getDisplayMessage -class DetailsActivity : BaseActivity(), - TabLayoutMediator.TabConfigurationStrategy { +class DetailsActivity : BaseActivity(), TabLayoutMediator.TabConfigurationStrategy, + AdapterView.OnItemSelectedListener { private val viewModel by viewModel { parametersOf(MangaIntent(intent)) @@ -53,9 +55,16 @@ class DetailsActivity : BaseActivity(), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(ActivityDetailsBinding.inflate(layoutInflater)) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - binding.pager.adapter = MangaDetailsAdapter(this) - TabLayoutMediator(binding.tabs, binding.pager, this).attach() + supportActionBar?.run { + setDisplayHomeAsUpEnabled(true) + setDisplayShowTitleEnabled(false) + } + val pager = binding.pager + if (pager != null) { + pager.adapter = MangaDetailsAdapter(this) + TabLayoutMediator(checkNotNull(binding.tabs), pager, this).attach() + } + binding.spinnerBranches?.let(::initSpinner) viewModel.manga.observe(this, ::onMangaUpdated) viewModel.newChaptersCount.observe(this, ::onNewChaptersChanged) @@ -96,25 +105,17 @@ class DetailsActivity : BaseActivity(), binding.snackbar.updatePadding( bottom = insets.bottom ) - with(binding.toolbar) { - updatePadding( - left = insets.left, - right = insets.right - ) - updateLayoutParams { - topMargin = insets.top - } - } - if (binding.tabs.parent !is Toolbar) { - binding.tabs.updatePadding( - left = insets.left, - right = insets.right - ) + binding.toolbar.updateLayoutParams { + topMargin = insets.top } + binding.root.updatePadding( + left = insets.left, + right = insets.right + ) } private fun onNewChaptersChanged(newChapters: Int) { - val tab = binding.tabs.getTabAt(1) ?: return + val tab = binding.tabs?.getTabAt(1) ?: return if (newChapters == 0) { tab.removeBadge() } else { @@ -208,11 +209,7 @@ class DetailsActivity : BaseActivity(), viewModel.manga.value?.let { lifecycleScope.launch { if (!get().requestPinShortcut(it)) { - Snackbar.make( - binding.pager, - R.string.operation_not_supported, - Snackbar.LENGTH_SHORT - ).show() + binding.snackbar.show(getString(R.string.operation_not_supported)) } } } @@ -231,19 +228,25 @@ class DetailsActivity : BaseActivity(), override fun onSupportActionModeStarted(mode: ActionMode) { super.onSupportActionModeStarted(mode) - binding.pager.isUserInputEnabled = false + binding.pager?.isUserInputEnabled = false } override fun onSupportActionModeFinished(mode: ActionMode) { super.onSupportActionModeFinished(mode) - binding.pager.isUserInputEnabled = true + binding.pager?.isUserInputEnabled = true + } + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + val spinner = binding.spinnerBranches ?: return + viewModel.setSelectedBranch(spinner.selectedItem as String?) } + override fun onNothingSelected(parent: AdapterView<*>?) = Unit + fun showChapterMissingDialog(chapterId: Long) { val remoteManga = viewModel.getRemoteManga() if (remoteManga == null) { - Snackbar.make(binding.pager, R.string.chapter_is_missing, Snackbar.LENGTH_LONG) - .show() + binding.snackbar.show(getString( R.string.chapter_is_missing)) return } MaterialAlertDialogBuilder(this).apply { @@ -266,9 +269,22 @@ class DetailsActivity : BaseActivity(), }.show() } - companion object { + private fun initSpinner(spinner: Spinner) { + val branchesAdapter = BranchesAdapter() + spinner.adapter = branchesAdapter + spinner.onItemSelectedListener = this + viewModel.branches.observe(this) { + branchesAdapter.setItems(it) + spinner.isVisible = it.size > 1 + } + viewModel.selectedBranchIndex.observe(this) { + if (it != -1 && it != spinner.selectedItemPosition) { + spinner.setSelection(it) + } + } + } - const val ACTION_MANGA_VIEW = "${BuildConfig.APPLICATION_ID}.action.VIEW_MANGA" + companion object { fun newIntent(context: Context, manga: Manga): Intent { return Intent(context, DetailsActivity::class.java) diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 550f46d34..5acdfd109 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -243,9 +243,7 @@ class DetailsFragment : BaseFragment(), View.OnClickList override fun onWindowInsetsChanged(insets: Insets) { binding.root.updatePadding( - left = insets.left, - right = insets.right, - bottom = insets.bottom + bottom = insets.bottom, ) } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index 77c4cbb5d..f3ae56470 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -176,17 +176,19 @@ abstract class MangaListFragment : BaseFragment(), val headerHeight = (activity as? AppBarOwner)?.appBar?.measureHeight() ?: insets.top binding.root.updatePadding( left = insets.left, - right = insets.right + right = insets.right, ) if (activity is MainActivity) { + val topOffsetDiff = binding.recyclerView.paddingTop - headerHeight binding.recyclerView.updatePadding( top = headerHeight, - bottom = insets.bottom + bottom = insets.bottom, ) + binding.recyclerView.scrollBy(0, topOffsetDiff) binding.swipeRefreshLayout.setProgressViewOffset( true, headerHeight + resources.resolveDp(-72), - headerHeight + resources.resolveDp(10) + headerHeight + resources.resolveDp(10), ) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt index d1ba95fb9..8349f1a52 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -10,13 +10,15 @@ import android.view.ViewGroup.MarginLayoutParams import androidx.appcompat.app.ActionBarDrawerToggle import androidx.core.content.ContextCompat import androidx.core.graphics.Insets -import androidx.core.view.* +import androidx.core.view.GravityCompat +import androidx.core.view.ViewCompat +import androidx.core.view.updateLayoutParams +import androidx.core.view.updatePadding import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.commit import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.CircularProgressDrawable import com.google.android.material.appbar.AppBarLayout import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -55,10 +57,7 @@ import org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker import org.koitharu.kotatsu.tracker.ui.FeedFragment import org.koitharu.kotatsu.tracker.work.TrackWorker -import org.koitharu.kotatsu.utils.ext.getDisplayMessage -import org.koitharu.kotatsu.utils.ext.hideKeyboard -import org.koitharu.kotatsu.utils.ext.measureHeight -import org.koitharu.kotatsu.utils.ext.resolveDp +import org.koitharu.kotatsu.utils.ext.* private const val TAG_PRIMARY = "primary" private const val TAG_SEARCH = "search" @@ -71,7 +70,8 @@ class MainActivity : BaseActivity(), private val searchSuggestionViewModel by viewModel() private lateinit var navHeaderBinding: NavigationHeaderBinding - private lateinit var drawerToggle: ActionBarDrawerToggle + private var drawerToggle: ActionBarDrawerToggle? = null + private var drawer: DrawerLayout? = null override val appBar: AppBarLayout get() = binding.appbar @@ -80,36 +80,35 @@ class MainActivity : BaseActivity(), super.onCreate(savedInstanceState) setContentView(ActivityMainBinding.inflate(layoutInflater)) navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater) - drawerToggle = ActionBarDrawerToggle( - this, - binding.drawer, - binding.toolbar, - R.string.open_menu, - R.string.close_menu - ) - drawerToggle.setHomeAsUpIndicator(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back)) - drawerToggle.setToolbarNavigationClickListener { - binding.searchView.hideKeyboard() - onBackPressed() + drawer = binding.root as? DrawerLayout + drawerToggle = drawer?.let { + ActionBarDrawerToggle( + this, + it, + binding.toolbar, + R.string.open_menu, + R.string.close_menu + ).apply { + setHomeAsUpIndicator(ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_arrow_back)) + setToolbarNavigationClickListener { + binding.searchView.hideKeyboard() + onBackPressed() + } + it.addDrawerListener(this) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + } } - binding.drawer.addDrawerListener(drawerToggle) - supportActionBar?.setDisplayHomeAsUpEnabled(true) with(binding.searchView) { onFocusChangeListener = this@MainActivity searchSuggestionListener = this@MainActivity + if (drawer == null) { + drawableStart = ContextCompat.getDrawable(context, R.drawable.ic_search) + } } with(binding.navigationView) { - val menuView = - findViewById(com.google.android.material.R.id.design_navigation_view) - ViewCompat.setOnApplyWindowInsetsListener(navHeaderBinding.root) { v, insets -> - val systemWindowInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.updatePadding(top = systemWindowInsets.top) - // NavigationView doesn't dispatch insets to the menu view, so pad the bottom here. - menuView.updatePadding(bottom = systemWindowInsets.bottom) - insets - } + ViewCompat.setOnApplyWindowInsetsListener(this, NavigationViewInsetsListener()) addHeaderView(navHeaderBinding.root) setNavigationItemSelectedListener(this@MainActivity) } @@ -134,26 +133,27 @@ class MainActivity : BaseActivity(), override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) - drawerToggle.isDrawerIndicatorEnabled = - binding.drawer.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED + drawerToggle?.isDrawerIndicatorEnabled = + drawer?.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED } override fun onPostCreate(savedInstanceState: Bundle?) { super.onPostCreate(savedInstanceState) - drawerToggle.syncState() + drawerToggle?.syncState() } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - drawerToggle.onConfigurationChanged(newConfig) + drawerToggle?.onConfigurationChanged(newConfig) } override fun onBackPressed() { val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH) binding.searchView.clearFocus() when { - binding.drawer.isDrawerOpen(binding.navigationView) -> binding.drawer.closeDrawer( - binding.navigationView) + drawer?.isDrawerOpen(binding.navigationView) == true -> { + drawer?.closeDrawer(binding.navigationView) + } fragment != null -> supportFragmentManager.commit { remove(fragment) setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) @@ -164,7 +164,7 @@ class MainActivity : BaseActivity(), } override fun onOptionsItemSelected(item: MenuItem): Boolean { - return drawerToggle.onOptionsItemSelected(item) || when (item.itemId) { + return drawerToggle?.onOptionsItemSelected(item) == true || when (item.itemId) { else -> super.onOptionsItemSelected(item) } } @@ -210,19 +210,22 @@ class MainActivity : BaseActivity(), else -> return false } } - binding.drawer.closeDrawers() + drawer?.closeDrawers() + appBar.setExpanded(true) return true } override fun onWindowInsetsChanged(insets: Insets) { - binding.toolbarCard.updateLayoutParams { - topMargin = insets.top + resources.resolveDp(8) - } binding.fab.updateLayoutParams { bottomMargin = insets.bottom + topMargin - leftMargin = insets.left + topMargin - rightMargin = insets.right + topMargin } + binding.toolbarCard.updateLayoutParams { + topMargin = insets.top + bottomMargin + } + binding.root.updatePadding( + left = insets.left, + right = insets.right, + ) binding.container.updateLayoutParams { topMargin = -(binding.appbar.measureHeight()) } @@ -360,14 +363,14 @@ class MainActivity : BaseActivity(), } private fun onSearchOpened() { - binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) - drawerToggle.isDrawerIndicatorEnabled = false + drawer?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) + drawerToggle?.isDrawerIndicatorEnabled = false adjustFabVisibility(isSearchOpened = true) } private fun onSearchClosed() { - binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) - drawerToggle.isDrawerIndicatorEnabled = true + drawer?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) + drawerToggle?.isDrawerIndicatorEnabled = true adjustFabVisibility(isSearchOpened = false) } diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/NavigationViewInsetsListener.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/NavigationViewInsetsListener.kt new file mode 100644 index 000000000..f3a66a8fa --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/NavigationViewInsetsListener.kt @@ -0,0 +1,24 @@ +package org.koitharu.kotatsu.main.ui + +import android.view.View +import androidx.core.view.OnApplyWindowInsetsListener +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding +import java.lang.ref.WeakReference +import com.google.android.material.R as materialR + +class NavigationViewInsetsListener : OnApplyWindowInsetsListener { + + private var menuViewRef: WeakReference? = null + + override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat { + val menuView = menuViewRef?.get() ?: v.findViewById(materialR.id.design_navigation_view).also { + menuViewRef = WeakReference(it) + } + val systemWindowInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding(top = systemWindowInsets.top) + // NavigationView doesn't dispatch insets to the menu view, so pad the bottom here. + menuView.updatePadding(bottom = systemWindowInsets.bottom) + return WindowInsetsCompat.CONSUMED + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt index 7132711f1..33a5cc62c 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ChaptersBottomSheet.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentManager -import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.divider.MaterialDividerItemDecoration import org.koin.android.ext.android.get @@ -20,6 +19,7 @@ import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.details.ui.model.toListItem import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.utils.BottomSheetToolbarController +import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback import org.koitharu.kotatsu.utils.ext.withArgs class ChaptersBottomSheet : BaseBottomSheet(), OnListItemClickListener { @@ -59,7 +59,7 @@ class ChaptersBottomSheet : BaseBottomSheet(), OnListItemC binding.recyclerView.adapter = ChaptersAdapter(this).also { adapter -> if (currentPosition >= 0) { val targetPosition = (currentPosition - 1).coerceAtLeast(0) - adapter.setItems(items, Scroller(binding.recyclerView, targetPosition)) + adapter.setItems(items, RecyclerViewScrollCallback(binding.recyclerView, targetPosition)) } else { adapter.items = items } @@ -78,13 +78,6 @@ class ChaptersBottomSheet : BaseBottomSheet(), OnListItemC fun onChapterChanged(chapter: MangaChapter) } - private class Scroller(private val recyclerView: RecyclerView, private val position: Int) : Runnable { - override fun run() { - val offset = recyclerView.resources.getDimensionPixelSize(R.dimen.chapter_list_item_height) / 2 - (recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, offset) - } - } - companion object { private const val ARG_CHAPTERS = "chapters" diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index 8f93d4449..1ae9ef264 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -243,7 +243,7 @@ class ReaderActivity : BaseFullscreenActivity(), rawX >= binding.root.width - gestureInsets.right || rawY >= binding.root.height - gestureInsets.bottom || binding.appbarTop.hasGlobalPoint(rawX, rawY) || - binding.appbarBottom.hasGlobalPoint(rawX, rawY) + binding.appbarBottom?.hasGlobalPoint(rawX, rawY) == true ) { false } else { @@ -320,11 +320,13 @@ class ReaderActivity : BaseFullscreenActivity(), if (binding.appbarTop.isVisible != isUiVisible) { val transition = TransitionSet() .setOrdering(TransitionSet.ORDERING_TOGETHER) - .addTransition(Slide(Gravity.BOTTOM).addTarget(binding.appbarBottom)) .addTransition(Slide(Gravity.TOP).addTarget(binding.appbarTop)) + binding.appbarBottom?.let { botomBar -> + transition.addTransition(Slide(Gravity.BOTTOM).addTarget(botomBar)) + } TransitionManager.beginDelayedTransition(binding.root, transition) binding.appbarTop.isVisible = isUiVisible - binding.appbarBottom.isVisible = isUiVisible + binding.appbarBottom?.isVisible = isUiVisible if (isUiVisible) { showSystemUI() } else { @@ -341,7 +343,7 @@ class ReaderActivity : BaseFullscreenActivity(), right = systemBars.right, left = systemBars.left ) - binding.appbarBottom.updatePadding( + binding.appbarBottom?.updatePadding( bottom = systemBars.bottom, right = systemBars.right, left = systemBars.left diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index 7fbf8f9da..c9a07f0fe 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -6,7 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager -import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.GridLayoutManager import com.google.android.material.bottomsheet.BottomSheetBehavior import org.koin.android.ext.android.get import org.koitharu.kotatsu.R @@ -29,6 +29,7 @@ class PagesThumbnailsSheet : BaseBottomSheet(), private lateinit var thumbnails: List private val spanResolver = MangaListSpanResolver() + private var currentPageIndex = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,12 +38,12 @@ class PagesThumbnailsSheet : BaseBottomSheet(), dismissAllowingStateLoss() return } - val current = arguments?.getInt(ARG_CURRENT, -1) ?: -1 + currentPageIndex = requireArguments().getInt(ARG_CURRENT, currentPageIndex) val repository = MangaRepository(pages.first().source) thumbnails = pages.mapIndexed { i, x -> PageThumbnail( number = i + 1, - isCurrent = i == current, + isCurrent = i == currentPageIndex, repository = repository, page = x ) @@ -69,11 +70,9 @@ class PagesThumbnailsSheet : BaseBottomSheet(), resources.getQuantityString(R.plurals.pages, thumbnails.size, thumbnails.size) } - val initialTopPosition = binding.recyclerView.top - with(binding.recyclerView) { addItemDecoration( - SpacingItemDecoration(view.resources.getDimensionPixelOffset(R.dimen.grid_spacing)) + SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)) ) adapter = PageThumbnailAdapter( thumbnails, @@ -82,16 +81,12 @@ class PagesThumbnailsSheet : BaseBottomSheet(), get(), this@PagesThumbnailsSheet ) - addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) = Unit - - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - super.onScrolled(recyclerView, dx, dy) - binding.appbar.isLifted = getChildAt(0).top < initialTopPosition - } - }) addOnLayoutChangeListener(spanResolver) spanResolver.setGridSize(get().gridSize / 100f, this) + if (currentPageIndex > 0) { + val offset = resources.getDimensionPixelOffset(R.dimen.preferred_grid_width) + (layoutManager as GridLayoutManager).scrollToPositionWithOffset(currentPageIndex, offset) + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt index 372655317..6ddd03a91 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/thumbnails/adapter/PageThumbnailAD.kt @@ -14,6 +14,8 @@ import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail import org.koitharu.kotatsu.utils.ext.IgnoreErrors import org.koitharu.kotatsu.utils.ext.referer +import org.koitharu.kotatsu.utils.ext.setTextColorAttr +import com.google.android.material.R as materialR fun pageThumbnailAD( coil: ImageLoader, @@ -31,7 +33,7 @@ fun pageThumbnailAD( height = (gridWidth * 13f / 18f).toInt() ) - binding.handle.setOnClickListener { + binding.root.setOnClickListener { clickListener.onItemClick(item.page, itemView) } @@ -39,7 +41,8 @@ fun pageThumbnailAD( job?.cancel() binding.imageViewThumb.setImageDrawable(null) with(binding.textViewNumber) { - setBackgroundResource(if (item.isCurrent) R.drawable.bg_badge_accent else R.drawable.bg_badge_default) + setBackgroundResource(if (item.isCurrent) R.drawable.bg_badge_accent else R.drawable.bg_badge_empty) + setTextColorAttr(if (item.isCurrent) materialR.attr.colorOnTertiary else android.R.attr.textColorPrimary) text = (item.number).toString() } job = scope.launch(Dispatchers.Default + IgnoreErrors) { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt index 49f944449..61700002a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/suggestion/adapter/SearchSuggestionsMangaListAD.kt @@ -15,7 +15,7 @@ import org.koitharu.kotatsu.databinding.ItemSearchSuggestionMangaGridBinding import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener import org.koitharu.kotatsu.search.ui.suggestion.model.SearchSuggestionItem -import org.koitharu.kotatsu.utils.ScrollResetCallback +import org.koitharu.kotatsu.utils.RecyclerViewScrollCallback import org.koitharu.kotatsu.utils.ext.enqueueWith import org.koitharu.kotatsu.utils.ext.newImageRequest @@ -37,7 +37,7 @@ fun searchSuggestionMangaListAD( right = recyclerView.paddingRight - spacing, ) recyclerView.addItemDecoration(SpacingItemDecoration(spacing)) - val scrollResetCallback = ScrollResetCallback(recyclerView) + val scrollResetCallback = RecyclerViewScrollCallback(recyclerView, 0) bind { adapter.setItems(item.items, scrollResetCallback) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt b/app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt new file mode 100644 index 000000000..984867ae4 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/RecyclerViewScrollCallback.kt @@ -0,0 +1,21 @@ +package org.koitharu.kotatsu.utils + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import java.lang.ref.WeakReference + +class RecyclerViewScrollCallback(recyclerView: RecyclerView, private val position: Int) : Runnable { + + private val recyclerViewRef = WeakReference(recyclerView) + + override fun run() { + val rv = recyclerViewRef.get() ?: return + val lm = rv.layoutManager ?: return + rv.stopScroll() + if (lm is LinearLayoutManager) { + lm.scrollToPositionWithOffset(position, 0) + } else { + lm.scrollToPosition(position) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ScrollResetCallback.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ScrollResetCallback.kt deleted file mode 100644 index 5a279f4ec..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ScrollResetCallback.kt +++ /dev/null @@ -1,13 +0,0 @@ -package org.koitharu.kotatsu.utils - -import androidx.recyclerview.widget.RecyclerView -import java.lang.ref.WeakReference - -class ScrollResetCallback(recyclerView: RecyclerView) : Runnable { - - private val recyclerViewRef = WeakReference(recyclerView) - - override fun run() { - recyclerViewRef.get()?.scrollToPosition(0) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt new file mode 100644 index 000000000..7276dab57 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/InsetsExt.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.utils.ext + +import android.view.View +import androidx.core.graphics.Insets + +fun Insets.getStart(view: View): Int { + return if (view.layoutDirection == View.LAYOUT_DIRECTION_RTL) { + right + } else { + left + } +} + +fun Insets.getEnd(view: View): Int { + return if (view.layoutDirection == View.LAYOUT_DIRECTION_RTL) { + left + } else { + right + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt index 05df723de..59620f2b0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/TextViewExt.kt @@ -3,7 +3,9 @@ package org.koitharu.kotatsu.utils.ext import android.graphics.drawable.Drawable import android.view.View import android.widget.TextView +import androidx.annotation.AttrRes import androidx.annotation.StringRes +import androidx.core.content.res.use import androidx.core.view.isGone var TextView.textAndVisible: CharSequence? @@ -35,4 +37,11 @@ fun TextView.setTextAndVisible(@StringRes textResId: Int) { setText(textResId) isGone = text.isNullOrEmpty() } +} + +fun TextView.setTextColorAttr(@AttrRes attrResId: Int) { + val colors = context.obtainStyledAttributes(intArrayOf(attrResId)).use { + it.getColorStateList(0) + } + setTextColor(colors) } \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_badge_empty.xml b/app/src/main/res/drawable/bg_badge_empty.xml new file mode 100644 index 000000000..55ad85bd1 --- /dev/null +++ b/app/src/main/res/drawable/bg_badge_empty.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/dialog_list_mode.xml b/app/src/main/res/layout-land/dialog_list_mode.xml new file mode 100644 index 000000000..f103a0ac3 --- /dev/null +++ b/app/src/main/res/layout-land/dialog_list_mode.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp-port/fragment_details.xml b/app/src/main/res/layout-w600dp-port/fragment_details.xml deleted file mode 100644 index c42301de6..000000000 --- a/app/src/main/res/layout-w600dp-port/fragment_details.xml +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp/activity_details.xml b/app/src/main/res/layout-w600dp/activity_details.xml deleted file mode 100644 index 6bf664eea..000000000 --- a/app/src/main/res/layout-w600dp/activity_details.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp/activity_reader.xml b/app/src/main/res/layout-w600dp/activity_reader.xml new file mode 100644 index 000000000..90a78c533 --- /dev/null +++ b/app/src/main/res/layout-w600dp/activity_reader.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp-land/fragment_details.xml b/app/src/main/res/layout-w600dp/fragment_details.xml similarity index 92% rename from app/src/main/res/layout-w600dp-land/fragment_details.xml rename to app/src/main/res/layout-w600dp/fragment_details.xml index 55df1bb95..d751d0c6c 100644 --- a/app/src/main/res/layout-w600dp-land/fragment_details.xml +++ b/app/src/main/res/layout-w600dp/fragment_details.xml @@ -17,8 +17,8 @@ android:id="@+id/imageView_cover" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginTop="16dp" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" android:foreground="?selectableItemBackground" android:scaleType="centerCrop" android:transitionName="cover" @@ -35,9 +35,9 @@ android:id="@+id/textView_title" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginTop="16dp" - android:layout_marginEnd="16dp" + android:layout_marginStart="8dp" + android:layout_marginTop="8dp" + android:layout_marginEnd="8dp" android:ellipsize="end" android:maxLines="3" android:textAppearance="?attr/textAppearanceHeadlineSmall" @@ -50,9 +50,9 @@ android:id="@+id/textView_subtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginTop="6dp" - android:layout_marginEnd="16dp" + android:layout_marginStart="8dp" + android:layout_marginTop="4dp" + android:layout_marginEnd="8dp" android:ellipsize="end" android:maxLines="3" android:textAppearance="?attr/textAppearanceBodyMedium" @@ -65,11 +65,11 @@ android:id="@+id/textView_author" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="12dp" + android:layout_marginStart="6dp" android:layout_marginTop="2dp" - android:layout_marginEnd="12dp" + android:layout_marginEnd="6dp" android:background="@drawable/list_selector" - android:padding="4dp" + android:padding="2dp" android:singleLine="true" android:textColor="?attr/colorTertiary" android:textStyle="bold" @@ -84,9 +84,9 @@ android:id="@+id/textView_state" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" + android:layout_marginStart="8dp" android:layout_marginTop="4dp" - android:layout_marginEnd="16dp" + android:layout_marginEnd="8dp" android:drawablePadding="4dp" android:singleLine="true" android:textAppearance="?attr/textAppearanceBodySmall" @@ -96,12 +96,19 @@ tools:drawableStart="@drawable/ic_state_finished" tools:text="Finished" /> + + @@ -128,7 +135,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" - android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:enabled="false" android:text="@string/read" @@ -140,14 +146,6 @@ app:layout_constraintTop_toBottomOf="@id/info_layout" tools:text="@string/_continue" /> - - + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w720dp/activity_details.xml b/app/src/main/res/layout-w720dp/activity_details.xml new file mode 100644 index 000000000..337b9ec77 --- /dev/null +++ b/app/src/main/res/layout-w720dp/activity_details.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w720dp/fragment_chapters.xml b/app/src/main/res/layout-w720dp/fragment_chapters.xml new file mode 100644 index 000000000..386ce6fb0 --- /dev/null +++ b/app/src/main/res/layout-w720dp/fragment_chapters.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml index 5a723948f..8190e9c82 100644 --- a/app/src/main/res/layout/activity_details.xml +++ b/app/src/main/res/layout/activity_details.xml @@ -3,7 +3,6 @@ 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:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".details.ui.DetailsActivity"> @@ -12,24 +11,28 @@ android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" - app:liftOnScroll="false" - app:elevation="0dp"> + app:elevation="0dp" + app:liftOnScroll="false"> + app:layout_scrollFlags="scroll|enterAlways" + tools:ignore="PrivateResource"> - + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 682ca84a3..e4ed68397 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -3,7 +3,6 @@ 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:id="@+id/drawer" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".main.ui.MainActivity"> @@ -16,12 +15,15 @@ android:id="@id/container" android:layout_width="match_parent" android:layout_height="match_parent" + tools:layout="@layout/fragment_list" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> @@ -29,10 +31,7 @@ android:id="@+id/toolbar_card" android:layout_width="match_parent" android:layout_height="48dp" - android:layout_marginStart="16dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="16dp" - android:layout_marginBottom="8dp" + android:layout_marginVertical="8dp" android:background="@drawable/toolbar_background"> + app:contentInsetStartWithNavigation="0dp"> - + xmlns:app="http://schemas.android.com/apk/res-auto" + style="@style/Widget.Material3.CardView.Outlined" + app:cardBackgroundColor="?scrimBackground"> - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 3f5cbbf6d..f4b747b4a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -21,6 +21,4 @@ 124dp 4dp - - \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index d1b29006e..a51ebf1e4 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -85,4 +85,12 @@ +