Add directories to distingish between pixelized apps.

This commit is contained in:
Thomas Andres Gomez 2025-03-02 10:20:52 +01:00
parent 03df369e0b
commit 3f67e342a7
18 changed files with 178 additions and 108 deletions

View file

@ -31,6 +31,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import coil3.ImageLoader
import coil3.compose.setSingletonImageLoaderFactory
import coil3.request.crossfade
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository.Status
import com.pixelized.desktop.lwa.ui.composable.key.KeyEventHandler
@ -85,6 +88,13 @@ fun ApplicationScope.App() {
val windowController = remember { WindowController(maxWindowHeight) }
val keyEventHandlers = remember { mutableStateListOf<KeyEventHandler>() }
// Coil configuration
setSingletonImageLoaderFactory { context ->
ImageLoader.Builder(context)
.crossfade(enable = false)
.build()
}
CompositionLocalProvider(
LocalSnackHost provides snackHostState,
LocalErrorSnackHost provides errorSnackHostState,

View file

@ -33,6 +33,7 @@ import com.pixelized.desktop.lwa.ui.screen.roll.RollViewModel
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryViewModel
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
import com.pixelized.shared.lwa.utils.PathProvider
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
@ -67,7 +68,12 @@ val toolsDependencies
}
}
}
single<LwaClient> { LwaClientImpl(get(), get()) }
single<LwaClient> {
LwaClientImpl(get(), get())
}
single {
PathProvider(appName = "LwaClient")
}
}
val storeDependencies

View file

@ -1,9 +1,9 @@
package com.pixelized.desktop.lwa.repository.settings
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import com.pixelized.desktop.lwa.repository.settings.model.Settings
import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson
import com.pixelized.shared.lwa.storePath
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import com.pixelized.shared.lwa.utils.PathProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -14,6 +14,7 @@ import kotlinx.serialization.json.Json
import java.io.File
class SettingsStore(
private val pathProvider: PathProvider,
private val factory: SettingsFactory,
private val useCase: SettingsUseCase,
private val jsonFormatter: Json,
@ -24,7 +25,7 @@ class SettingsStore(
init {
// create the directory
File(storePath()).also { it.mkdirs() }
File(pathProvider.storePath()).also { it.mkdirs() }
// load the data.
val scope = CoroutineScope(Dispatchers.IO + Job())
scope.launch {
@ -80,7 +81,7 @@ class SettingsStore(
}
private fun settingsFile(): File {
return File("${storePath()}settings.json")
return File("${pathProvider.storePath()}settings.json")
}
sealed class SettingsStoreException(root: Exception) : Exception(root)

View file

@ -1,5 +1,12 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.EaseOutCirc
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -7,7 +14,9 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@ -23,8 +32,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.DpSize
@ -36,6 +45,8 @@ import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_heart_24dp
import lwacharactersheet.composeapp.generated.resources.ic_water_drop_24dp
import org.jetbrains.compose.resources.painterResource
import kotlin.math.max
import kotlin.math.min
@Stable
data class PlayerPortraitUio(
@ -48,10 +59,17 @@ data class PlayerPortraitUio(
val maxPp: Int,
)
object PlayerPortrait {
object Default {
val bloodColor = Color(0xbb0a1e).copy(alpha = 0.25f)
}
}
@Composable
fun PlayerPortrait(
modifier: Modifier = Modifier,
size: DpSize,
bloodColor: Color = PlayerPortrait.Default.bloodColor,
character: PlayerPortraitUio,
onCharacter: (id: Campaign.CharacterInstance.Id) -> Unit,
) {
@ -64,14 +82,26 @@ fun PlayerPortrait(
.background(color = colorScheme.elevated.base1dp)
.clickable { onCharacter(character.id) },
) {
AsyncImage(
modifier = Modifier.fillMaxSize(),
model = character.portrait,
contentScale = ContentScale.Crop,
alignment = Alignment.TopCenter,
filterQuality = FilterQuality.High,
contentDescription = null,
AnimatedContent(
targetState = character.portrait,
transitionSpec = { fadeIn() togetherWith fadeOut() },
) { portrait ->
AsyncImage(
modifier = Modifier.fillMaxSize(),
model = portrait,
contentScale = ContentScale.Crop,
alignment = Alignment.TopCenter,
filterQuality = FilterQuality.High,
contentDescription = null,
)
}
BloodOverlay(
bloodColor = bloodColor,
maxHp = character.maxHp.toFloat(),
hp = character.hp.toFloat(),
)
Column(
modifier = Modifier
.fillMaxSize()
@ -128,4 +158,23 @@ fun PlayerPortrait(
}
}
}
}
@Composable
private fun BloodOverlay(
modifier: Modifier = Modifier,
maxHp: Float,
hp: Float,
bloodColor: Color = PlayerPortrait.Default.bloodColor,
) {
val animatedRatio = animateFloatAsState(
targetValue = min(maxHp, max(0f, (maxHp - hp) / maxHp)),
animationSpec = tween(durationMillis = 350, easing = EaseOutCirc)
)
Box(
modifier = modifier
.fillMaxWidth()
.fillMaxHeight(fraction = animatedRatio.value)
.background(color = bloodColor)
)
}

View file

@ -6,8 +6,8 @@ import com.lordcodes.turtle.shellRun
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.shared.lwa.OperatingSystem
import com.pixelized.shared.lwa.storePath
import com.pixelized.shared.lwa.utils.OperatingSystem
import com.pixelized.shared.lwa.utils.PathProvider
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class MainPageViewModel(
private val pathProvider: PathProvider,
private val characterSheetRepository: CharacterSheetRepository,
private val campaignRepository: CampaignRepository,
networkRepository: NetworkRepository,
@ -86,9 +87,10 @@ class MainPageViewModel(
fun openSaveDirectory(
os: OperatingSystem = OperatingSystem.current,
) {
val path = pathProvider.storePath(os = os)
when (os) {
OperatingSystem.Windows -> shellRun("explorer.exe", listOf(storePath(os = os)))
OperatingSystem.Macintosh -> shellRun("open", listOf(storePath(os = os)))
OperatingSystem.Windows -> shellRun("explorer.exe", listOf(path))
OperatingSystem.Macintosh -> shellRun("open", listOf(path))
}
}
}

View file

@ -3,7 +3,6 @@ package com.pixelized.desktop.lwa
import androidx.compose.ui.window.application
import com.pixelized.shared.lwa.sharedModuleDependencies
import org.koin.compose.KoinContext
import org.koin.core.context.loadKoinModules
import org.koin.core.context.startKoin
import javax.swing.UIManager