UI improvements
This commit is contained in:
@@ -14,6 +14,7 @@ import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.widget.LinearLayoutCompat
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import androidx.core.view.children
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
|
||||
@@ -100,6 +101,11 @@ class ProgressButton @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun setEnabled(enabled: Boolean) {
|
||||
super.setEnabled(enabled)
|
||||
children.forEach { it.isEnabled = enabled }
|
||||
}
|
||||
|
||||
override fun onAnimationUpdate(animation: ValueAnimator) {
|
||||
progress = animation.animatedValue as Float
|
||||
invalidate()
|
||||
|
||||
@@ -54,7 +54,8 @@ class DetailsLoadUseCase @Inject constructor(
|
||||
} catch (e: IOException) {
|
||||
local?.await()?.manga?.also { localManga ->
|
||||
send(MangaDetails(localManga, null, localManga.description?.parseAsHtml(withImages = false), true))
|
||||
} ?: throw e
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import android.view.ViewTreeObserver
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.inSpans
|
||||
@@ -57,7 +56,6 @@ import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||
import org.koitharu.kotatsu.core.util.FileSize
|
||||
import org.koitharu.kotatsu.core.util.ViewBadge
|
||||
import org.koitharu.kotatsu.core.util.ext.crossfade
|
||||
import org.koitharu.kotatsu.core.util.ext.drawableStart
|
||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||
import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty
|
||||
@@ -67,7 +65,6 @@ import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.parentView
|
||||
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
|
||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
||||
import org.koitharu.kotatsu.core.util.ext.showDistinct
|
||||
import org.koitharu.kotatsu.core.util.ext.source
|
||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||
import org.koitharu.kotatsu.databinding.ActivityDetailsNewBinding
|
||||
@@ -486,14 +483,14 @@ class DetailsActivity2 :
|
||||
ratingBar.isVisible = false
|
||||
}
|
||||
|
||||
textViewState.apply {
|
||||
manga.state?.let { state ->
|
||||
textAndVisible = resources.getString(state.titleResId)
|
||||
drawableStart = ContextCompat.getDrawable(context, state.iconResId)
|
||||
} ?: run {
|
||||
isVisible = false
|
||||
}
|
||||
manga.state?.let { state ->
|
||||
textViewState.textAndVisible = resources.getString(state.titleResId)
|
||||
imageViewState.setImageResource(state.iconResId)
|
||||
} ?: run {
|
||||
textViewState.isVisible = false
|
||||
imageViewState.isVisible = false
|
||||
}
|
||||
|
||||
if (manga.source == MangaSource.LOCAL || manga.source == MangaSource.DUMMY) {
|
||||
infoLayout.chipSource.isVisible = false
|
||||
} else {
|
||||
|
||||
@@ -10,8 +10,8 @@ import android.view.ViewGroup
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginBottom
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import coil.ImageLoader
|
||||
import coil.request.CachePolicy
|
||||
import coil.request.ErrorResult
|
||||
@@ -21,6 +21,7 @@ import coil.target.ViewTarget
|
||||
import com.davemorrissey.labs.subscaleview.ImageSource
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayIcon
|
||||
@@ -42,27 +43,25 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(), ImageRequest.Listene
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityImageBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowTitleEnabled(false)
|
||||
}
|
||||
viewBinding.buttonBack.setOnClickListener(this)
|
||||
loadImage(intent.data)
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) {
|
||||
with(viewBinding.toolbar) {
|
||||
updatePadding(
|
||||
left = insets.left,
|
||||
right = insets.right,
|
||||
)
|
||||
with(viewBinding.buttonBack) {
|
||||
updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = insets.top
|
||||
topMargin = insets.top + marginBottom
|
||||
leftMargin = insets.left + marginBottom
|
||||
rightMargin = insets.right + marginBottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
loadImage(intent.data)
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.button_back -> dispatchNavigateUp()
|
||||
else -> loadImage(intent.data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(request: ImageRequest, result: ErrorResult) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
|
||||
import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||
import org.koitharu.kotatsu.core.ui.widgets.TipView
|
||||
import org.koitharu.kotatsu.core.util.ShareHelper
|
||||
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
|
||||
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
|
||||
@@ -231,6 +232,10 @@ abstract class MangaListFragment :
|
||||
|
||||
override fun onListHeaderClick(item: ListHeader, view: View) = Unit
|
||||
|
||||
override fun onPrimaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onSecondaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onRetryClick(error: Throwable) {
|
||||
resolveException(error)
|
||||
}
|
||||
|
||||
@@ -24,5 +24,6 @@ open class MangaListAdapter(
|
||||
addDelegate(ListItemType.STATE_EMPTY, emptyStateListAD(coil, lifecycleOwner, listener))
|
||||
addDelegate(ListItemType.HINT_EMPTY, emptyHintAD(coil, lifecycleOwner, listener))
|
||||
addDelegate(ListItemType.HEADER, listHeaderAD(listener))
|
||||
addDelegate(ListItemType.TIP, tipAD(listener))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.koitharu.kotatsu.list.ui.adapter
|
||||
|
||||
import android.view.View
|
||||
import org.koitharu.kotatsu.core.ui.widgets.TipView
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
|
||||
interface MangaListListener : MangaDetailsClickListener, ListStateHolderListener, ListHeaderClickListener {
|
||||
interface MangaListListener : MangaDetailsClickListener, ListStateHolderListener, ListHeaderClickListener,
|
||||
TipView.OnButtonClickListener {
|
||||
|
||||
fun onUpdateFilter(tags: Set<MangaTag>)
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package org.koitharu.kotatsu.local.data
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.StatFs
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toFile
|
||||
import dagger.Reusable
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
@@ -101,6 +106,23 @@ class LocalStorageManager @Inject constructor(
|
||||
contentResolver.takePersistableUriPermission(uri, flags)
|
||||
}
|
||||
|
||||
fun isOnExternalStorage(file: File): Boolean {
|
||||
return !file.absolutePath.contains(context.packageName)
|
||||
}
|
||||
|
||||
fun hasExternalStoragePermission(isReadOnly: Boolean): Boolean {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
Environment.isExternalStorageManager()
|
||||
} else {
|
||||
val permission = if (isReadOnly) {
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
} else {
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
}
|
||||
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getDirectoryDisplayName(dir: File, isFullPath: Boolean): String = runInterruptible(Dispatchers.IO) {
|
||||
val packageName = context.packageName
|
||||
if (dir.absolutePath.contains(packageName)) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.koitharu.kotatsu.local.ui
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.net.toFile
|
||||
import androidx.core.net.toUri
|
||||
@@ -12,9 +15,11 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
|
||||
import org.koitharu.kotatsu.core.ui.widgets.TipView
|
||||
import org.koitharu.kotatsu.core.util.ShareHelper
|
||||
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
import org.koitharu.kotatsu.core.util.ext.tryLaunch
|
||||
import org.koitharu.kotatsu.core.util.ext.withArgs
|
||||
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
||||
import org.koitharu.kotatsu.filter.ui.FilterOwner
|
||||
@@ -23,9 +28,23 @@ import org.koitharu.kotatsu.filter.ui.sheet.FilterSheetFragment
|
||||
import org.koitharu.kotatsu.list.ui.MangaListFragment
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
|
||||
import org.koitharu.kotatsu.settings.storage.RequestStorageManagerPermissionContract
|
||||
import org.koitharu.kotatsu.settings.storage.directories.MangaDirectoriesActivity
|
||||
|
||||
class LocalListFragment : MangaListFragment(), FilterOwner {
|
||||
|
||||
private val permissionRequestLauncher = registerForActivityResult(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
RequestStorageManagerPermissionContract()
|
||||
} else {
|
||||
ActivityResultContracts.RequestPermission()
|
||||
},
|
||||
) {
|
||||
if (it) {
|
||||
viewModel.onRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
withArgs(1) {
|
||||
putSerializable(
|
||||
@@ -54,6 +73,16 @@ class LocalListFragment : MangaListFragment(), FilterOwner {
|
||||
FilterSheetFragment.show(childFragmentManager)
|
||||
}
|
||||
|
||||
override fun onPrimaryButtonClick(tipView: TipView) {
|
||||
if (!permissionRequestLauncher.tryLaunch(Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||
Snackbar.make(tipView, R.string.operation_not_supported, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSecondaryButtonClick(tipView: TipView) {
|
||||
startActivity(MangaDirectoriesActivity.newIntent(tipView.context))
|
||||
}
|
||||
|
||||
override fun onScrolledToEnd() = viewModel.loadNextPage()
|
||||
|
||||
override fun onCreateActionMode(
|
||||
|
||||
@@ -10,12 +10,18 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.toFileOrNull
|
||||
import org.koitharu.kotatsu.core.util.ext.toUriOrNull
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||
import org.koitharu.kotatsu.filter.ui.FilterCoordinator
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.MangaItemModel
|
||||
import org.koitharu.kotatsu.list.ui.model.TipModel
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageChanges
|
||||
import org.koitharu.kotatsu.local.data.LocalStorageManager
|
||||
import org.koitharu.kotatsu.local.domain.DeleteLocalMangaUseCase
|
||||
import org.koitharu.kotatsu.local.domain.model.LocalManga
|
||||
import org.koitharu.kotatsu.remotelist.ui.RemoteListViewModel
|
||||
@@ -32,6 +38,7 @@ class LocalListViewModel @Inject constructor(
|
||||
private val deleteLocalMangaUseCase: DeleteLocalMangaUseCase,
|
||||
exploreRepository: ExploreRepository,
|
||||
@LocalStorageChanges private val localStorageChanges: SharedFlow<LocalManga?>,
|
||||
private val localStorageManager: LocalStorageManager,
|
||||
) : RemoteListViewModel(
|
||||
savedStateHandle,
|
||||
mangaRepositoryFactory,
|
||||
@@ -54,6 +61,31 @@ class LocalListViewModel @Inject constructor(
|
||||
settings.subscribe(this)
|
||||
}
|
||||
|
||||
override suspend fun onBuildList(list: MutableList<ListModel>) {
|
||||
super.onBuildList(list)
|
||||
if (localStorageManager.hasExternalStoragePermission(isReadOnly = true)) {
|
||||
return
|
||||
}
|
||||
for (item in list) {
|
||||
if (item !is MangaItemModel) {
|
||||
continue
|
||||
}
|
||||
val file = item.manga.url.toUriOrNull()?.toFileOrNull() ?: continue
|
||||
if (localStorageManager.isOnExternalStorage(file)) {
|
||||
val tip = TipModel(
|
||||
key = "permission",
|
||||
title = R.string.external_storage,
|
||||
text = R.string.missing_storage_permission,
|
||||
icon = R.drawable.ic_storage,
|
||||
primaryButtonText = R.string.fix,
|
||||
secondaryButtonText = R.string.settings,
|
||||
)
|
||||
list.add(0, tip)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
settings.unsubscribe(this)
|
||||
super.onCleared()
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.koitharu.kotatsu.filter.ui.MangaFilter
|
||||
import org.koitharu.kotatsu.list.domain.ListExtraProvider
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
import org.koitharu.kotatsu.list.ui.model.EmptyState
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
|
||||
import org.koitharu.kotatsu.list.ui.model.LoadingState
|
||||
import org.koitharu.kotatsu.list.ui.model.toErrorFooter
|
||||
@@ -89,6 +90,7 @@ open class RemoteListViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
onBuildList(this)
|
||||
}
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
|
||||
|
||||
@@ -166,6 +168,8 @@ open class RemoteListViewModel @Inject constructor(
|
||||
actionStringRes = if (canResetFilter) R.string.reset_filter else 0,
|
||||
)
|
||||
|
||||
protected open suspend fun onBuildList(list: MutableList<ListModel>) = Unit
|
||||
|
||||
fun openRandom() {
|
||||
if (randomJob?.isActive == true) {
|
||||
return
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.ui.list.ListSelectionController
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.ui.widgets.TipView
|
||||
import org.koitharu.kotatsu.core.util.ShareHelper
|
||||
import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
@@ -140,6 +141,10 @@ class MultiSearchActivity :
|
||||
|
||||
override fun onListHeaderClick(item: ListHeader, view: View) = Unit
|
||||
|
||||
override fun onPrimaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onSecondaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onSelectionChanged(controller: ListSelectionController, count: Int) {
|
||||
viewBinding.recyclerView.invalidateNestedItemDecorations()
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
|
||||
import org.koitharu.kotatsu.core.ui.widgets.TipView
|
||||
import org.koitharu.kotatsu.core.util.ext.addMenuProvider
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||
@@ -100,6 +101,10 @@ class FeedFragment :
|
||||
|
||||
override fun onEmptyActionClick() = Unit
|
||||
|
||||
override fun onPrimaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onSecondaryButtonClick(tipView: TipView) = Unit
|
||||
|
||||
override fun onListHeaderClick(item: ListHeader, view: View) {
|
||||
val context = view.context
|
||||
context.startActivity(UpdatesActivity.newIntent(context))
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package org.koitharu.kotatsu.tracker.ui.feed.adapter
|
||||
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import coil.ImageLoader
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.util.ext.drawableStart
|
||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||
import org.koitharu.kotatsu.core.util.ext.source
|
||||
@@ -20,14 +22,13 @@ fun feedItemAD(
|
||||
) = adapterDelegateViewBinding<FeedItem, ListModel, ItemFeedBinding>(
|
||||
{ inflater, parent -> ItemFeedBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
val indicatorNew = ContextCompat.getDrawable(context, R.drawable.ic_new)
|
||||
|
||||
itemView.setOnClickListener {
|
||||
clickListener.onItemClick(item.manga, it)
|
||||
}
|
||||
|
||||
bind {
|
||||
val alpha = if (item.isNew) 1f else 0.5f
|
||||
binding.textViewTitle.alpha = alpha
|
||||
binding.textViewSummary.alpha = alpha
|
||||
binding.imageViewCover.newImageRequest(lifecycleOwner, item.imageUrl)?.run {
|
||||
placeholder(R.drawable.ic_placeholder)
|
||||
fallback(R.drawable.ic_placeholder)
|
||||
@@ -42,5 +43,10 @@ fun feedItemAD(
|
||||
item.count,
|
||||
item.count,
|
||||
)
|
||||
binding.textViewSummary.drawableStart = if (item.isNew) {
|
||||
indicatorNew
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<FrameLayout
|
||||
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="match_parent">
|
||||
|
||||
@@ -9,12 +10,19 @@
|
||||
android:id="@+id/ssiv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:restoreStrategy="deferred" />
|
||||
app:restoreStrategy="deferred"
|
||||
tools:background="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<ImageButton
|
||||
android:id="@+id/button_back"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="@dimen/screen_padding"
|
||||
android:background="@drawable/bg_circle_button"
|
||||
android:contentDescription="@string/back"
|
||||
android:elevation="4dp"
|
||||
android:scaleType="center"
|
||||
android:src="?homeAsUpIndicator" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progressBar"
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:drawablePadding="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
|
||||
@@ -649,4 +649,6 @@
|
||||
<string name="minutes_short">%d m</string>
|
||||
<!-- Short hours and minutes format pattern -->
|
||||
<string name="hours_minutes_short">%1$d h %2$d m</string>
|
||||
<string name="fix">Fix</string>
|
||||
<string name="missing_storage_permission">There is no permission to access manga on external storage</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user