Polish ItemScreen
This commit is contained in:
parent
01ce06467d
commit
3417466e30
@ -8,10 +8,10 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.readrops.app.R
|
||||
import com.readrops.app.util.DefaultPreview
|
||||
import com.readrops.app.util.components.SelectableIconText
|
||||
import com.readrops.app.util.components.dialog.BaseDialog
|
||||
import com.readrops.app.util.components.SelectableImageText
|
||||
import com.readrops.app.util.theme.spacing
|
||||
|
||||
enum class ItemImageChoice {
|
||||
@ -30,25 +30,32 @@ fun ItemImageDialog(
|
||||
onDismiss = onDismiss
|
||||
) {
|
||||
Column {
|
||||
SelectableImageText(
|
||||
image = rememberVectorPainter(image = Icons.Default.Share),
|
||||
SelectableIconText(
|
||||
icon = rememberVectorPainter(image = Icons.Default.Share),
|
||||
text = stringResource(id = R.string.share_image),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
spacing = MaterialTheme.spacing.shortSpacing,
|
||||
spacing = MaterialTheme.spacing.mediumSpacing,
|
||||
padding = MaterialTheme.spacing.shortSpacing,
|
||||
imageSize = 16.dp,
|
||||
onClick = { onChoice(ItemImageChoice.SHARE) }
|
||||
)
|
||||
|
||||
SelectableImageText(
|
||||
image = painterResource(id = R.drawable.ic_download),
|
||||
SelectableIconText(
|
||||
icon = painterResource(id = R.drawable.ic_download),
|
||||
text = stringResource(id = R.string.download_image),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
spacing = MaterialTheme.spacing.shortSpacing,
|
||||
spacing = MaterialTheme.spacing.mediumSpacing,
|
||||
padding = MaterialTheme.spacing.shortSpacing,
|
||||
imageSize = 16.dp,
|
||||
onClick = { onChoice(ItemImageChoice.DOWNLOAD) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreview
|
||||
@Composable
|
||||
private fun ItemImageDialogPreview() {
|
||||
ItemImageDialog(
|
||||
onChoice = {},
|
||||
onDismiss = {}
|
||||
)
|
||||
}
|
@ -13,9 +13,13 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
@ -51,12 +55,15 @@ import androidx.core.net.toUri
|
||||
import androidx.core.view.children
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import cafe.adriel.voyager.koin.getScreenModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import coil.compose.AsyncImage
|
||||
import com.readrops.app.R
|
||||
import com.readrops.app.item.view.ItemNestedScrollView
|
||||
import com.readrops.app.item.view.ItemWebView
|
||||
import com.readrops.app.util.components.AndroidScreen
|
||||
import com.readrops.app.util.components.CenteredProgressIndicator
|
||||
import com.readrops.app.util.components.FeedIcon
|
||||
import com.readrops.app.util.components.IconText
|
||||
import com.readrops.app.util.theme.MediumSpacer
|
||||
import com.readrops.app.util.theme.ShortSpacer
|
||||
@ -74,6 +81,7 @@ class ItemScreen(
|
||||
override fun Content() {
|
||||
val context = LocalContext.current
|
||||
val density = LocalDensity.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val screenModel =
|
||||
getScreenModel<ItemScreenModel>(parameters = { parametersOf(itemId) })
|
||||
@ -122,7 +130,7 @@ class ItemScreen(
|
||||
|
||||
LaunchedEffect(state.fileDownloadedEvent) {
|
||||
if (state.fileDownloadedEvent) {
|
||||
snackbarHostState.showSnackbar("Downloaded file!")
|
||||
snackbarHostState.showSnackbar(context.getString(R.string.downloaded_file))
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +144,12 @@ class ItemScreen(
|
||||
primaryColor
|
||||
}
|
||||
|
||||
val colorScheme = when (state.theme) {
|
||||
"light" -> CustomTabsIntent.COLOR_SCHEME_LIGHT
|
||||
"dark" -> CustomTabsIntent.COLOR_SCHEME_DARK
|
||||
else -> CustomTabsIntent.COLOR_SCHEME_SYSTEM
|
||||
}
|
||||
|
||||
fun openUrl(url: String) {
|
||||
if (state.openInExternalBrowser) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
@ -150,14 +164,14 @@ class ItemScreen(
|
||||
)
|
||||
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
|
||||
.setUrlBarHidingEnabled(true)
|
||||
.setColorScheme(colorScheme)
|
||||
.build()
|
||||
.launchUrl(context, url.toUri())
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
.nestedScroll(nestedScrollConnection),
|
||||
modifier = Modifier.nestedScroll(nestedScrollConnection),
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
bottomBar = {
|
||||
ItemScreenBottomBar(
|
||||
@ -194,6 +208,7 @@ class ItemScreen(
|
||||
factory = { context ->
|
||||
ItemNestedScrollView(
|
||||
context = context,
|
||||
useBackgroundTitle = item.imageLink != null,
|
||||
onGlobalLayoutListener = { viewHeight, contentHeight ->
|
||||
isScrollable = viewHeight - contentHeight < 0
|
||||
},
|
||||
@ -203,19 +218,27 @@ class ItemScreen(
|
||||
if (item.imageLink != null) {
|
||||
BackgroundTitle(itemWithFeed = itemWithFeed)
|
||||
} else {
|
||||
val tintColor = if (itemWithFeed.color != 0) {
|
||||
Color(itemWithFeed.color)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onBackground
|
||||
}
|
||||
Box {
|
||||
IconButton(
|
||||
onClick = { navigator.pop() },
|
||||
modifier = Modifier
|
||||
.statusBarsPadding()
|
||||
.align(Alignment.TopStart)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
SimpleTitle(
|
||||
itemWithFeed = itemWithFeed,
|
||||
titleColor = tintColor,
|
||||
accentColor = tintColor,
|
||||
baseColor = MaterialTheme.colorScheme.onBackground,
|
||||
bottomPadding = true
|
||||
)
|
||||
SimpleTitle(
|
||||
itemWithFeed = itemWithFeed,
|
||||
titleColor = accentColor,
|
||||
accentColor = accentColor,
|
||||
baseColor = MaterialTheme.colorScheme.onBackground,
|
||||
bottomPadding = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -248,6 +271,8 @@ class ItemScreen(
|
||||
fun BackgroundTitle(
|
||||
itemWithFeed: ItemWithFeed,
|
||||
) {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val onScrimColor = Color.White.copy(alpha = 0.85f)
|
||||
val accentColor = if (itemWithFeed.color != 0) {
|
||||
Color(itemWithFeed.color)
|
||||
@ -276,13 +301,28 @@ fun BackgroundTitle(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
SimpleTitle(
|
||||
itemWithFeed = itemWithFeed,
|
||||
titleColor = onScrimColor,
|
||||
accentColor = accentColor,
|
||||
baseColor = onScrimColor,
|
||||
bottomPadding = true
|
||||
)
|
||||
Box {
|
||||
IconButton(
|
||||
onClick = { navigator.pop() },
|
||||
modifier = Modifier
|
||||
.statusBarsPadding()
|
||||
.align(Alignment.TopStart)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.ArrowBack,
|
||||
contentDescription = null,
|
||||
tint = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
SimpleTitle(
|
||||
itemWithFeed = itemWithFeed,
|
||||
titleColor = onScrimColor,
|
||||
accentColor = accentColor,
|
||||
baseColor = onScrimColor,
|
||||
bottomPadding = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,14 +349,11 @@ fun SimpleTitle(
|
||||
bottom = if (bottomPadding) spacing else 0.dp
|
||||
)
|
||||
) {
|
||||
AsyncImage(
|
||||
model = itemWithFeed.feedIconUrl,
|
||||
contentDescription = itemWithFeed.feedName,
|
||||
placeholder = painterResource(id = R.drawable.ic_rss_feed_grey),
|
||||
error = painterResource(id = R.drawable.ic_rss_feed_grey),
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(CircleShape)
|
||||
FeedIcon(
|
||||
iconUrl = itemWithFeed.feedIconUrl,
|
||||
name = itemWithFeed.feedName,
|
||||
size = 48.dp,
|
||||
modifier = Modifier.clip(CircleShape)
|
||||
)
|
||||
|
||||
ShortSpacer()
|
||||
|
@ -24,6 +24,7 @@ import com.readrops.db.queries.ItemSelectionQueryBuilder
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
@ -81,17 +82,22 @@ class ItemScreenModel(
|
||||
}
|
||||
|
||||
screenModelScope.launch(dispatcher) {
|
||||
preferences.openLinksWith.flow
|
||||
.collect { value ->
|
||||
mutableState.update {
|
||||
it.copy(
|
||||
openInExternalBrowser = when (value) {
|
||||
"external_navigator" -> true
|
||||
else -> false
|
||||
}
|
||||
)
|
||||
}
|
||||
combine(
|
||||
preferences.openLinksWith.flow,
|
||||
preferences.theme.flow
|
||||
) { openLinksWith, theme ->
|
||||
openLinksWith to theme
|
||||
}.collect { (openLinksWith, theme) ->
|
||||
mutableState.update {
|
||||
it.copy(
|
||||
openInExternalBrowser = when (openLinksWith) {
|
||||
"external_navigator" -> true
|
||||
else -> false
|
||||
},
|
||||
theme = theme
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,5 +192,6 @@ data class ItemState(
|
||||
val bottomBarState: BottomBarState = BottomBarState(),
|
||||
val imageDialogUrl: String? = null,
|
||||
val fileDownloadedEvent: Boolean = false,
|
||||
val openInExternalBrowser: Boolean = false
|
||||
val openInExternalBrowser: Boolean = false,
|
||||
val theme: String? = ""
|
||||
)
|
@ -11,6 +11,7 @@ import androidx.core.widget.NestedScrollView
|
||||
@SuppressLint("ResourceType", "ViewConstructor")
|
||||
class ItemNestedScrollView(
|
||||
context: Context,
|
||||
useBackgroundTitle: Boolean,
|
||||
onGlobalLayoutListener: (viewHeight: Int, contentHeight: Int) -> Unit,
|
||||
onUrlClick: (String) -> Unit,
|
||||
onImageLongPress: (String) -> Unit,
|
||||
@ -54,6 +55,12 @@ class ItemNestedScrollView(
|
||||
webViewParams.addRule(RelativeLayout.BELOW, composeView.id)
|
||||
webView.layoutParams = webViewParams
|
||||
|
||||
if (useBackgroundTitle) {
|
||||
val density = resources.displayMetrics.density
|
||||
val dpAsPixels = (8 * density + 0.5f).toInt()
|
||||
composeView.setPadding(0, 0, 0, dpAsPixels)
|
||||
}
|
||||
|
||||
addView(composeView)
|
||||
addView(webView)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import com.readrops.app.util.FeedKey
|
||||
fun FeedIcon(
|
||||
iconUrl: String?,
|
||||
name: String,
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = 24.dp
|
||||
) {
|
||||
AsyncImage(
|
||||
@ -22,6 +23,6 @@ fun FeedIcon(
|
||||
placeholder = painterResource(R.drawable.ic_rss_feed_grey),
|
||||
fallback = painterResource(id = R.drawable.ic_rss_feed_grey),
|
||||
contentDescription = name,
|
||||
modifier = Modifier.size(size)
|
||||
modifier = modifier.size(size)
|
||||
)
|
||||
}
|
@ -217,4 +217,5 @@
|
||||
<string name="litecoin_copy_address">Litecoin (copier l\'adresse)</string>
|
||||
<string name="donation_text">"Si vous considérez que mon travail vous est utile et si vous souhaitez me soutenir, vous pouvez me faire une donation. "</string>
|
||||
<string name="add_feed">Ajouter un flux</string>
|
||||
<string name="downloaded_file">Fichier téléchargé !</string>
|
||||
</resources>
|
@ -230,4 +230,5 @@
|
||||
<string name="litecoin_copy_address">Litecoin (copy address)</string>
|
||||
<string name="donation_text">I you find my work useful and you would like to support me, you can consider making me a donation.</string>
|
||||
<string name="add_feed">Add feed</string>
|
||||
<string name="downloaded_file">Downloaded file!</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user