Add basic resources links.

This commit is contained in:
Thomas Andres Gomez 2025-05-07 13:21:04 +02:00
parent 3a56bad9a4
commit b230d38805
15 changed files with 352 additions and 355 deletions

View file

@ -0,0 +1,96 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="24dp"
android:height="24dp"
android:viewportWidth="508"
android:viewportHeight="508">
<path
android:fillColor="#7d2ae7"
android:fillType="evenOdd"
android:pathData="M253.82,253.82m-253.82,0a253.82,253.82 0,1 1,507.64 0a253.82,253.82 0,1 1,-507.64 0"
android:strokeLineJoin="round" />
<path
android:fillType="evenOdd"
android:pathData="M253.82,253.82m-253.82,0a253.82,253.82 0,1 1,507.64 0a253.82,253.82 0,1 1,-507.64 0"
android:strokeLineJoin="round">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="97.91"
android:centerY="449.93"
android:gradientRadius="392.62"
android:type="radial">
<item
android:color="#FF6420FF"
android:offset="0" />
<item
android:color="#006420FF"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:fillType="evenOdd"
android:pathData="M253.82,253.82m-253.82,0a253.82,253.82 0,1 1,507.64 0a253.82,253.82 0,1 1,-507.64 0"
android:strokeLineJoin="round">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="134.39"
android:centerY="57.71"
android:gradientRadius="442.75"
android:type="radial">
<item
android:color="#FF00C4CC"
android:offset="0" />
<item
android:color="#0000C4CC"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:fillType="evenOdd"
android:pathData="M253.82,253.82m-253.82,0a253.82,253.82 0,1 1,507.64 0a253.82,253.82 0,1 1,-507.64 0"
android:strokeLineJoin="round">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="98.06"
android:centerY="449.93"
android:gradientRadius="387.86"
android:type="radial">
<item
android:color="#FF6420FF"
android:offset="0" />
<item
android:color="#006420FF"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:fillType="evenOdd"
android:pathData="M253.82,253.82m-253.82,0a253.82,253.82 0,1 1,507.64 0a253.82,253.82 0,1 1,-507.64 0"
android:strokeLineJoin="round">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="207.6"
android:centerY="68.4"
android:gradientRadius="399.66"
android:type="radial">
<item
android:color="#BA00C4CC"
android:offset="0" />
<item
android:color="#FF00C4CC"
android:offset="0" />
<item
android:color="#0000C4CC"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#fff"
android:fillType="nonZero"
android:pathData="M446.74,276.85c-0.67,0 -1.27,0.43 -1.58,1.33 -4.01,11.45 -9.43,18.25 -13.89,18.25 -2.56,0 -3.6,-2.86 -3.6,-7.34 0,-11.21 6.71,-34.98 10.1,-45.82 0.39,-1.31 0.65,-2.48 0.65,-3.48 0,-3.15 -1.72,-4.7 -5.99,-4.7 -4.6,0 -9.55,1.8 -14.36,10.23 -1.66,-7.43 -6.69,-10.68 -13.72,-10.68 -8.12,0 -15.97,5.22 -22.42,13.7 -6.46,8.47 -14.05,11.25 -19.76,9.88 4.11,-10.06 5.63,-17.57 5.63,-23.15 0,-8.75 -4.32,-14.03 -11.31,-14.03 -10.62,0 -16.75,10.13 -16.75,20.8 0,8.24 3.74,16.71 11.95,20.82 -6.89,15.57 -16.94,29.66 -20.76,29.66 -4.93,0 -6.38,-24.12 -6.11,-41.38 0.18,-9.9 1,-10.41 1,-13.4 0,-1.72 -1.12,-2.9 -5.59,-2.9 -10.45,0 -13.68,8.84 -14.16,19a50.05,50.05 0,0 1,-1.8 11.41c-4.36,15.57 -13.36,27.39 -19.23,27.39 -2.72,0 -3.46,-2.72 -3.46,-6.28 0,-11.21 6.28,-25.22 6.28,-37.17 0,-8.78 -3.85,-14.34 -11.11,-14.34 -8.55,0 -19.86,10.17 -30.56,29.23 3.52,-14.6 4.97,-28.72 -5.46,-28.72a14.11,14.11 0,0 0,-6.48 1.68,3.69 3.69,0 0,0 -2.11,3.56c1,15.53 -12.52,55.33 -25.34,55.33 -2.33,0 -3.46,-2.52 -3.46,-6.59 0,-11.23 6.69,-34.94 10.06,-45.8 0.43,-1.41 0.67,-2.62 0.67,-3.68 0,-2.97 -1.84,-4.5 -6.01,-4.5 -4.58,0 -9.55,1.74 -14.34,10.17 -1.68,-7.43 -6.71,-10.68 -13.73,-10.68 -11.52,0 -24.4,12.19 -30.05,28.08 -7.57,21.21 -22.83,41.69 -43.38,41.69 -18.65,0 -28.49,-15.52 -28.49,-40.03 0,-35.39 25.98,-64.31 45.25,-64.31 9.22,0 13.62,5.87 13.62,14.87 0,10.9 -6.09,15.96 -6.09,20.11 0,1.27 1.06,2.52 3.15,2.52 8.37,0 18.23,-9.84 18.23,-23.26 0,-13.42 -10.9,-23.24 -30.17,-23.24 -31.85,0 -63.9,32.05 -63.9,73.11 0,32.67 16.12,52.37 44,52.37 19.02,0 35.63,-14.79 44.59,-32.05 1.02,14.3 7.51,21.78 17.41,21.78 8.8,0 15.93,-5.24 21.36,-14.46 2.09,9.65 7.65,14.36 14.87,14.36 8.27,0 15.2,-5.24 21.79,-14.99 -0.1,7.65 1.64,14.85 8.28,14.85 3.13,0 6.87,-0.73 7.53,-3.46 6.98,-28.88 24.24,-52.45 29.52,-52.45 1.57,0 2,1.51 2,3.29 0,7.85 -5.54,23.93 -5.54,34.2 0,11.09 4.72,18.43 14.46,18.43 10.8,0 21.77,-13.23 29.09,-32.56 2.29,18.06 7.24,32.63 14.99,32.63 9.51,0 26.39,-20.01 36.63,-41.2 4.01,0.51 10.04,0.37 15.83,-3.72 -2.46,6.24 -3.91,13.07 -3.91,19.9 0,19.66 9.39,25.18 17.47,25.18 8.78,0 15.91,-5.24 21.36,-14.46 1.8,8.31 6.4,14.34 14.85,14.34 13.23,0 24.71,-13.52 24.71,-24.61 0,-2.93 -1.25,-4.72 -2.72,-4.72zM172.23,295.39c-5.34,0 -7.43,-5.38 -7.43,-13.4 0,-13.93 9.53,-37.19 19.6,-37.19 4.4,0 6.07,5.18 6.07,11.52 0,14.15 -9.06,39.07 -18.24,39.07zM355.18,253.82c-3.19,-3.8 -4.34,-8.96 -4.34,-13.56 0,-5.67 2.07,-10.47 4.56,-10.47 2.48,0 3.25,2.45 3.25,5.85 0,5.69 -2.04,14.01 -3.46,18.18zM396.6,295.39c-5.34,0 -7.43,-6.18 -7.43,-13.4 0,-13.44 9.53,-37.19 19.68,-37.19 4.4,0 5.97,5.15 5.97,11.52 0,14.15 -8.9,39.07 -18.22,39.07z"
android:strokeLineJoin="round" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="16dp"
android:viewportWidth="638.39"
android:viewportHeight="448.44">
<path
android:fillColor="#FF000000"
android:pathData="M234.54,331.41l2.81,0.83c3.53,-1.58 10.63,0.86 14.4,2.06 -6.93,-7.69 -17.38,-18.98 -24.91,-26.09 -2.47,-8.61 -1.42,-17.28 -0.88,-26.08l0.11,-0.73c-2.97,7.04 -6.73,13.89 -8.76,21.3 -2.37,10 10.52,20.78 15.52,26.97zM449.44,373.7c-19.35,-0.55 -27.86,-0.5 -37.72,-16.7l-7.68,0.22c-8.94,-0.4 -5.21,-0.22 -11.18,-0.51 -9.97,-0.39 -8.37,-9.86 -10.13,-14.87 -2.81,-16.99 3.71,-34.07 3.51,-51.07 -0.07,-6.03 -8.61,-27.39 -11.66,-35.03 -9.56,1.8 -19.18,2.14 -28.88,2.63 -22.36,-0.05 -44.57,-2.79 -66.61,-6.27 -4.3,17.75 -17.07,42.59 -6.51,60.63 12.81,18.66 21.8,23.83 35.74,24.95 13.94,1.12 17.08,16.86 13.71,22.48 -2.98,3.88 -8.23,4.59 -12.69,5.53l-8.91,0.42c-7.01,-0.24 -13.28,-2.13 -19.53,-5.05 -10.44,-5.83 -21.22,-17.94 -29.23,-26.64 1.87,3.47 2.98,10.25 1.29,13.41 -4.74,6.71 -25.22,6.67 -34.6,2.5 -10.65,-4.74 -36.4,-37.98 -40.38,-62.88 10.59,-20.03 26.02,-37.47 33.83,-59.28 -17.01,-10.86 -26.13,-28.53 -24.94,-48.55l0.43,-2.32c-16.74,3.13 -8.06,1.97 -26.07,3.33 -57.36,-0.17 -107.8,-39.06 -79.39,-99.5 1.85,-3.58 3.6,-6.83 6.74,-5.28 2.51,1.25 2.15,6.25 0.89,11.8C73.2,159.84 152.55,160.4 201.33,147.03c4.84,-1.33 14.47,-10.26 21.14,-13.22 10.9,-4.84 22.74,-6.81 34.48,-8.22 29.21,-3.33 64.31,12.06 82.15,12.56 17.84,0.5 43.21,-4.27 58.78,-3.27 11.3,0.52 22.4,2.56 33.3,5.46C438.24,105.95 438.74,80.61 455.47,74.74c9.82,1.55 17.39,14.93 22.99,22.08l0.02,-0c11.41,-0.45 22.26,2.44 33.06,5.66 19.54,-2.77 35.94,-13.75 53.19,-22.28 -0.05,0.27 -0.34,0.36 -0.5,0.54 -16.98,13.73 -19.35,36.96 -17.36,58.43 0.74,11.14 -2.41,23.24 -6.3,34.65 -7.28,18.59 -21.35,38.19 -37.68,37.18 -6.17,-0.19 -9.76,-3.69 -14.35,-7.42 -0.89,7.56 -4.39,14.3 -7.76,20.99 -7.79,14.82 -28.14,21.35 -46.98,37.18 -18.84,15.83 6.03,72.35 12.06,82.65 6.03,10.3 22.86,14.07 16.33,23.36 -2,3.07 -5.05,4.17 -8.32,5.36z" />
</vector>

View file

@ -57,6 +57,11 @@
<string name="roll_page__criticality_special__label">Spécial</string>
<string name="roll_page__criticality_critical__label">Critique</string>
<string name="resources__content_descriptions">Ressources</string>
<string name="resources__virtual_table__title">Table de jeu</string>
<string name="resources__rules__title">Règles de jeu</string>
<string name="resources__map_title">Carte du monde</string>
<string name="character_sheet_edit__create__title">Création de personnage</string>
<string name="character_sheet_edit__edit__title">Édition de personnage</string>
<string name="character_sheet_edit__id_label">Identifiant du personnage</string>

View file

@ -1,8 +1,5 @@
package com.pixelized.desktop.lwa
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
@ -13,13 +10,11 @@ import androidx.compose.material.SnackbarDefaults
import androidx.compose.material.SnackbarDuration
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
@ -48,13 +43,10 @@ import com.pixelized.desktop.lwa.ui.navigation.window.WindowsNavHost
import com.pixelized.desktop.lwa.ui.navigation.window.destination.CharacterSheetEditWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.CharacterSheetWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.GameMasterWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.RollHistoryWindow
import com.pixelized.desktop.lwa.ui.navigation.window.rememberMaxWindowHeight
import com.pixelized.desktop.lwa.ui.overlay.roll.RollHostState
import com.pixelized.desktop.lwa.ui.screen.characterSheet.CharacterSheetMainNavHost
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterNavHost
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterScreen
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage
import com.pixelized.desktop.lwa.ui.theme.LwaTheme
import com.pixelized.desktop.lwa.utils.InstallCoil
import kotlinx.coroutines.launch
@ -182,8 +174,6 @@ private fun WindowsHandler(
),
)
is RollHistoryWindow -> RollHistoryPage()
is GameMasterWindow -> LwaScaffold {
GameMasterNavHost()
}

View file

@ -33,8 +33,8 @@ import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogFactor
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogViewModel
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.network.NetworkFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkViewModel
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.CharacterRibbonFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel
@ -45,6 +45,7 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player.PlayerR
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.characterSheet.detail.CharacterSheetFactory
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetViewModel
import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.CharacterSheetEditFactory
@ -69,7 +70,6 @@ import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.list.GMItemFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.item.list.GMItemViewModel
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.rollhistory.RollHistoryViewModel
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsViewModel
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
@ -176,10 +176,10 @@ val viewModelDependencies
get() = module {
viewModelOf(::DataSyncViewModel)
viewModelOf(::CampaignToolbarViewModel)
viewModelOf(::ResourcesViewModel)
viewModelOf(::CharacterSheetViewModel)
viewModelOf(::CharacterSheetEditViewModel)
viewModelOf(::RollViewModel)
viewModelOf(::RollHistoryViewModel)
viewModelOf(::NetworkViewModel)
viewModelOf(::PlayerRibbonViewModel)
viewModelOf(::NpcRibbonViewModel)

View file

@ -1,29 +0,0 @@
package com.pixelized.desktop.lwa.ui.navigation.window.destination
import androidx.compose.runtime.Stable
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.navigation.window.WindowController
@Stable
class RollHistoryWindow(
title: String,
size: DpSize,
) : Window(
title = title,
size = size,
)
fun WindowController.navigateToRollHistory(
title: String = "",
) {
showWindow(
window = RollHistoryWindow(
title = title,
size = DpSize(
width = 400.dp + 64.dp,
height = maxWindowHeight - 32.dp,
)
)
)
}

View file

@ -3,18 +3,15 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
@ -29,15 +26,15 @@ import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToSettings
import com.pixelized.desktop.lwa.ui.navigation.window.destination.navigateToGameMasterWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.navigateToRollHistory
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkDialog
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesMenu
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkMenu
import com.pixelized.desktop.lwa.ui.theme.lwa
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
import lwacharactersheet.composeapp.generated.resources.ic_settings_24dp
import lwacharactersheet.composeapp.generated.resources.ic_timeline_24dp
import lwacharactersheet.composeapp.generated.resources.ic_wifi_24dp
import lwacharactersheet.composeapp.generated.resources.ic_wifi_off_24dp
import lwacharactersheet.composeapp.generated.resources.main_page__roll_history_action
import lwacharactersheet.composeapp.generated.resources.resources__content_descriptions
import lwacharactersheet.composeapp.generated.resources.settings__title
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
@ -50,7 +47,7 @@ fun CampaignToolbar(
val windows = LocalWindowController.current
val screen = LocalScreenController.current
val isOverflowMenuOpen = remember { mutableStateOf(false) }
val isResourcesMenuOpen = remember { mutableStateOf(false) }
val isNetworkMenuOpen = remember { mutableStateOf(false) }
val title = viewModel.title.collectAsState()
@ -62,29 +59,24 @@ fun CampaignToolbar(
status = status,
isAdmin = isAdmin,
isNetworkMenuOpen = isNetworkMenuOpen,
isOverflowMenuOpen = isOverflowMenuOpen,
isResourcesMenuOpen = isResourcesMenuOpen,
onAdmin = {
windows.navigateToGameMasterWindow()
},
onNetwork = {
isNetworkMenuOpen.value = true
},
onOverflow = {
isOverflowMenuOpen.value = true
},
onRollHistory = {
isOverflowMenuOpen.value = false
windows.navigateToRollHistory()
onResources = {
isResourcesMenuOpen.value = true
},
onSettings = {
isOverflowMenuOpen.value = false
screen.navigateToSettings()
},
onDismissNetworkMenu = {
isNetworkMenuOpen.value = false
},
onDismissOverflowMenu = {
isOverflowMenuOpen.value = false
onDismissResourcesMenu = {
isResourcesMenuOpen.value = false
},
)
}
@ -96,14 +88,13 @@ private fun CampaignToolbarContent(
status: State<NetworkRepository.Status>,
isAdmin: State<Boolean>,
isNetworkMenuOpen: State<Boolean>,
isOverflowMenuOpen: State<Boolean>,
isResourcesMenuOpen: State<Boolean>,
onAdmin: () -> Unit,
onNetwork: () -> Unit,
onOverflow: () -> Unit,
onRollHistory: () -> Unit,
onResources: () -> Unit,
onSettings: () -> Unit,
onDismissNetworkMenu: () -> Unit,
onDismissOverflowMenu: () -> Unit,
onDismissResourcesMenu: () -> Unit,
) {
TopAppBar(
modifier = modifier,
@ -127,6 +118,15 @@ private fun CampaignToolbarContent(
)
}
}
IconButton(
onClick = onResources,
) {
Icon(
painter = painterResource(Res.drawable.ic_link_24dp),
tint = MaterialTheme.colors.primary,
contentDescription = stringResource(Res.string.resources__content_descriptions),
)
}
IconButton(
onClick = onNetwork,
) {
@ -145,12 +145,12 @@ private fun CampaignToolbarContent(
)
}
IconButton(
onClick = onOverflow,
onClick = onSettings,
) {
Icon(
imageVector = Icons.Default.MoreVert,
painter = painterResource(Res.drawable.ic_settings_24dp),
tint = MaterialTheme.colors.primary,
contentDescription = null,
contentDescription = stringResource(Res.string.settings__title),
)
}
DropdownMenu(
@ -158,44 +158,19 @@ private fun CampaignToolbarContent(
expanded = isNetworkMenuOpen.value,
onDismissRequest = onDismissNetworkMenu,
content = {
NetworkDialog(
NetworkMenu(
modifier = Modifier.size(384.dp + 96.dp, 240.dp),
)
},
)
DropdownMenu(
offset = remember { DpOffset(x = (-8).dp, y = 8.dp) },
expanded = isOverflowMenuOpen.value,
onDismissRequest = onDismissOverflowMenu,
offset = remember { DpOffset(x = -(48.dp + 8.dp), y = 8.dp) },
expanded = isResourcesMenuOpen.value,
onDismissRequest = onDismissResourcesMenu,
content = {
DropdownMenuItem(
onClick = onRollHistory,
) {
Icon(
painter = painterResource(Res.drawable.ic_timeline_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null,
)
Text(
modifier = Modifier.padding(start = 8.dp),
color = MaterialTheme.colors.primary,
text = stringResource(Res.string.main_page__roll_history_action),
)
}
DropdownMenuItem(
onClick = onSettings,
) {
Icon(
painter = painterResource(Res.drawable.ic_settings_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null,
)
Text(
modifier = Modifier.padding(start = 8.dp),
color = MaterialTheme.colors.primary,
text = stringResource(Res.string.settings__title),
)
}
ResourcesMenu(
modifier = Modifier.width(384.dp + 96.dp),
)
},
)
},

View file

@ -0,0 +1,138 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.lwa
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
@Stable
data class ResourcesDialogUio(
val resources: List<LinkResource>,
) {
@Stable
data class LinkResource(
val icon: DrawableResource,
val tint: Boolean = false,
val name: StringResource,
val action: () -> Unit,
)
}
@Immutable
object ResourcesDialogDefault {
@Stable
val padding: PaddingValues = PaddingValues(vertical = 4.dp, horizontal = 8.dp)
@Stable
val spacing: Dp = 4.dp
}
@Immutable
object ResourcesItemDefault {
@Stable
val padding: PaddingValues = PaddingValues(vertical = 2.dp, horizontal = 8.dp)
@Stable
val shape: Shape = RoundedCornerShape(8.dp)
@Stable
val spacing: Dp = 8.dp
}
@Composable
fun ResourcesMenu(
modifier: Modifier = Modifier,
viewModel: ResourcesViewModel = koinViewModel(),
) {
ResourcesContent(
modifier = modifier,
dialog = viewModel.dialog,
)
}
@Composable
private fun ResourcesContent(
modifier: Modifier = Modifier,
dialog: ResourcesDialogUio,
padding: PaddingValues = ResourcesDialogDefault.padding,
spacing: Dp = ResourcesDialogDefault.spacing,
) {
Column(
modifier = Modifier.padding(paddingValues = padding).then(other = modifier),
verticalArrangement = Arrangement.spacedBy(space = spacing),
) {
dialog.resources.forEach { resource ->
ResourcesItem(
resource = resource,
onClick = resource.action,
)
}
}
}
@Composable
private fun ResourcesItem(
modifier: Modifier = Modifier,
padding: PaddingValues = ResourcesItemDefault.padding,
spacing: Dp = ResourcesItemDefault.spacing,
shape: Shape = ResourcesItemDefault.shape,
resource: ResourcesDialogUio.LinkResource,
onClick: () -> Unit,
) {
Row(
modifier = Modifier
.clip(shape = shape)
.clickable(onClick = onClick)
.minimumInteractiveComponentSize()
.fillMaxWidth()
.padding(paddingValues = padding)
.then(other = modifier),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(space = spacing),
) {
Image(
modifier = Modifier.size(size = 24.dp),
colorFilter = when (resource.tint) {
true -> ColorFilter.tint(color = MaterialTheme.lwa.colorScheme.base.primary)
else -> null
},
painter = painterResource(resource = resource.icon),
contentDescription = null,
)
Text(
style = MaterialTheme.lwa.typography.base.body1,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.lwa.colorScheme.base.primary,
text = stringResource(resource = resource.name),
)
}
}

View file

@ -0,0 +1,63 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links
import androidx.lifecycle.ViewModel
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_canva_24dp
import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
import lwacharactersheet.composeapp.generated.resources.ic_tiddlywiki_24dp
import lwacharactersheet.composeapp.generated.resources.resources__map_title
import lwacharactersheet.composeapp.generated.resources.resources__rules__title
import lwacharactersheet.composeapp.generated.resources.resources__virtual_table__title
import java.awt.Desktop
import java.net.URI
class ResourcesViewModel : ViewModel() {
val dialog = ResourcesDialogUio(
resources = createResources()
)
private fun createResources(): List<ResourcesDialogUio.LinkResource> {
return try {
if (Desktop.isDesktopSupported()) {
val desktop = Desktop.getDesktop()
if (desktop.isSupported(Desktop.Action.BROWSE)) {
listOf(
ResourcesDialogUio.LinkResource(
icon = Res.drawable.ic_canva_24dp,
name = Res.string.resources__virtual_table__title,
action = { desktop.browse(URI.create(CANVA)) },
),
ResourcesDialogUio.LinkResource(
icon = Res.drawable.ic_tiddlywiki_24dp,
name = Res.string.resources__rules__title,
action = { desktop.browse(URI.create(TIDDLY)) },
),
ResourcesDialogUio.LinkResource(
icon = Res.drawable.ic_link_24dp,
tint = true,
name = Res.string.resources__map_title,
action = { desktop.browse(URI.create(MAP)) },
),
)
} else {
error("Desktop.Action.BROWSE is not supported")
}
} else {
error("Desktop.isDesktopSupported return false")
}
} catch (exception: Exception) {
emptyList()
}
}
companion object {
private const val CANVA =
"https://www.canva.com/design/DAGSzwpIAAY/1YOfnIiazVWzGbKtzKdu5g/edit"
private const val TIDDLY =
"https://lwa-manuel-pj.tiddlyhost.com/"
private const val MAP =
"https://drive.google.com/file/d/1vuoyk1sfrerkMKtttf7kGPpnHpkjWvl5/view?usp=drive_link"
}
}

View file

@ -1,4 +1,4 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.network
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network
import com.pixelized.desktop.lwa.repository.network.NetworkRepository.Status

View file

@ -1,4 +1,4 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.network
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
@ -93,7 +93,7 @@ data class NetworkPageUio(
}
@Composable
fun NetworkDialog(
fun NetworkMenu(
modifier: Modifier = Modifier,
viewModel: NetworkViewModel = koinViewModel(),
) {

View file

@ -1,4 +1,4 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.network
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network
import androidx.compose.material.SnackbarDuration
import androidx.compose.runtime.State

View file

@ -1,127 +0,0 @@
package com.pixelized.desktop.lwa.ui.screen.rollhistory
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.roll_history__item__difficulty
import lwacharactersheet.composeapp.generated.resources.roll_history__item__throw
import org.jetbrains.compose.resources.stringResource
@Stable
data class RollHistoryItemUio(
val character: String,
val skillLabel: String,
val rollDifficulty: String?,
val rollValue: Int,
val rollSuccessLimit: Int?,
val resultLabel: String?,
)
@Composable
fun RollHistoryItem(
modifier: Modifier = Modifier,
roll: RollHistoryItemUio,
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier.weight(1f)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.body1,
fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = roll.character,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = stringResource(Res.string.roll_history__item__throw),
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = roll.skillLabel,
)
}
Row(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
roll.rollDifficulty?.let {
Text(
style = MaterialTheme.typography.caption,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = stringResource(Res.string.roll_history__item__difficulty),
)
Text(
style = MaterialTheme.typography.caption,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = it,
)
Text(
style = MaterialTheme.typography.caption,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = "-",
)
}
roll.resultLabel?.let {
Text(
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = it,
)
}
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h5,
fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = "${roll.rollValue}",
)
roll.rollSuccessLimit?.let {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Light,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = "/ $it",
)
}
}
}
}

View file

@ -1,79 +0,0 @@
package com.pixelized.desktop.lwa.ui.screen.rollhistory
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.roll_history__title
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun RollHistoryPage(
viewModel: RollHistoryViewModel = koinViewModel(),
) {
val rolls = viewModel.rolls.collectAsState()
Surface(
modifier = Modifier.fillMaxSize(),
) {
RollHistoryContent(
modifier = Modifier.fillMaxSize(),
rolls = rolls,
)
}
}
@Composable
private fun RollHistoryContent(
modifier: Modifier = Modifier,
rolls: State<List<RollHistoryItemUio>>,
) {
Scaffold(
modifier = modifier,
topBar = {
TopAppBar(
title = {
Text(
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = stringResource(Res.string.roll_history__title),
)
},
)
},
content = {
val state = rememberLazyListState()
LazyColumn(
modifier = Modifier.fillMaxSize(),
state = state,
reverseLayout = true,
contentPadding = PaddingValues(all = 24.dp),
verticalArrangement = Arrangement.spacedBy(space = 16.dp)
) {
items(items = rolls.value) {
RollHistoryItem(
modifier = Modifier.fillMaxWidth(),
roll = it
)
}
}
}
)
}

View file

@ -1,44 +0,0 @@
package com.pixelized.desktop.lwa.ui.screen.rollhistory
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
class RollHistoryViewModel(
characterRepository: CharacterSheetRepository,
rollRepository: RollHistoryRepository,
) : ViewModel() {
private var _rolls: List<RollHistoryItemUio> = emptyList()
val rolls = combine(
characterRepository.characterSheetPreviewFlow(),
rollRepository.rolls(),
) { sheets, message ->
val name = sheets.firstOrNull { it.characterSheetId == message.characterSheetId }?.name ?: ""
val roll = RollHistoryItemUio(
character = name,
skillLabel = message.skillLabel,
rollDifficulty = message.rollDifficulty,
resultLabel = message.resultLabel,
rollValue = message.rollValue,
rollSuccessLimit = message.rollSuccessLimit,
)
_rolls = _rolls.toMutableList().also {
if (it.size == MAX_ROLL_HISTORY_SIZE) it.removeAt(index = it.lastIndex)
it.add(index = 0, element = roll)
}
_rolls
}.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = _rolls,
)
companion object {
const val MAX_ROLL_HISTORY_SIZE = 100
}
}