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_special__label">Spécial</string>
<string name="roll_page__criticality_critical__label">Critique</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__create__title">Création de personnage</string>
<string name="character_sheet_edit__edit__title">Édition 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> <string name="character_sheet_edit__id_label">Identifiant du personnage</string>

View file

@ -1,8 +1,5 @@
package com.pixelized.desktop.lwa 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.foundation.layout.fillMaxSize
import androidx.compose.material.ButtonDefaults import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
@ -13,13 +10,11 @@ import androidx.compose.material.SnackbarDefaults
import androidx.compose.material.SnackbarDuration import androidx.compose.material.SnackbarDuration
import androidx.compose.material.SnackbarHost import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState import androidx.compose.material.SnackbarHostState
import androidx.compose.material.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TextButton import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember 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.CharacterSheetEditWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.CharacterSheetWindow 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.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.navigation.window.rememberMaxWindowHeight
import com.pixelized.desktop.lwa.ui.overlay.roll.RollHostState 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.characterSheet.CharacterSheetMainNavHost
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterNavHost 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.ui.theme.LwaTheme
import com.pixelized.desktop.lwa.utils.InstallCoil import com.pixelized.desktop.lwa.utils.InstallCoil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -182,8 +174,6 @@ private fun WindowsHandler(
), ),
) )
is RollHistoryWindow -> RollHistoryPage()
is GameMasterWindow -> LwaScaffold { is GameMasterWindow -> LwaScaffold {
GameMasterNavHost() 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.composable.character.purse.PurseDialogViewModel
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.network.NetworkFactory import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkViewModel 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.CharacterRibbonFactory
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetFactory 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
@ -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.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.characterSheet.detail.CharacterSheetFactory 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.detail.CharacterSheetViewModel
import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.CharacterSheetEditFactory 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.gamemaster.item.list.GMItemViewModel
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.rollhistory.RollHistoryViewModel
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.SettingsUseCase
import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory
@ -176,10 +176,10 @@ val viewModelDependencies
get() = module { get() = module {
viewModelOf(::DataSyncViewModel) viewModelOf(::DataSyncViewModel)
viewModelOf(::CampaignToolbarViewModel) viewModelOf(::CampaignToolbarViewModel)
viewModelOf(::ResourcesViewModel)
viewModelOf(::CharacterSheetViewModel) viewModelOf(::CharacterSheetViewModel)
viewModelOf(::CharacterSheetEditViewModel) viewModelOf(::CharacterSheetEditViewModel)
viewModelOf(::RollViewModel) viewModelOf(::RollViewModel)
viewModelOf(::RollHistoryViewModel)
viewModelOf(::NetworkViewModel) viewModelOf(::NetworkViewModel)
viewModelOf(::PlayerRibbonViewModel) viewModelOf(::PlayerRibbonViewModel)
viewModelOf(::NpcRibbonViewModel) 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.AnimatedVisibility
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
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.material.DropdownMenu import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
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
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TextButton import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar 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.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState 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.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToSettings 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.navigateToGameMasterWindow
import com.pixelized.desktop.lwa.ui.navigation.window.destination.navigateToRollHistory import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesMenu
import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkDialog import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.network.NetworkMenu
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
import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
import lwacharactersheet.composeapp.generated.resources.ic_settings_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_24dp
import lwacharactersheet.composeapp.generated.resources.ic_wifi_off_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 lwacharactersheet.composeapp.generated.resources.settings__title
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.resources.stringResource
@ -50,7 +47,7 @@ fun CampaignToolbar(
val windows = LocalWindowController.current val windows = LocalWindowController.current
val screen = LocalScreenController.current val screen = LocalScreenController.current
val isOverflowMenuOpen = remember { mutableStateOf(false) } val isResourcesMenuOpen = remember { mutableStateOf(false) }
val isNetworkMenuOpen = remember { mutableStateOf(false) } val isNetworkMenuOpen = remember { mutableStateOf(false) }
val title = viewModel.title.collectAsState() val title = viewModel.title.collectAsState()
@ -62,29 +59,24 @@ fun CampaignToolbar(
status = status, status = status,
isAdmin = isAdmin, isAdmin = isAdmin,
isNetworkMenuOpen = isNetworkMenuOpen, isNetworkMenuOpen = isNetworkMenuOpen,
isOverflowMenuOpen = isOverflowMenuOpen, isResourcesMenuOpen = isResourcesMenuOpen,
onAdmin = { onAdmin = {
windows.navigateToGameMasterWindow() windows.navigateToGameMasterWindow()
}, },
onNetwork = { onNetwork = {
isNetworkMenuOpen.value = true isNetworkMenuOpen.value = true
}, },
onOverflow = { onResources = {
isOverflowMenuOpen.value = true isResourcesMenuOpen.value = true
},
onRollHistory = {
isOverflowMenuOpen.value = false
windows.navigateToRollHistory()
}, },
onSettings = { onSettings = {
isOverflowMenuOpen.value = false
screen.navigateToSettings() screen.navigateToSettings()
}, },
onDismissNetworkMenu = { onDismissNetworkMenu = {
isNetworkMenuOpen.value = false isNetworkMenuOpen.value = false
}, },
onDismissOverflowMenu = { onDismissResourcesMenu = {
isOverflowMenuOpen.value = false isResourcesMenuOpen.value = false
}, },
) )
} }
@ -96,14 +88,13 @@ private fun CampaignToolbarContent(
status: State<NetworkRepository.Status>, status: State<NetworkRepository.Status>,
isAdmin: State<Boolean>, isAdmin: State<Boolean>,
isNetworkMenuOpen: State<Boolean>, isNetworkMenuOpen: State<Boolean>,
isOverflowMenuOpen: State<Boolean>, isResourcesMenuOpen: State<Boolean>,
onAdmin: () -> Unit, onAdmin: () -> Unit,
onNetwork: () -> Unit, onNetwork: () -> Unit,
onOverflow: () -> Unit, onResources: () -> Unit,
onRollHistory: () -> Unit,
onSettings: () -> Unit, onSettings: () -> Unit,
onDismissNetworkMenu: () -> Unit, onDismissNetworkMenu: () -> Unit,
onDismissOverflowMenu: () -> Unit, onDismissResourcesMenu: () -> Unit,
) { ) {
TopAppBar( TopAppBar(
modifier = modifier, 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( IconButton(
onClick = onNetwork, onClick = onNetwork,
) { ) {
@ -145,12 +145,12 @@ private fun CampaignToolbarContent(
) )
} }
IconButton( IconButton(
onClick = onOverflow, onClick = onSettings,
) { ) {
Icon( Icon(
imageVector = Icons.Default.MoreVert, painter = painterResource(Res.drawable.ic_settings_24dp),
tint = MaterialTheme.colors.primary, tint = MaterialTheme.colors.primary,
contentDescription = null, contentDescription = stringResource(Res.string.settings__title),
) )
} }
DropdownMenu( DropdownMenu(
@ -158,44 +158,19 @@ private fun CampaignToolbarContent(
expanded = isNetworkMenuOpen.value, expanded = isNetworkMenuOpen.value,
onDismissRequest = onDismissNetworkMenu, onDismissRequest = onDismissNetworkMenu,
content = { content = {
NetworkDialog( NetworkMenu(
modifier = Modifier.size(384.dp + 96.dp, 240.dp), modifier = Modifier.size(384.dp + 96.dp, 240.dp),
) )
}, },
) )
DropdownMenu( DropdownMenu(
offset = remember { DpOffset(x = (-8).dp, y = 8.dp) }, offset = remember { DpOffset(x = -(48.dp + 8.dp), y = 8.dp) },
expanded = isOverflowMenuOpen.value, expanded = isResourcesMenuOpen.value,
onDismissRequest = onDismissOverflowMenu, onDismissRequest = onDismissResourcesMenu,
content = { content = {
DropdownMenuItem( ResourcesMenu(
onClick = onRollHistory, modifier = Modifier.width(384.dp + 96.dp),
) { )
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),
)
}
}, },
) )
}, },

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 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.AnimatedContent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
@ -93,7 +93,7 @@ data class NetworkPageUio(
} }
@Composable @Composable
fun NetworkDialog( fun NetworkMenu(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
viewModel: NetworkViewModel = koinViewModel(), 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.material.SnackbarDuration
import androidx.compose.runtime.State 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
}
}