Add a download link to a portrait.
This commit is contained in:
parent
7dd5ade1f5
commit
ca5d01c0ca
3 changed files with 85 additions and 22 deletions
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M440,680L280,680Q197,680 138.5,621.5Q80,563 80,480Q80,397 138.5,338.5Q197,280 280,280L440,280L440,360L280,360Q230,360 195,395Q160,430 160,480Q160,530 195,565Q230,600 280,600L440,600L440,680ZM320,520L320,440L640,440L640,520L320,520ZM520,680L520,600L680,600Q730,600 765,565Q800,530 800,480Q800,430 765,395Q730,360 680,360L520,360L520,280L680,280Q763,280 821.5,338.5Q880,397 880,480Q880,563 821.5,621.5Q763,680 680,680L520,680Z" />
|
||||
</vector>
|
||||
|
|
@ -2,15 +2,18 @@ package com.pixelized.desktop.lwa.ui.overlay.portrait
|
|||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
|
@ -23,9 +26,16 @@ import com.pixelized.desktop.lwa.ui.theme.lwa
|
|||
import kotlinx.coroutines.launch
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
@Stable
|
||||
data class PortraitOptionUio(
|
||||
val isBrowserAvailable: Boolean,
|
||||
val isGameMaster: Boolean,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun PortraitOverlay(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -33,13 +43,16 @@ fun PortraitOverlay(
|
|||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val portrait = viewModel.portrait.collectAsState()
|
||||
val isGameMaster = viewModel.isGameMaster.collectAsState()
|
||||
val options = viewModel.options.collectAsState()
|
||||
|
||||
PortraitContent(
|
||||
modifier = modifier,
|
||||
portrait = portrait,
|
||||
isGameMaster = isGameMaster,
|
||||
onGameMaster = {
|
||||
options = options,
|
||||
onDownload = { url ->
|
||||
viewModel.browse(url)
|
||||
},
|
||||
onClose = {
|
||||
scope.launch {
|
||||
viewModel.dismissPortrait()
|
||||
}
|
||||
|
|
@ -51,8 +64,9 @@ fun PortraitOverlay(
|
|||
private fun PortraitContent(
|
||||
modifier: Modifier = Modifier,
|
||||
portrait: State<String?>,
|
||||
isGameMaster: State<Boolean>,
|
||||
onGameMaster: () -> Unit,
|
||||
options: State<PortraitOptionUio>,
|
||||
onDownload: (url: String) -> Unit,
|
||||
onClose: () -> Unit,
|
||||
) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier
|
||||
|
|
@ -65,11 +79,11 @@ private fun PortraitContent(
|
|||
) {
|
||||
when (it) {
|
||||
null -> Box(
|
||||
modifier = Modifier.size(MaterialTheme.lwa.size.portrait.maximized)
|
||||
modifier = Modifier.size(size = MaterialTheme.lwa.size.portrait.maximized)
|
||||
)
|
||||
|
||||
else -> Box(
|
||||
modifier = Modifier.size(MaterialTheme.lwa.size.portrait.maximized)
|
||||
modifier = Modifier.size(size = MaterialTheme.lwa.size.portrait.maximized)
|
||||
) {
|
||||
AsyncImage(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
|
|
@ -78,20 +92,40 @@ private fun PortraitContent(
|
|||
contentDescription = null
|
||||
)
|
||||
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.align(alignment = Alignment.TopEnd),
|
||||
visible = isGameMaster.value,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.TopEnd)
|
||||
.animateContentSize(),
|
||||
) {
|
||||
IconButton(
|
||||
onClick = onGameMaster,
|
||||
AnimatedVisibility(
|
||||
visible = options.value.isBrowserAvailable,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_cancel_24dp),
|
||||
tint = MaterialTheme.lwa.colorScheme.base.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
IconButton(
|
||||
onClick = { onDownload(it) },
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_link_24dp),
|
||||
tint = MaterialTheme.lwa.colorScheme.base.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = options.value.isGameMaster,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
IconButton(
|
||||
onClick = onClose,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_cancel_24dp),
|
||||
tint = MaterialTheme.lwa.colorScheme.base.primary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.flatMapLatest
|
|||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import java.awt.Desktop
|
||||
import java.net.URI
|
||||
|
||||
class PortraitOverlayViewModel(
|
||||
private val networkRepository: NetworkRepository,
|
||||
|
|
@ -32,12 +34,21 @@ class PortraitOverlayViewModel(
|
|||
initialValue = null
|
||||
)
|
||||
|
||||
val isGameMaster = settingsRepository.settingsFlow()
|
||||
.map { settings -> settings.isGameMaster ?: false }
|
||||
val options = settingsRepository.settingsFlow()
|
||||
.map { settings ->
|
||||
PortraitOptionUio(
|
||||
isGameMaster = settings.isGameMaster ?: false,
|
||||
isBrowserAvailable = Desktop.isDesktopSupported()
|
||||
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)
|
||||
)
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = false
|
||||
initialValue = PortraitOptionUio(
|
||||
isGameMaster = false,
|
||||
isBrowserAvailable = false,
|
||||
)
|
||||
)
|
||||
|
||||
suspend fun dismissPortrait() {
|
||||
|
|
@ -48,4 +59,13 @@ class PortraitOverlayViewModel(
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun browse(url: String) {
|
||||
if (Desktop.isDesktopSupported()) {
|
||||
val desktop = Desktop.getDesktop()
|
||||
if (desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||
desktop.browse(URI.create(url))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue