mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
refactor: Use Compose for EmptyView
This commit is contained in:
parent
b1665eaedf
commit
5824ac81c2
13 changed files with 228 additions and 95 deletions
|
@ -5,6 +5,8 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import android.view.MenuItem
|
||||
import android.widget.LinearLayout
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.FileDownloadOff
|
||||
import androidx.core.view.WindowInsetsCompat.Type.systemBars
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
|
@ -212,7 +214,7 @@ class DownloadBottomSheet @JvmOverloads constructor(
|
|||
setBottomSheet()
|
||||
if (presenter.downloadQueueState.value.isEmpty()) {
|
||||
binding.emptyView.show(
|
||||
R.drawable.ic_download_off_24dp,
|
||||
Icons.Filled.FileDownloadOff,
|
||||
MR.strings.nothing_is_downloading,
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -28,6 +28,8 @@ import android.widget.ImageView
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.HeartBroken
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.ViewCompat
|
||||
|
@ -1135,7 +1137,7 @@ open class LibraryController(
|
|||
binding.emptyView.hide()
|
||||
} else {
|
||||
binding.emptyView.show(
|
||||
R.drawable.ic_heart_off_24dp,
|
||||
Icons.Filled.HeartBroken,
|
||||
if (hasActiveFilters) {
|
||||
MR.strings.no_matches_for_filters
|
||||
} else {
|
||||
|
|
|
@ -18,6 +18,8 @@ import android.widget.TextView
|
|||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.SearchOff
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.WindowInsetsCompat.Type.systemBars
|
||||
|
@ -31,7 +33,6 @@ import com.google.android.material.datepicker.MaterialDatePicker
|
|||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import com.mikepenz.fastadapter.listeners.addClickListener
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
|
@ -317,7 +318,7 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
|
|||
if (results.isEmpty()) {
|
||||
setMiddleTrackView(binding.searchEmptyView.id)
|
||||
binding.searchEmptyView.show(
|
||||
R.drawable.ic_search_off_24dp,
|
||||
Icons.Filled.SearchOff,
|
||||
MR.strings.no_results_found,
|
||||
)
|
||||
} else {
|
||||
|
@ -338,7 +339,7 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) :
|
|||
binding.trackSearchRecycler.isVisible = false
|
||||
searchItemAdapter.clear()
|
||||
binding.searchEmptyView.show(
|
||||
R.drawable.ic_search_off_24dp,
|
||||
Icons.Filled.SearchOff,
|
||||
error.message ?: "",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import android.view.View
|
|||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.HeartBroken
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.util.Pair
|
||||
|
@ -458,7 +460,10 @@ class StatsDetailsController :
|
|||
with(binding ?: headerBinding) {
|
||||
val hasNoData = currentStats.isNullOrEmpty() || currentStats.all { it.count == 0 }
|
||||
if (hasNoData) {
|
||||
this@StatsDetailsController.binding.noChartData.show(R.drawable.ic_heart_off_24dp, MR.strings.no_data_for_filters)
|
||||
this@StatsDetailsController.binding.noChartData.show(
|
||||
Icons.Filled.HeartBroken,
|
||||
MR.strings.no_data_for_filters,
|
||||
)
|
||||
presenter.currentStats?.removeAll { it.count == 0 }
|
||||
handleNoChartLayout()
|
||||
this?.statsPieChart?.isVisible = false
|
||||
|
|
|
@ -12,6 +12,9 @@ import android.view.RoundedCorner
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.BackEventCompat
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.HistoryToggleOff
|
||||
import androidx.compose.material.icons.filled.SearchOff
|
||||
import androidx.core.view.WindowInsetsCompat.Type.systemBars
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -596,9 +599,9 @@ class RecentsController(bundle: Bundle? = null) :
|
|||
if (recents.isEmpty()) {
|
||||
binding.recentsEmptyView.show(
|
||||
if (!isSearching()) {
|
||||
R.drawable.ic_history_off_24dp
|
||||
Icons.Filled.HistoryToggleOff
|
||||
} else {
|
||||
R.drawable.ic_search_off_24dp
|
||||
Icons.Filled.SearchOff
|
||||
},
|
||||
if (isSearching()) {
|
||||
MR.strings.no_results_found
|
||||
|
|
|
@ -75,8 +75,8 @@ class RecentsPresenter(
|
|||
}
|
||||
private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED)
|
||||
private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS)
|
||||
private val continueReadingHeader =
|
||||
RecentMangaHeaderItem(RecentMangaHeaderItem.CONTINUE_READING)
|
||||
private val continueReadingHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.CONTINUE_READING)
|
||||
|
||||
var finished = false
|
||||
private var shouldMoveToTop = false
|
||||
var viewType: RecentsViewType = RecentsViewType.valueOf(uiPreferences.recentsViewType().get())
|
||||
|
|
|
@ -7,6 +7,8 @@ import android.view.MenuInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Book
|
||||
import androidx.core.view.WindowInsetsCompat.Type.systemBars
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isInvisible
|
||||
|
@ -193,7 +195,7 @@ class ClearDatabaseController :
|
|||
binding.emptyView.hide()
|
||||
} else {
|
||||
binding.emptyView.show(
|
||||
R.drawable.ic_book_24dp,
|
||||
Icons.Filled.Book,
|
||||
MR.strings.database_clean,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import android.view.MenuInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExploreOff
|
||||
import androidx.core.view.WindowInsetsCompat.Type.ime
|
||||
import androidx.core.view.WindowInsetsCompat.Type.systemBars
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -62,7 +64,6 @@ import eu.kanade.tachiyomi.widget.EmptyView
|
|||
import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset
|
||||
import kotlin.math.roundToInt
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
@ -577,7 +578,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
|||
snack?.dismiss()
|
||||
|
||||
val message = getErrorMessage(error)
|
||||
val retryAction = View.OnClickListener {
|
||||
val retryAction = {
|
||||
// If not the first page, show bottom binding.progress bar.
|
||||
if (adapter.mainItemCount > 0 && progressItem != null) {
|
||||
adapter.addScrollableFooterWithDelay(progressItem!!, 0, true)
|
||||
|
@ -606,16 +607,16 @@ open class BrowseSourceController(bundle: Bundle) :
|
|||
|
||||
binding.emptyView.show(
|
||||
if (presenter.source is HttpSource) {
|
||||
R.drawable.ic_browse_off_24dp
|
||||
EmptyView.Image.Vector(Icons.Filled.ExploreOff)
|
||||
} else {
|
||||
R.drawable.ic_local_library_24dp
|
||||
EmptyView.Image.ResourceVector(R.drawable.ic_local_library_24dp)
|
||||
},
|
||||
message,
|
||||
actions,
|
||||
)
|
||||
} else {
|
||||
snack = binding.sourceLayout.snack(message, Snackbar.LENGTH_INDEFINITE) {
|
||||
setAction(MR.strings.retry, retryAction)
|
||||
setAction(MR.strings.retry) { retryAction() }
|
||||
}
|
||||
}
|
||||
if (isControllerVisible) {
|
||||
|
|
12
app/src/main/java/eu/kanade/tachiyomi/util/WindowSize.kt
Normal file
12
app/src/main/java/eu/kanade/tachiyomi/util/WindowSize.kt
Normal file
|
@ -0,0 +1,12 @@
|
|||
package eu.kanade.tachiyomi.util
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import eu.kanade.tachiyomi.util.system.isTablet
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun isTablet(): Boolean {
|
||||
return LocalConfiguration.current.isTablet()
|
||||
}
|
|
@ -54,6 +54,8 @@ import yokai.i18n.MR
|
|||
|
||||
private const val TABLET_UI_MIN_SCREEN_WIDTH_DP = 720
|
||||
|
||||
private const val TABLET_UI_MIN_SCREEN_WIDTH_LANDSCAPE_DP = 600
|
||||
|
||||
/**
|
||||
* Helper method to create a notification.
|
||||
*
|
||||
|
@ -113,7 +115,8 @@ fun Float.dpToPxEnd(resources: Resources): Float {
|
|||
val Resources.isLTR
|
||||
get() = configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR
|
||||
|
||||
fun Context.isTablet() = resources.configuration.smallestScreenWidthDp >= 600
|
||||
fun Configuration.isTablet() = smallestScreenWidthDp >= TABLET_UI_MIN_SCREEN_WIDTH_LANDSCAPE_DP
|
||||
fun Context.isTablet() = resources.configuration.isTablet()
|
||||
|
||||
val displayMaxHeightInPx: Int
|
||||
get() = Resources.getSystem().displayMetrics.let { max(it.heightPixels, it.widthPixels) }
|
||||
|
|
|
@ -2,28 +2,60 @@ package eu.kanade.tachiyomi.widget
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import android.view.Gravity
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.AbstractComposeView
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.CommonViewEmptyBinding
|
||||
import eu.kanade.tachiyomi.util.view.setText
|
||||
import eu.kanade.tachiyomi.util.view.setVectorCompat
|
||||
import eu.kanade.tachiyomi.util.isTablet
|
||||
import yokai.presentation.component.EmptyScreen
|
||||
import yokai.presentation.theme.YokaiTheme
|
||||
import yokai.util.lang.getString
|
||||
import android.R as AR
|
||||
|
||||
class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
RelativeLayout(context, attrs) {
|
||||
class EmptyView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : AbstractComposeView(context, attrs, defStyleAttr) {
|
||||
|
||||
private val binding: CommonViewEmptyBinding =
|
||||
CommonViewEmptyBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
private var image by mutableStateOf<Image>(Image.Vector(Icons.Filled.Download))
|
||||
private var message by mutableStateOf("")
|
||||
private var actions by mutableStateOf(emptyList<Action>())
|
||||
|
||||
init {
|
||||
layoutParams = FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER)
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun image(): ImageVector {
|
||||
return when (image) {
|
||||
is Image.Vector -> (image as Image.Vector).image
|
||||
is Image.ResourceVector -> ImageVector.vectorResource((image as Image.ResourceVector).id)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
YokaiTheme {
|
||||
EmptyScreen(
|
||||
image = image(),
|
||||
message = message,
|
||||
isTablet = isTablet(),
|
||||
actions = actions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the information view
|
||||
|
@ -36,16 +68,21 @@ class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
* Show the information view
|
||||
* @param textResource text of information view
|
||||
*/
|
||||
fun show(@DrawableRes drawable: Int, textResource: StringResource, actions: List<Action>? = null) {
|
||||
show(drawable, context.getString(textResource), actions)
|
||||
fun show(image: ImageVector, textResource: StringResource, actions: List<Action> = emptyList()) {
|
||||
show(Image.Vector(image), context.getString(textResource), actions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the information view
|
||||
* @param textResource text of information view
|
||||
*/
|
||||
fun show(@DrawableRes drawable: Int, @StringRes textResource: Int, actions: List<Action>? = null) {
|
||||
show(drawable, context.getString(textResource), actions)
|
||||
fun show(image: ImageVector, @StringRes textResource: Int, actions: List<Action> = emptyList()) {
|
||||
show(Image.Vector(image), context.getString(textResource), actions)
|
||||
}
|
||||
|
||||
@Deprecated("Use EmptyView.Image instead of passing ImageVector directly")
|
||||
fun show(image: ImageVector, message: String, actions: List<Action> = emptyList()) {
|
||||
show(Image.Vector(image), message, actions)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,36 +90,20 @@ class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||
* @param drawable icon of information view
|
||||
* @param textResource text of information view
|
||||
*/
|
||||
fun show(@DrawableRes drawable: Int, message: String, actions: List<Action>? = null) {
|
||||
binding.imageView.setVectorCompat(drawable, AR.attr.textColorHint)
|
||||
binding.textLabel.text = message
|
||||
|
||||
binding.actionsContainer.removeAllViews()
|
||||
binding.actionsContainer.isVisible = !actions.isNullOrEmpty()
|
||||
if (!actions.isNullOrEmpty()) {
|
||||
actions.forEach {
|
||||
val button =
|
||||
(inflate(context, R.layout.material_text_button, null) as MaterialButton)
|
||||
.apply {
|
||||
setText(it.resId)
|
||||
setOnClickListener(it.listener)
|
||||
}
|
||||
binding.actionsContainer.addView(button)
|
||||
if (context.resources.configuration.screenHeightDp < 600) {
|
||||
button.textAlignment = View.TEXT_ALIGNMENT_TEXT_START
|
||||
button.updateLayoutParams<MarginLayoutParams> {
|
||||
width = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun show(image: Image, message: String, actions: List<Action> = emptyList()) {
|
||||
this.image = image
|
||||
this.message = message
|
||||
this.actions = actions
|
||||
this.isVisible = true
|
||||
}
|
||||
|
||||
data class Action(
|
||||
val resId: StringResource,
|
||||
val listener: OnClickListener,
|
||||
val listener: () -> Unit,
|
||||
)
|
||||
|
||||
sealed class Image {
|
||||
data class Vector(val image: ImageVector) : Image()
|
||||
data class ResourceVector(val id: Int) : Image()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.content.res.Configuration
|
|||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
@ -13,6 +15,7 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -21,7 +24,11 @@ import androidx.compose.ui.graphics.ImageBitmap
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import eu.kanade.tachiyomi.util.compose.textHint
|
||||
import eu.kanade.tachiyomi.widget.EmptyView
|
||||
import yokai.i18n.MR
|
||||
|
||||
private val defaultIconModifier =
|
||||
Modifier.size(128.dp)
|
||||
|
@ -34,8 +41,9 @@ fun EmptyScreen(
|
|||
modifier: Modifier = Modifier,
|
||||
image: ImageVector,
|
||||
message: String,
|
||||
actions: @Composable () -> Unit = {},
|
||||
) = EmptyScreen(
|
||||
isTablet: Boolean,
|
||||
actions: List<EmptyView.Action> = emptyList(),
|
||||
) = EmptyScreenImpl(
|
||||
modifier = modifier,
|
||||
image = {
|
||||
Image(
|
||||
|
@ -46,7 +54,8 @@ fun EmptyScreen(
|
|||
)
|
||||
},
|
||||
message = message,
|
||||
actions = actions,
|
||||
actions = { EmptyScreenActions(actions, isTablet) },
|
||||
isTablet = isTablet,
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
@ -54,8 +63,9 @@ fun EmptyScreen(
|
|||
modifier: Modifier = Modifier,
|
||||
image: ImageBitmap,
|
||||
message: String,
|
||||
actions: @Composable () -> Unit = {},
|
||||
) = EmptyScreen(
|
||||
isTablet: Boolean,
|
||||
actions: List<EmptyView.Action> = emptyList(),
|
||||
) = EmptyScreenImpl(
|
||||
modifier = modifier,
|
||||
image = {
|
||||
Image(
|
||||
|
@ -65,35 +75,104 @@ fun EmptyScreen(
|
|||
)
|
||||
},
|
||||
message = message,
|
||||
actions = actions,
|
||||
actions = { EmptyScreenActions(actions, isTablet) },
|
||||
isTablet = isTablet,
|
||||
)
|
||||
|
||||
@Preview(name = "Light", uiMode = Configuration.UI_MODE_NIGHT_NO, showBackground = true)
|
||||
@Composable
|
||||
private fun EmptyScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
image: @Composable () -> Unit = {
|
||||
Image(modifier = defaultIconModifier, imageVector = Icons.Filled.Download, contentDescription = null)
|
||||
},
|
||||
message: String = "Something went wrong",
|
||||
actions: @Composable () -> Unit = {},
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
image()
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp),
|
||||
text = message,
|
||||
color = MaterialTheme.colorScheme.textHint,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
actions()
|
||||
private fun EmptyScreenActions(actions: List<EmptyView.Action>, isTablet: Boolean) {
|
||||
if (isTablet) {
|
||||
FlowRow {
|
||||
actions.forEach { action ->
|
||||
TextButton(onClick = { action.listener() }) {
|
||||
Text(
|
||||
text = stringResource(action.resId),
|
||||
fontSize = 14.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
actions.forEach { action ->
|
||||
TextButton(onClick = { action.listener() }) {
|
||||
Text(
|
||||
text = stringResource(action.resId),
|
||||
fontSize = 14.sp,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EmptyScreenImpl(
|
||||
modifier: Modifier = Modifier,
|
||||
image: @Composable () -> Unit,
|
||||
message: String,
|
||||
actions: @Composable () -> Unit,
|
||||
isTablet: Boolean,
|
||||
) {
|
||||
if (isTablet) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Row {
|
||||
image()
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 4.dp),
|
||||
text = message,
|
||||
color = MaterialTheme.colorScheme.textHint,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
actions()
|
||||
}
|
||||
} else {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
image()
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp),
|
||||
text = message,
|
||||
color = MaterialTheme.colorScheme.textHint,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
actions()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true)
|
||||
@Preview(name = "Light", uiMode = Configuration.UI_MODE_NIGHT_NO, showBackground = true)
|
||||
@Composable
|
||||
private fun EmptyScreenPreview() {
|
||||
EmptyScreen(
|
||||
image = Icons.Filled.Download,
|
||||
message = "Something went wrong",
|
||||
actions = listOf(
|
||||
EmptyView.Action(MR.strings.download) {},
|
||||
EmptyView.Action(MR.strings.download) {},
|
||||
EmptyView.Action(MR.strings.download) {},
|
||||
EmptyView.Action(MR.strings.download) {},
|
||||
EmptyView.Action(MR.strings.download) {},
|
||||
),
|
||||
isTablet = false,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import dev.icerock.moko.resources.compose.stringResource
|
|||
import eu.kanade.tachiyomi.util.compose.LocalAlertDialog
|
||||
import eu.kanade.tachiyomi.util.compose.LocalBackPress
|
||||
import eu.kanade.tachiyomi.util.compose.currentOrThrow
|
||||
import eu.kanade.tachiyomi.util.isTablet
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import yokai.domain.ComposableAlertDialog
|
||||
|
@ -101,6 +102,7 @@ fun ExtensionRepoScreen(
|
|||
modifier = Modifier.fillParentMaxSize(),
|
||||
image = Icons.Filled.ExtensionOff,
|
||||
message = stringResource(MR.strings.information_empty_repos),
|
||||
isTablet = isTablet(),
|
||||
)
|
||||
}
|
||||
return@LazyColumn
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue