Add static resource managment to (image) to the client.
This commit is contained in:
parent
1c9b1c49b1
commit
9f0198ce53
12 changed files with 67 additions and 46 deletions
|
|
@ -34,7 +34,7 @@ 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.usecase.ImagerModelLogic
|
||||||
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.admin.AdminViewModel
|
import com.pixelized.desktop.lwa.ui.screen.admin.AdminViewModel
|
||||||
|
|
@ -77,7 +77,7 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkViewM
|
||||||
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpFactory
|
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpFactory
|
||||||
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpViewModel
|
import com.pixelized.desktop.lwa.ui.screen.levelup.LevelUpViewModel
|
||||||
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsViewModel
|
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsViewModel
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
|
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
|
||||||
import com.pixelized.shared.lwa.utils.PathProvider
|
import com.pixelized.shared.lwa.utils.PathProvider
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
|
|
@ -122,7 +122,7 @@ val toolsDependencies
|
||||||
single {
|
single {
|
||||||
PathProvider(appName = "LwaClient")
|
PathProvider(appName = "LwaClient")
|
||||||
}
|
}
|
||||||
singleOf(::ImagerModelConverter)
|
singleOf(::ImagerModelLogic)
|
||||||
}
|
}
|
||||||
|
|
||||||
val storeDependencies
|
val storeDependencies
|
||||||
|
|
@ -218,6 +218,6 @@ val viewModelDependencies
|
||||||
|
|
||||||
val useCaseDependencies
|
val useCaseDependencies
|
||||||
get() = module {
|
get() = module {
|
||||||
factoryOf(::SettingsUseCase)
|
factoryOf(::SettingsLogic)
|
||||||
factoryOf(::GMActionUseCase)
|
factoryOf(::GMActionUseCase)
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ package com.pixelized.desktop.lwa.repository.resources
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
import androidx.compose.ui.graphics.toComposeImageBitmap
|
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||||
import com.pixelized.desktop.lwa.ui.composable.image.ImagerModelConverter
|
import com.pixelized.desktop.lwa.usecase.ImagerModelLogic
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.readRawBytes
|
import io.ktor.client.statement.readRawBytes
|
||||||
|
|
@ -10,11 +10,11 @@ import org.jetbrains.skia.Image
|
||||||
|
|
||||||
class ImageResourcesRepository(
|
class ImageResourcesRepository(
|
||||||
private val httpClient: HttpClient,
|
private val httpClient: HttpClient,
|
||||||
private val googleImageConverter: ImagerModelConverter,
|
private val imageConverter: ImagerModelLogic,
|
||||||
) {
|
) {
|
||||||
suspend fun load(url: String): ImageBitmap {
|
suspend fun load(url: String): ImageBitmap {
|
||||||
try {
|
try {
|
||||||
val unwrapUri = googleImageConverter.unwrap(model = url)
|
val unwrapUri = imageConverter.unwrap(model = url)
|
||||||
val byteArray = httpClient.get(unwrapUri).readRawBytes()
|
val byteArray = httpClient.get(unwrapUri).readRawBytes()
|
||||||
val skiaImage = Image.makeFromEncoded(byteArray)
|
val skiaImage = Image.makeFromEncoded(byteArray)
|
||||||
return skiaImage.toComposeImageBitmap()
|
return skiaImage.toComposeImageBitmap()
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
|
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV1
|
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV1
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV2
|
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV2
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
|
|
||||||
|
|
||||||
class SettingsFactory(
|
class SettingsFactory(
|
||||||
private val useCase: SettingsUseCase,
|
private val useCase: SettingsLogic,
|
||||||
) {
|
) {
|
||||||
fun convertToJson(
|
fun convertToJson(
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package com.pixelized.desktop.lwa.repository.settings
|
package com.pixelized.desktop.lwa.repository.settings
|
||||||
|
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
class SettingsRepository(
|
class SettingsRepository(
|
||||||
private val store: SettingsStore,
|
private val store: SettingsStore,
|
||||||
private val useCase: SettingsUseCase,
|
private val useCase: SettingsLogic,
|
||||||
) {
|
) {
|
||||||
fun settingsFlow(): StateFlow<Settings> = store.settingsFlow
|
fun settingsFlow(): StateFlow<Settings> = store.settingsFlow
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package com.pixelized.desktop.lwa.repository.settings
|
||||||
|
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
|
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
import com.pixelized.shared.lwa.utils.PathProvider
|
import com.pixelized.shared.lwa.utils.PathProvider
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -13,7 +13,7 @@ import java.io.File
|
||||||
class SettingsStore(
|
class SettingsStore(
|
||||||
private val pathProvider: PathProvider,
|
private val pathProvider: PathProvider,
|
||||||
private val factory: SettingsFactory,
|
private val factory: SettingsFactory,
|
||||||
private val useCase: SettingsUseCase,
|
private val useCase: SettingsLogic,
|
||||||
private val jsonFormatter: Json,
|
private val jsonFormatter: Json,
|
||||||
) {
|
) {
|
||||||
private val _settingsFlow = MutableStateFlow(value = useCase.defaultSettings())
|
private val _settingsFlow = MutableStateFlow(value = useCase.defaultSettings())
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
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 -> unwrap(model = model)
|
|
||||||
else -> model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unwrap(
|
|
||||||
model: String,
|
|
||||||
): String {
|
|
||||||
return googleDriveUrlRegex.find(model)?.let {
|
|
||||||
val id = it.groupValues.getOrNull(1)
|
|
||||||
"$workingGoogleDriveUri$id"
|
|
||||||
} ?: model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,12 +11,13 @@ import androidx.compose.ui.layout.ContentScale
|
||||||
import coil3.compose.AsyncImage
|
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.usecase.ImagerModelLogic
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LwaAsyncImage(
|
fun LwaAsyncImage(
|
||||||
model: Any?,
|
model: Any?,
|
||||||
modelConverter: ImagerModelConverter? = koinInject<ImagerModelConverter?>(),
|
modelConverter: ImagerModelLogic? = koinInject<ImagerModelLogic?>(),
|
||||||
contentDescription: String?,
|
contentDescription: String?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
transform: (State) -> State = DefaultTransform,
|
transform: (State) -> State = DefaultTransform,
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.chatbox.messages.RollTextMes
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.chatbox.messages.RollTextMessageUio
|
import com.pixelized.desktop.lwa.ui.screen.campaign.chatbox.messages.RollTextMessageUio
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.chatbox.messages.TextMessage
|
import com.pixelized.desktop.lwa.ui.screen.campaign.chatbox.messages.TextMessage
|
||||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
import lwacharactersheet.composeapp.generated.resources.Res
|
import lwacharactersheet.composeapp.generated.resources.Res
|
||||||
import lwacharactersheet.composeapp.generated.resources.ic_more_down_24dp
|
import lwacharactersheet.composeapp.generated.resources.ic_more_down_24dp
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
|
@ -64,7 +64,7 @@ data class ChatSettingsUio(
|
||||||
val autoScroll: Boolean,
|
val autoScroll: Boolean,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
fun default() = with(SettingsUseCase().defaultSettings()) {
|
fun default() = with(SettingsLogic().defaultSettings()) {
|
||||||
ChatSettingsUio(
|
ChatSettingsUio(
|
||||||
show = chat.showChat,
|
show = chat.showChat,
|
||||||
autoScroll = chat.autoScrollChat,
|
autoScroll = chat.autoScrollChat,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
|
||||||
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingNumberItemUio
|
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingNumberItemUio
|
||||||
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingSectionUio
|
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingSectionUio
|
||||||
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingToggleItemUio
|
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingToggleItemUio
|
||||||
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
|
import com.pixelized.desktop.lwa.usecase.SettingsLogic
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import lwacharactersheet.composeapp.generated.resources.Res
|
import lwacharactersheet.composeapp.generated.resources.Res
|
||||||
import lwacharactersheet.composeapp.generated.resources.ic_fan_focus_24dp
|
import lwacharactersheet.composeapp.generated.resources.ic_fan_focus_24dp
|
||||||
|
|
@ -29,7 +29,7 @@ import lwacharactersheet.composeapp.generated.resources.settings__player_portrai
|
||||||
|
|
||||||
class SettingsViewModel(
|
class SettingsViewModel(
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
private val settingsUseCase: SettingsUseCase,
|
private val settingsLogic: SettingsLogic,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val settings = settingsRepository.settingsFlow()
|
private val settings = settingsRepository.settingsFlow()
|
||||||
private val booleanStates = hashMapOf<String, MutableState<Boolean>>()
|
private val booleanStates = hashMapOf<String, MutableState<Boolean>>()
|
||||||
|
|
@ -132,7 +132,7 @@ class SettingsViewModel(
|
||||||
fun onReset() {
|
fun onReset() {
|
||||||
val current = settingsRepository.settings()
|
val current = settingsRepository.settings()
|
||||||
settingsRepository.update(
|
settingsRepository.update(
|
||||||
settings = settingsUseCase.defaultSettings().copy(
|
settings = settingsLogic.defaultSettings().copy(
|
||||||
playerName = current.playerName,
|
playerName = current.playerName,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.pixelized.desktop.lwa.usecase
|
||||||
|
|
||||||
|
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
|
class ImagerModelLogic(
|
||||||
|
settingsRepo: SettingsRepository, // not sure about those import into a Logic class.
|
||||||
|
settingsLogic: SettingsLogic,
|
||||||
|
) {
|
||||||
|
val googleDriveUrlRegex = Regex("""drive\.google\.com/file/d/([^/]*)""")
|
||||||
|
val workingGoogleDriveUri = "https://drive.google.com/uc?export=view&id="
|
||||||
|
|
||||||
|
val localUrlRegex = Regex("""^/resources/.*$""")
|
||||||
|
val workingLocalUrl = settingsRepo.settingsFlow()
|
||||||
|
.map { it.network.root }
|
||||||
|
.stateIn(
|
||||||
|
scope = CoroutineScope(Dispatchers.IO + Job()),
|
||||||
|
started = SharingStarted.Eagerly,
|
||||||
|
initialValue = settingsLogic.defaultSettings(),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun convert(
|
||||||
|
model: Any?,
|
||||||
|
): Any? {
|
||||||
|
return when (model) {
|
||||||
|
is String -> unwrap(model = model)
|
||||||
|
else -> model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unwrap(
|
||||||
|
model: String,
|
||||||
|
): String {
|
||||||
|
return googleDriveUrlRegex.find(model)?.let {
|
||||||
|
val id = it.groupValues.getOrNull(1)
|
||||||
|
"$workingGoogleDriveUri$id"
|
||||||
|
} ?: localUrlRegex.find(model)?.let {
|
||||||
|
"${workingLocalUrl.value}$model"
|
||||||
|
} ?: model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ package com.pixelized.desktop.lwa.usecase
|
||||||
|
|
||||||
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
import com.pixelized.desktop.lwa.repository.settings.model.Settings
|
||||||
|
|
||||||
class SettingsUseCase {
|
class SettingsLogic {
|
||||||
|
|
||||||
fun defaultSettings(): Settings = Settings(
|
fun defaultSettings(): Settings = Settings(
|
||||||
playerName = "",
|
playerName = "",
|
||||||
|
|
@ -148,7 +148,6 @@ class LocalServer {
|
||||||
staticFiles(
|
staticFiles(
|
||||||
remotePath = "/resources",
|
remotePath = "/resources",
|
||||||
dir = File(pathProvider.resourcesPath()),
|
dir = File(pathProvider.resourcesPath()),
|
||||||
index = null,
|
|
||||||
)
|
)
|
||||||
route(path = "/campaign") {
|
route(path = "/campaign") {
|
||||||
get(
|
get(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue