mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-29 12:37:50 +02:00
Split UpdatesGridGlanceWidget into smaller bits (#8991)
- Renamed Composables - Moved Constants to core module
This commit is contained in:
@ -1,20 +0,0 @@
|
||||
package tachiyomi.presentation.widget
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
|
||||
fun GlanceModifier.appWidgetBackgroundRadius(): GlanceModifier {
|
||||
return this.cornerRadius(R.dimen.appwidget_background_radius)
|
||||
}
|
||||
|
||||
fun GlanceModifier.appWidgetInnerRadius(): GlanceModifier {
|
||||
return this.cornerRadius(R.dimen.appwidget_inner_radius)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun stringResource(@StringRes id: Int): String {
|
||||
return LocalContext.current.getString(id)
|
||||
}
|
@ -8,10 +8,14 @@ import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
object TachiyomiWidgetManager {
|
||||
class TachiyomiWidgetManager(
|
||||
private val database: DatabaseHandler = Injekt.get(),
|
||||
) {
|
||||
|
||||
fun Context.init(scope: LifecycleCoroutineScope, database: DatabaseHandler) {
|
||||
fun Context.init(scope: LifecycleCoroutineScope) {
|
||||
database.subscribeToList { updatesViewQueries.updates(after = UpdatesGridGlanceWidget.DateLimit.timeInMillis) }
|
||||
.drop(1)
|
||||
.distinctUntilChanged()
|
||||
|
@ -1,41 +1,19 @@
|
||||
package tachiyomi.presentation.widget
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.Image
|
||||
import androidx.glance.ImageProvider
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.LocalSize
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.CircularProgressIndicator
|
||||
import androidx.glance.appwidget.GlanceAppWidget
|
||||
import androidx.glance.appwidget.GlanceAppWidgetManager
|
||||
import androidx.glance.appwidget.SizeMode
|
||||
import androidx.glance.appwidget.action.actionStartActivity
|
||||
import androidx.glance.appwidget.appWidgetBackground
|
||||
import androidx.glance.appwidget.updateAll
|
||||
import androidx.glance.background
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.ContentScale
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.layout.size
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextAlign
|
||||
import androidx.glance.text.TextStyle
|
||||
import androidx.glance.unit.ColorProvider
|
||||
import coil.executeBlocking
|
||||
import coil.imageLoader
|
||||
import coil.request.CachePolicy
|
||||
@ -49,6 +27,10 @@ import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import kotlinx.coroutines.MainScope
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import tachiyomi.presentation.widget.components.CoverHeight
|
||||
import tachiyomi.presentation.widget.components.CoverWidth
|
||||
import tachiyomi.presentation.widget.components.LockedWidget
|
||||
import tachiyomi.presentation.widget.components.UpdatesWidget
|
||||
import tachiyomi.view.UpdatesView
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -62,127 +44,18 @@ class UpdatesGridGlanceWidget : GlanceAppWidget() {
|
||||
|
||||
private val coroutineScope = MainScope()
|
||||
|
||||
var data: List<Pair<Long, Bitmap?>>? = null
|
||||
private var data: List<Pair<Long, Bitmap?>>? = null
|
||||
|
||||
override val sizeMode = SizeMode.Exact
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
// App lock enabled, don't do anything
|
||||
// If app lock enabled, don't do anything
|
||||
if (preferences.useAuthenticator().get()) {
|
||||
WidgetNotAvailable()
|
||||
} else {
|
||||
UpdatesWidget()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WidgetNotAvailable() {
|
||||
val clazz = Class.forName("eu.kanade.tachiyomi.ui.main.MainActivity")
|
||||
val intent = Intent(LocalContext.current, clazz).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.clickable(actionStartActivity(intent))
|
||||
.then(ContainerModifier)
|
||||
.padding(8.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.appwidget_unavailable_locked),
|
||||
style = TextStyle(
|
||||
color = ColorProvider(R.color.appwidget_on_secondary_container),
|
||||
fontSize = 12.sp,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UpdatesWidget() {
|
||||
val (rowCount, columnCount) = LocalSize.current.calculateRowAndColumnCount()
|
||||
Column(
|
||||
modifier = ContainerModifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
val inData = data
|
||||
if (inData == null) {
|
||||
CircularProgressIndicator()
|
||||
} else if (inData.isEmpty()) {
|
||||
Text(text = stringResource(R.string.information_no_recent))
|
||||
} else {
|
||||
(0 until rowCount).forEach { i ->
|
||||
val coverRow = (0 until columnCount).mapNotNull { j ->
|
||||
inData.getOrNull(j + (i * columnCount))
|
||||
}
|
||||
if (coverRow.isNotEmpty()) {
|
||||
Row(
|
||||
modifier = GlanceModifier
|
||||
.padding(vertical = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
coverRow.forEach { (mangaId, cover) ->
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.padding(horizontal = 3.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
val intent = Intent(LocalContext.current, Class.forName("eu.kanade.tachiyomi.ui.main.MainActivity")).apply {
|
||||
action = "eu.kanade.tachiyomi.SHOW_MANGA"
|
||||
putExtra("manga", mangaId)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
|
||||
// https://issuetracker.google.com/issues/238793260
|
||||
addCategory(mangaId.toString())
|
||||
}
|
||||
Cover(
|
||||
modifier = GlanceModifier.clickable(actionStartActivity(intent)),
|
||||
cover = cover,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Cover(
|
||||
modifier: GlanceModifier = GlanceModifier,
|
||||
cover: Bitmap?,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(width = CoverWidth, height = CoverHeight)
|
||||
.appWidgetInnerRadius(),
|
||||
) {
|
||||
if (cover != null) {
|
||||
Image(
|
||||
provider = ImageProvider(cover),
|
||||
contentDescription = null,
|
||||
modifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.appWidgetInnerRadius(),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
} else {
|
||||
// Enjoy placeholder
|
||||
Image(
|
||||
provider = ImageProvider(R.drawable.appwidget_cover_error),
|
||||
contentDescription = null,
|
||||
modifier = GlanceModifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
}
|
||||
LockedWidget()
|
||||
return
|
||||
}
|
||||
UpdatesWidget(data)
|
||||
}
|
||||
|
||||
fun loadData(list: List<UpdatesView>? = null) {
|
||||
@ -254,32 +127,8 @@ class UpdatesGridGlanceWidget : GlanceAppWidget() {
|
||||
}
|
||||
}
|
||||
|
||||
private val CoverWidth = 58.dp
|
||||
private val CoverHeight = 87.dp
|
||||
|
||||
private val ContainerModifier = GlanceModifier
|
||||
val ContainerModifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.background(ImageProvider(R.drawable.appwidget_background))
|
||||
.appWidgetBackground()
|
||||
.appWidgetBackgroundRadius()
|
||||
|
||||
/**
|
||||
* Calculates row-column count.
|
||||
*
|
||||
* Row
|
||||
* Numerator: Container height - container vertical padding
|
||||
* Denominator: Cover height + cover vertical padding
|
||||
*
|
||||
* Column
|
||||
* Numerator: Container width - container horizontal padding
|
||||
* Denominator: Cover width + cover horizontal padding
|
||||
*
|
||||
* @return pair of row and column count
|
||||
*/
|
||||
private fun DpSize.calculateRowAndColumnCount(): Pair<Int, Int> {
|
||||
// Hack: Size provided by Glance manager is not reliable so take at least 1 row and 1 column
|
||||
// Set max to 10 children each direction because of Glance limitation
|
||||
val rowCount = (height.value / 95).toInt().coerceIn(1, 10)
|
||||
val columnCount = (width.value / 64).toInt().coerceIn(1, 10)
|
||||
return Pair(rowCount, columnCount)
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package tachiyomi.presentation.widget.components
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.action.actionStartActivity
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.text.Text
|
||||
import androidx.glance.text.TextAlign
|
||||
import androidx.glance.text.TextStyle
|
||||
import androidx.glance.unit.ColorProvider
|
||||
import tachiyomi.core.Constants
|
||||
import tachiyomi.presentation.widget.ContainerModifier
|
||||
import tachiyomi.presentation.widget.R
|
||||
import tachiyomi.presentation.widget.stringResource
|
||||
|
||||
@Composable
|
||||
fun LockedWidget() {
|
||||
val intent = Intent(LocalContext.current, Class.forName(Constants.MAIN_ACTIVITY)).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.clickable(actionStartActivity(intent))
|
||||
.then(ContainerModifier)
|
||||
.padding(8.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.appwidget_unavailable_locked),
|
||||
style = TextStyle(
|
||||
color = ColorProvider(R.color.appwidget_on_secondary_container),
|
||||
fontSize = 12.sp,
|
||||
textAlign = TextAlign.Center,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package tachiyomi.presentation.widget.components
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.Image
|
||||
import androidx.glance.ImageProvider
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.ContentScale
|
||||
import androidx.glance.layout.fillMaxSize
|
||||
import androidx.glance.layout.size
|
||||
import tachiyomi.presentation.widget.R
|
||||
import tachiyomi.presentation.widget.appWidgetInnerRadius
|
||||
|
||||
val CoverWidth = 58.dp
|
||||
val CoverHeight = 87.dp
|
||||
|
||||
@Composable
|
||||
fun UpdatesMangaCover(
|
||||
modifier: GlanceModifier = GlanceModifier,
|
||||
cover: Bitmap?,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(width = CoverWidth, height = CoverHeight)
|
||||
.appWidgetInnerRadius(),
|
||||
) {
|
||||
if (cover != null) {
|
||||
Image(
|
||||
provider = ImageProvider(cover),
|
||||
contentDescription = null,
|
||||
modifier = GlanceModifier
|
||||
.fillMaxSize()
|
||||
.appWidgetInnerRadius(),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
} else {
|
||||
// Enjoy placeholder
|
||||
Image(
|
||||
provider = ImageProvider(R.drawable.appwidget_cover_error),
|
||||
contentDescription = null,
|
||||
modifier = GlanceModifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package tachiyomi.presentation.widget.components
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.LocalSize
|
||||
import androidx.glance.action.clickable
|
||||
import androidx.glance.appwidget.CircularProgressIndicator
|
||||
import androidx.glance.appwidget.action.actionStartActivity
|
||||
import androidx.glance.layout.Alignment
|
||||
import androidx.glance.layout.Box
|
||||
import androidx.glance.layout.Column
|
||||
import androidx.glance.layout.Row
|
||||
import androidx.glance.layout.fillMaxWidth
|
||||
import androidx.glance.layout.padding
|
||||
import androidx.glance.text.Text
|
||||
import tachiyomi.core.Constants
|
||||
import tachiyomi.presentation.widget.ContainerModifier
|
||||
import tachiyomi.presentation.widget.R
|
||||
import tachiyomi.presentation.widget.calculateRowAndColumnCount
|
||||
import tachiyomi.presentation.widget.stringResource
|
||||
|
||||
@Composable
|
||||
fun UpdatesWidget(data: List<Pair<Long, Bitmap?>>?) {
|
||||
val (rowCount, columnCount) = LocalSize.current.calculateRowAndColumnCount()
|
||||
Column(
|
||||
modifier = ContainerModifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
if (data == null) {
|
||||
CircularProgressIndicator()
|
||||
} else if (data.isEmpty()) {
|
||||
Text(text = stringResource(R.string.information_no_recent))
|
||||
} else {
|
||||
(0 until rowCount).forEach { i ->
|
||||
val coverRow = (0 until columnCount).mapNotNull { j ->
|
||||
data.getOrNull(j + (i * columnCount))
|
||||
}
|
||||
if (coverRow.isNotEmpty()) {
|
||||
Row(
|
||||
modifier = GlanceModifier
|
||||
.padding(vertical = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
coverRow.forEach { (mangaId, cover) ->
|
||||
Box(
|
||||
modifier = GlanceModifier
|
||||
.padding(horizontal = 3.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
val intent = Intent(LocalContext.current, Class.forName(Constants.MAIN_ACTIVITY)).apply {
|
||||
action = Constants.SHORTCUT_MANGA
|
||||
putExtra(Constants.MANGA_EXTRA, mangaId)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
|
||||
// https://issuetracker.google.com/issues/238793260
|
||||
addCategory(mangaId.toString())
|
||||
}
|
||||
UpdatesMangaCover(
|
||||
modifier = GlanceModifier.clickable(actionStartActivity(intent)),
|
||||
cover = cover,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package tachiyomi.presentation.widget
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.glance.GlanceModifier
|
||||
import androidx.glance.LocalContext
|
||||
import androidx.glance.appwidget.cornerRadius
|
||||
|
||||
fun GlanceModifier.appWidgetBackgroundRadius(): GlanceModifier {
|
||||
return this.cornerRadius(R.dimen.appwidget_background_radius)
|
||||
}
|
||||
|
||||
fun GlanceModifier.appWidgetInnerRadius(): GlanceModifier {
|
||||
return this.cornerRadius(R.dimen.appwidget_inner_radius)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun stringResource(@StringRes id: Int): String {
|
||||
return LocalContext.current.getString(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates row-column count.
|
||||
*
|
||||
* Row
|
||||
* Numerator: Container height - container vertical padding
|
||||
* Denominator: Cover height + cover vertical padding
|
||||
*
|
||||
* Column
|
||||
* Numerator: Container width - container horizontal padding
|
||||
* Denominator: Cover width + cover horizontal padding
|
||||
*
|
||||
* @return pair of row and column count
|
||||
*/
|
||||
fun DpSize.calculateRowAndColumnCount(): Pair<Int, Int> {
|
||||
// Hack: Size provided by Glance manager is not reliable so take at least 1 row and 1 column
|
||||
// Set max to 10 children each direction because of Glance limitation
|
||||
val rowCount = (height.value / 95).toInt().coerceIn(1, 10)
|
||||
val columnCount = (width.value / 64).toInt().coerceIn(1, 10)
|
||||
return Pair(rowCount, columnCount)
|
||||
}
|
Reference in New Issue
Block a user