From 24fe0306636a122e708b21549bebfb9b77360eee Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Sat, 18 Oct 2025 11:01:42 +0200 Subject: [PATCH] Add support for google drive share url. --- .../com/pixelized/desktop/lwa/Module.kt | 10 +++-- .../composable/image/DesaturatedAsyncImage.kt | 8 ++-- .../composable/image/ImagerModelConverter.kt | 19 ++++++++ .../lwa/ui/composable/image/LwaAsyncImage.kt | 44 +++++++++++++++++++ .../ui/overlay/portrait/PortraitOverlay.kt | 3 +- .../lwa/ui/screen/campaign/CampaignScreen.kt | 31 +++++++------ .../detail/inventory/item/InventoryItem.kt | 5 ++- .../common/CharacterRibbonAlteration.kt | 4 +- .../ribbon/common/CharacterRibbonPortrait.kt | 7 +-- .../lwa/ui/screen/levelup/LevelScreen.kt | 4 +- 10 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/ImagerModelConverter.kt create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/LwaAsyncImage.kt diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt index 650a4cf..7a9467f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt @@ -31,21 +31,22 @@ import com.pixelized.desktop.lwa.ui.composable.character.item.ItemDetailDialogFa import com.pixelized.desktop.lwa.ui.composable.character.item.ItemDetailDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogFactory import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.image.ImagerModelConverter import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlayViewModel import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel -import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkFactory -import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkViewModel -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonFactory -import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.CharacterDetailInventoryFactory +import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetFactory +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.NpcRibbonViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.text.CampaignChatViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.text.TextMessageFactory import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.CampaignToolbarViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesViewModel +import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkFactory +import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkViewModel import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterViewModel import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionUseCase import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel @@ -112,6 +113,7 @@ val toolsDependencies single { PathProvider(appName = "LwaClient") } + singleOf(::ImagerModelConverter) } val storeDependencies diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/DesaturatedAsyncImage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/DesaturatedAsyncImage.kt index aff7164..8d4f827 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/DesaturatedAsyncImage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/DesaturatedAsyncImage.kt @@ -6,12 +6,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush - import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.layout.ContentScale -import coil3.compose.AsyncImage import coil3.compose.AsyncImagePainter.Companion.DefaultTransform import coil3.compose.AsyncImagePainter.State import com.pixelized.desktop.lwa.utils.rememberBackgroundGradient @@ -32,8 +30,10 @@ fun DesaturatedAsyncImage( filterQuality: FilterQuality = FilterQuality.Low, clipToBounds: Boolean = true, ) { - Box(modifier = modifier) { - AsyncImage( + Box( + modifier = modifier, + ) { + LwaAsyncImage( model = model, contentDescription = contentDescription, modifier = Modifier.matchParentSize(), diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/ImagerModelConverter.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/ImagerModelConverter.kt new file mode 100644 index 0000000..8172ad0 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/ImagerModelConverter.kt @@ -0,0 +1,19 @@ +package com.pixelized.desktop.lwa.ui.composable.image + +class ImagerModelConverter { + + val googleDriveUrlRegex = Regex("""drive\.google\.com/file/d/([^/]*)""") + val workingGoogleDriveUri = "https://drive.google.com/uc?export=view&id=" + + fun convert( + model: Any?, + ): Any? { + return when (model) { + is String -> googleDriveUrlRegex.find(model)?.let { + val id = it.groupValues.getOrNull(1) + "$workingGoogleDriveUri$id" + } ?: model + else -> model + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/LwaAsyncImage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/LwaAsyncImage.kt new file mode 100644 index 0000000..5ea6cae --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/image/LwaAsyncImage.kt @@ -0,0 +1,44 @@ +package com.pixelized.desktop.lwa.ui.composable.image + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.DefaultAlpha +import androidx.compose.ui.graphics.FilterQuality +import androidx.compose.ui.layout.ContentScale +import coil3.compose.AsyncImage +import coil3.compose.AsyncImagePainter.Companion.DefaultTransform +import coil3.compose.AsyncImagePainter.State +import org.koin.compose.koinInject + +@Composable +fun LwaAsyncImage( + model: Any?, + modelConverter: ImagerModelConverter? = koinInject(), + contentDescription: String?, + modifier: Modifier = Modifier, + transform: (State) -> State = DefaultTransform, + onState: ((State) -> Unit)? = null, + alignment: Alignment = Alignment.Center, + contentScale: ContentScale = ContentScale.Fit, + alpha: Float = DefaultAlpha, + colorFilter: ColorFilter? = null, + filterQuality: FilterQuality = FilterQuality.Low, + clipToBounds: Boolean = true, +) { + AsyncImage( + modifier = modifier, + model = remember(modelConverter, model) { modelConverter?.convert(model) ?: model }, + contentDescription = contentDescription, + transform = transform, + onState = onState, + alignment = alignment, + contentScale = contentScale, + alpha = alpha, + colorFilter = colorFilter, + filterQuality = filterQuality, + clipToBounds = clipToBounds, + ) +} diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlay.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlay.kt index 4d4f2ce..1377216 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlay.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/portrait/PortraitOverlay.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage +import com.pixelized.desktop.lwa.ui.composable.image.LwaAsyncImage import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors import com.pixelized.desktop.lwa.ui.theme.lwa import kotlinx.coroutines.launch @@ -97,7 +98,7 @@ private fun PortraitContent( else -> Box( modifier = Modifier.fillMaxSize(), ) { - AsyncImage( + LwaAsyncImage( modifier = Modifier.matchParentSize(), model = it, filterQuality = FilterQuality.High, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt index d786bd3..c608e2a 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material.MaterialTheme @@ -351,14 +352,6 @@ private fun CampaignLayout( ) { main() - Box( - modifier = Modifier - .align(alignment = Alignment.Center) - .fillMaxSize(), - ) { - overlay() - } - Row { Box( modifier = Modifier @@ -368,13 +361,23 @@ private fun CampaignLayout( ) { leftPanel() } - Box( - modifier = Modifier - .align(alignment = Alignment.Bottom) - .weight(weight = 1f, fill = true) - .onSizeChanged { chatOverlayState.value = it.toDp(density) }, + Column( + modifier = Modifier.weight(weight = 1f, fill = true), ) { - chat() + Box( + modifier = Modifier + .fillMaxWidth() + .weight(weight = 1f, fill = true), + ) { + overlay() + } + Box( + modifier = Modifier + .fillMaxWidth() + .onSizeChanged { chatOverlayState.value = it.toDp(density) }, + ) { + chat() + } } Box( modifier = Modifier diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt index 07ac083..7cfa99d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/item/InventoryItem.kt @@ -44,10 +44,10 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import coil3.PlatformContext -import coil3.compose.AsyncImage import coil3.request.ImageRequest import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox import com.pixelized.desktop.lwa.ui.composable.image.DesaturatedAsyncImage +import com.pixelized.desktop.lwa.ui.composable.image.LwaAsyncImage import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipLayout import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.utils.extention.calculatePaddings @@ -194,7 +194,8 @@ fun InventoryItem( shape = CircleShape, ) ) - AsyncImage( + + LwaAsyncImage( modifier = Modifier .size(size = icon) .aspectRatio(ratio = 1f, matchHeightConstraintsFirst = true), diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt index 000d761..0286625 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt @@ -24,8 +24,8 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import coil3.PlatformContext -import coil3.compose.AsyncImage import coil3.request.ImageRequest +import com.pixelized.desktop.lwa.ui.composable.image.LwaAsyncImage import com.pixelized.desktop.lwa.ui.composable.tooltip.BasicTooltipLayout import com.pixelized.desktop.lwa.ui.composable.tooltip.BasicTooltipUio import com.pixelized.desktop.lwa.ui.theme.lwa @@ -74,7 +74,7 @@ fun CharacterRibbonAlteration( targetState = it.icon, transitionSpec = { fadeIn() togetherWith fadeOut() }, ) { icon -> - AsyncImage( + LwaAsyncImage( modifier = Modifier.size(24.dp), model = ImageRequest.Builder(context = PlatformContext.INSTANCE) .data(data = icon) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonPortrait.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonPortrait.kt index 983ceb0..1e74d3b 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonPortrait.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonPortrait.kt @@ -6,7 +6,6 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.PointerMatcher import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -18,7 +17,6 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.onClick import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme @@ -30,12 +28,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.graphics.FilterQuality -import androidx.compose.ui.input.pointer.PointerButton import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp -import coil3.compose.AsyncImage +import com.pixelized.desktop.lwa.ui.composable.image.LwaAsyncImage import com.pixelized.desktop.lwa.ui.composable.shapes.ArrowShape import com.pixelized.desktop.lwa.ui.theme.lwa import lwacharactersheet.composeapp.generated.resources.Res @@ -80,7 +77,7 @@ fun CharacterRibbonPortrait( targetState = character.portrait, transitionSpec = { fadeIn() togetherWith fadeOut() }, ) { portrait -> - AsyncImage( + LwaAsyncImage( modifier = Modifier.fillMaxSize(), model = portrait, contentScale = ContentScale.Crop, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt index 799d8d4..1d5e264 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt @@ -60,9 +60,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController -import coil3.compose.AsyncImage import com.pixelized.desktop.lwa.LocalRollHostState import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox +import com.pixelized.desktop.lwa.ui.composable.image.LwaAsyncImage import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController import com.pixelized.desktop.lwa.ui.navigation.screen.destination.LevelUpDestination @@ -204,7 +204,7 @@ private fun LevelUpContent( ) }, background = { - AsyncImage( + LwaAsyncImage( modifier = Modifier.matchParentSize(), model = header.value?.portrait, contentScale = ContentScale.FillHeight,