Add support for google drive share url.

This commit is contained in:
Thomas Andres Gomez 2025-10-18 11:01:42 +02:00
parent c5f4a3e46e
commit 24fe030663
10 changed files with 101 additions and 34 deletions

View file

@ -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.item.ItemDetailDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogFactory 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.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.portrait.PortraitOverlayViewModel
import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel 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.CharacterDetailPanelViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderFactory 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.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.NpcRibbonViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonViewModel 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.CampaignChatViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.text.TextMessageFactory 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.CampaignToolbarViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesViewModel 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.GameMasterViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionUseCase import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionUseCase
import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel
@ -112,6 +113,7 @@ val toolsDependencies
single { single {
PathProvider(appName = "LwaClient") PathProvider(appName = "LwaClient")
} }
singleOf(::ImagerModelConverter)
} }
val storeDependencies val storeDependencies

View file

@ -6,12 +6,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter.Companion.DefaultTransform import coil3.compose.AsyncImagePainter.Companion.DefaultTransform
import coil3.compose.AsyncImagePainter.State import coil3.compose.AsyncImagePainter.State
import com.pixelized.desktop.lwa.utils.rememberBackgroundGradient import com.pixelized.desktop.lwa.utils.rememberBackgroundGradient
@ -32,8 +30,10 @@ fun DesaturatedAsyncImage(
filterQuality: FilterQuality = FilterQuality.Low, filterQuality: FilterQuality = FilterQuality.Low,
clipToBounds: Boolean = true, clipToBounds: Boolean = true,
) { ) {
Box(modifier = modifier) { Box(
AsyncImage( modifier = modifier,
) {
LwaAsyncImage(
model = model, model = model,
contentDescription = contentDescription, contentDescription = contentDescription,
modifier = Modifier.matchParentSize(), modifier = Modifier.matchParentSize(),

View file

@ -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
}
}
}

View file

@ -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<ImagerModelConverter?>(),
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,
)
}

View file

@ -30,6 +30,7 @@ import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage 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.color.component.LwaButtonColors
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -97,7 +98,7 @@ private fun PortraitContent(
else -> Box( else -> Box(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) { ) {
AsyncImage( LwaAsyncImage(
modifier = Modifier.matchParentSize(), modifier = Modifier.matchParentSize(),
model = it, model = it,
filterQuality = FilterQuality.High, filterQuality = FilterQuality.High,

View file

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
@ -351,14 +352,6 @@ private fun CampaignLayout(
) { ) {
main() main()
Box(
modifier = Modifier
.align(alignment = Alignment.Center)
.fillMaxSize(),
) {
overlay()
}
Row { Row {
Box( Box(
modifier = Modifier modifier = Modifier
@ -368,14 +361,24 @@ private fun CampaignLayout(
) { ) {
leftPanel() leftPanel()
} }
Column(
modifier = Modifier.weight(weight = 1f, fill = true),
) {
Box( Box(
modifier = Modifier modifier = Modifier
.align(alignment = Alignment.Bottom) .fillMaxWidth()
.weight(weight = 1f, fill = true) .weight(weight = 1f, fill = true),
) {
overlay()
}
Box(
modifier = Modifier
.fillMaxWidth()
.onSizeChanged { chatOverlayState.value = it.toDp(density) }, .onSizeChanged { chatOverlayState.value = it.toDp(density) },
) { ) {
chat() chat()
} }
}
Box( Box(
modifier = Modifier modifier = Modifier
.width(width = MaterialTheme.lwa.dimen.layout.panelWidth) .width(width = MaterialTheme.lwa.dimen.layout.panelWidth)

View file

@ -44,10 +44,10 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.PlatformContext import coil3.PlatformContext
import coil3.compose.AsyncImage
import coil3.request.ImageRequest import coil3.request.ImageRequest
import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox 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.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.composable.tooltip.TooltipLayout
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.desktop.lwa.utils.extention.calculatePaddings import com.pixelized.desktop.lwa.utils.extention.calculatePaddings
@ -194,7 +194,8 @@ fun InventoryItem(
shape = CircleShape, shape = CircleShape,
) )
) )
AsyncImage(
LwaAsyncImage(
modifier = Modifier modifier = Modifier
.size(size = icon) .size(size = icon)
.aspectRatio(ratio = 1f, matchHeightConstraintsFirst = true), .aspectRatio(ratio = 1f, matchHeightConstraintsFirst = true),

View file

@ -24,8 +24,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.PlatformContext import coil3.PlatformContext
import coil3.compose.AsyncImage
import coil3.request.ImageRequest 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.BasicTooltipLayout
import com.pixelized.desktop.lwa.ui.composable.tooltip.BasicTooltipUio import com.pixelized.desktop.lwa.ui.composable.tooltip.BasicTooltipUio
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
@ -74,7 +74,7 @@ fun CharacterRibbonAlteration(
targetState = it.icon, targetState = it.icon,
transitionSpec = { fadeIn() togetherWith fadeOut() }, transitionSpec = { fadeIn() togetherWith fadeOut() },
) { icon -> ) { icon ->
AsyncImage( LwaAsyncImage(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
model = ImageRequest.Builder(context = PlatformContext.INSTANCE) model = ImageRequest.Builder(context = PlatformContext.INSTANCE)
.data(data = icon) .data(data = icon)

View file

@ -6,7 +6,6 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.PointerMatcher
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box 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.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.onClick
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.IconButton import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme 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.clip
import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp 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.composable.shapes.ArrowShape
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
@ -80,7 +77,7 @@ fun CharacterRibbonPortrait(
targetState = character.portrait, targetState = character.portrait,
transitionSpec = { fadeIn() togetherWith fadeOut() }, transitionSpec = { fadeIn() togetherWith fadeOut() },
) { portrait -> ) { portrait ->
AsyncImage( LwaAsyncImage(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
model = portrait, model = portrait,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,

View file

@ -60,9 +60,9 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import coil3.compose.AsyncImage
import com.pixelized.desktop.lwa.LocalRollHostState import com.pixelized.desktop.lwa.LocalRollHostState
import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox 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.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.LevelUpDestination import com.pixelized.desktop.lwa.ui.navigation.screen.destination.LevelUpDestination
@ -204,7 +204,7 @@ private fun LevelUpContent(
) )
}, },
background = { background = {
AsyncImage( LwaAsyncImage(
modifier = Modifier.matchParentSize(), modifier = Modifier.matchParentSize(),
model = header.value?.portrait, model = header.value?.portrait,
contentScale = ContentScale.FillHeight, contentScale = ContentScale.FillHeight,