diff --git a/android-app/app/build.gradle b/android-app/app/build.gradle index dd918b8..f15d616 100644 --- a/android-app/app/build.gradle +++ b/android-app/app/build.gradle @@ -91,4 +91,7 @@ dependencies { // Coroutine implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' + + //Accompanist + implementation 'com.google.accompanist:accompanist-systemuicontroller:0.22.0-rc' } \ No newline at end of file diff --git a/android-app/app/src/main/java/com/nimtome/app/CharacterDetailsActivity.kt b/android-app/app/src/main/java/com/nimtome/app/CharacterDetailsActivity.kt index 5389cad..5e4ca6b 100644 --- a/android-app/app/src/main/java/com/nimtome/app/CharacterDetailsActivity.kt +++ b/android-app/app/src/main/java/com/nimtome/app/CharacterDetailsActivity.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModelProvider import com.nimtome.app.CharacterDetailsActivity.Companion.KEY_NAME +import com.nimtome.app.DndApplication.Companion.colorPalette import com.nimtome.app.model.DndCharacter import com.nimtome.app.model.Spell import com.nimtome.app.ui.components.DndTopBar @@ -65,7 +66,8 @@ class CharacterDetailsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - DndSpellsTheme { + DndSpellsTheme(darkColors = colorPalette.darkColors, + lightColors = colorPalette.lightColors) { // A surface container using the 'background' color from the theme val viewModel = ViewModelProvider(this) val nameInDb = intent.getStringExtra(KEY_NAME) ?: "" @@ -86,7 +88,7 @@ class CharacterDetailsActivity : ComponentActivity() { @Composable fun CharacterDetailContent( character: DndCharacter = DndCharacter(), - spells: List = listOf() + spells: List = listOf(), ) { val activity = (LocalContext.current as? Activity) diff --git a/android-app/app/src/main/java/com/nimtome/app/CharacterListActivity.kt b/android-app/app/src/main/java/com/nimtome/app/CharacterListActivity.kt index e42ce8f..96398e5 100644 --- a/android-app/app/src/main/java/com/nimtome/app/CharacterListActivity.kt +++ b/android-app/app/src/main/java/com/nimtome/app/CharacterListActivity.kt @@ -7,7 +7,6 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -33,6 +32,7 @@ import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.outlined.Menu import androidx.compose.material.rememberBackdropScaffoldState import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState @@ -48,14 +48,18 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProvider +import com.nimtome.app.DndApplication.Companion.colorPalette import com.nimtome.app.model.DndCharacter import com.nimtome.app.model.Spell import com.nimtome.app.model.SpellImporter import com.nimtome.app.ui.components.CharacterCard +import com.nimtome.app.ui.components.ColorPaletteSelector import com.nimtome.app.ui.components.EditCharacterCard +import com.nimtome.app.ui.components.MainMenuContentSelector +import com.nimtome.app.ui.components.MainMenuElement import com.nimtome.app.ui.components.MainMenuSpellCard import com.nimtome.app.ui.theme.CARD_INNER_FILL_RATIO -import com.nimtome.app.ui.theme.CharacterListTopbarColors +import com.nimtome.app.ui.theme.ColorPalette import com.nimtome.app.ui.theme.DndSpellsTheme import com.nimtome.app.viewmodel.CharacterViewModel import com.nimtome.app.viewmodel.SpellViewModel @@ -77,22 +81,22 @@ class CharacterListActivity : ComponentActivity() { GlobalScope.launch { withContext(Dispatchers.IO) { val resolver = this@CharacterListActivity.contentResolver - - resolver.openInputStream(uri)?.let { inputStream -> - val importer = SpellImporter() - val spellList = importer.importSpells(inputStream) - - // Show snakbar - spellsViewModel.nuke() - spellList.forEach { spell -> - spellsViewModel.insert(spell) + runCatching { + resolver.openInputStream(uri)?.let { inputStream -> + val importer = SpellImporter() + val spellList = importer.importSpells(inputStream) + + //TODO Show snakbar + spellsViewModel.nuke() + spellList.forEach { spell -> + spellsViewModel.insert(spell) + } } } } } } } - private val getFilePermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { @@ -111,8 +115,12 @@ class CharacterListActivity : ComponentActivity() { val characterList by characterViewModel.allCharacters.observeAsState() val spellList by spellsViewModel.allSpells.observeAsState() + var colorPalette by remember { mutableStateOf(colorPalette) } - DndSpellsTheme { + DndSpellsTheme( + darkColors = colorPalette.darkColors, + lightColors = colorPalette.lightColors + ) { Surface(color = MaterialTheme.colors.background) { MainActivityContent( characterList = characterList, @@ -142,6 +150,11 @@ class CharacterListActivity : ComponentActivity() { .putExtra(SpellDetailsActivity.KEY_SPELL_NAME, it.name) ) }, + colors = colorPalette, + onColorsChange = { + colorPalette = it + DndApplication.colorPalette = it + } ) if (showDialog.value) StorageAccessRationaleDialog( @@ -184,15 +197,11 @@ class CharacterListActivity : ComponentActivity() { } } -enum class MainMenuElements { - CHARACTERS, - SPELLS, -} @Composable private fun StorageAccessRationaleDialog( closeDialog: () -> Unit, - importSpells: () -> Unit + importSpells: () -> Unit, ) { AlertDialog( @@ -222,8 +231,6 @@ private fun StorageAccessRationaleDialog( ) } -private const val CARD_FILL_RATIO = .8f - @Suppress("UnusedPrivateMember") @ExperimentalMaterialApi @Composable @@ -236,11 +243,13 @@ private fun MainActivityContent( modifyCharacter: (DndCharacter) -> Unit = {}, openSpellDetails: (Spell) -> Unit = {}, modifySpell: (Spell) -> Unit = {}, + colors: ColorPalette, + onColorsChange: (ColorPalette) -> Unit, ) { val scope = rememberCoroutineScope() val scaffoldState = rememberBackdropScaffoldState(initialValue = BackdropValue.Concealed) - var menuSelection by remember { mutableStateOf(MainMenuElements.CHARACTERS) } + var menuSelection by remember { mutableStateOf(MainMenuElement.CHARACTERS) } var isEditMode by remember { mutableStateOf(false) } @@ -248,7 +257,7 @@ private fun MainActivityContent( appBar = { CenterAlignedTopAppBar( title = { Text(text = "D&D spells") }, - colors = CharacterListTopbarColors(), + colors = TopAppBarDefaults.centerAlignedTopAppBarColors(containerColor = MaterialTheme.colors.primary), navigationIcon = { IconButton(onClick = { scaffoldState.switch(scope) }) { Icon(Icons.Outlined.Menu, "Open Menu") @@ -270,32 +279,26 @@ private fun MainActivityContent( backLayerContent = { Column( Modifier - .fillMaxWidth(CARD_FILL_RATIO) - .selectableGroup() + .fillMaxWidth() + .selectableGroup(), + horizontalAlignment = Alignment.CenterHorizontally ) { - Row(verticalAlignment = Alignment.CenterVertically) { - androidx.compose.material3.RadioButton( - selected = menuSelection == MainMenuElements.SPELLS, - onClick = { menuSelection = MainMenuElements.SPELLS } - ) + MainMenuContentSelector( + modifier = Modifier.fillMaxWidth(CARD_INNER_FILL_RATIO), + selectedElement = menuSelection, + onSelectedElementChanged = { menuSelection = it }, + ) - Text("Spells") - } + Spacer(modifier = Modifier.padding(bottom = 5.dp)) - Row(verticalAlignment = Alignment.CenterVertically) { - androidx.compose.material3.RadioButton( - selected = menuSelection == MainMenuElements.CHARACTERS, - onClick = { menuSelection = MainMenuElements.CHARACTERS } - ) - Text("Characters") - } + ColorPaletteSelector(modifier = Modifier.fillMaxWidth(CARD_INNER_FILL_RATIO), selected = colors, onChanged = onColorsChange) Spacer(modifier = Modifier.padding(bottom = 15.dp)) } }, frontLayerContent = { - if (menuSelection == MainMenuElements.CHARACTERS) + if (menuSelection == MainMenuElement.CHARACTERS) CharacterList( list = characterList, isEditMode = isEditMode, @@ -335,7 +338,7 @@ private fun CharacterList( list: List?, isEditMode: Boolean, onClick: (DndCharacter) -> Unit = {}, - onEditClick: (DndCharacter) -> Unit + onEditClick: (DndCharacter) -> Unit, ) { if (list == null) { CircularProgressIndicator() @@ -423,22 +426,12 @@ private fun SpellList( @Composable fun CharacterListPreview() { DndSpellsTheme { - var showDialog by remember { - mutableStateOf(false) - } MainActivityContent( characterList = listOf(sampleCharacter), spellList = sampleSpells, - importSpells = {}, - addCharacter = {}, - modifyCharacter = {}, + importSpells = { }, + colors = ColorPalette.Purple, + onColorsChange = { } ) - if (showDialog) - StorageAccessRationaleDialog( - importSpells = {}, - closeDialog = { - showDialog = false - }, - ) } } diff --git a/android-app/app/src/main/java/com/nimtome/app/CreateCharacterActivity.kt b/android-app/app/src/main/java/com/nimtome/app/CreateCharacterActivity.kt index f766c54..13fc527 100644 --- a/android-app/app/src/main/java/com/nimtome/app/CreateCharacterActivity.kt +++ b/android-app/app/src/main/java/com/nimtome/app/CreateCharacterActivity.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModelProvider +import com.nimtome.app.DndApplication.Companion.colorPalette import com.nimtome.app.model.DndCharacter import com.nimtome.app.model.DndClass import com.nimtome.app.ui.components.ClassSelector @@ -180,7 +181,7 @@ fun EditCharacterFloatingActionButton( dndCharacter: DndCharacter, activity: CreateCharacterActivity?, scope: CoroutineScope, - scaffoldState: ScaffoldState + scaffoldState: ScaffoldState, ) { val characterErrorText = stringResource(R.string.character_error) @@ -205,7 +206,7 @@ fun CreateCharacterFloatingActionButton( dndCharacter: DndCharacter, activity: Activity?, scope: CoroutineScope, - scaffoldState: ScaffoldState + scaffoldState: ScaffoldState, ) { val characterErrorText = stringResource(R.string.character_error) @@ -243,7 +244,7 @@ fun validateCharacter(dndCharacter: DndCharacter): Boolean { fun CharacterDetailList( modifier: Modifier = Modifier, dndCharacter: DndCharacter, - onChangeDndCharacter: (DndCharacter) -> Unit + onChangeDndCharacter: (DndCharacter) -> Unit, ) { val classList = DndClass.values().toList().subList(0, DndClass.values().size - 1) @@ -283,7 +284,7 @@ fun CharacterDetailList( @Composable fun MyApp(component: @Composable () -> Unit) { - DndSpellsTheme { + DndSpellsTheme(darkColors = colorPalette.darkColors, lightColors = colorPalette.lightColors) { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { component() diff --git a/android-app/app/src/main/java/com/nimtome/app/DndApplication.kt b/android-app/app/src/main/java/com/nimtome/app/DndApplication.kt index d14f53e..28bd7fd 100644 --- a/android-app/app/src/main/java/com/nimtome/app/DndApplication.kt +++ b/android-app/app/src/main/java/com/nimtome/app/DndApplication.kt @@ -1,9 +1,11 @@ package com.nimtome.app import android.app.Application +import android.content.SharedPreferences import androidx.room.Room import com.nimtome.app.database.CharacterDatabase import com.nimtome.app.database.SpellDatabase +import com.nimtome.app.ui.theme.ColorPalette class DndApplication : Application() { @@ -12,6 +14,25 @@ class DndApplication : Application() { private set lateinit var spellDatabase: SpellDatabase private set + lateinit var sharedPreferences: SharedPreferences + private set + private const val SP_ID_MAIN = "com.nimtome.nimtome.main" + private const val SP_COLOR_THEME = "COLOR_THEME" + + var colorPalette: ColorPalette + get() { + return ColorPalette.valueOf( + sharedPreferences + .getString(SP_COLOR_THEME, ColorPalette.Purple.name) + ?: ColorPalette.Purple.name + ) + } + set(value) { + with(sharedPreferences.edit()) { + putString(SP_COLOR_THEME, value.name) + apply() + } + } } override fun onCreate() { @@ -26,6 +47,8 @@ class DndApplication : Application() { CharacterDatabase::class.java, "character_database", ).fallbackToDestructiveMigration().build() + + sharedPreferences = getSharedPreferences(SP_ID_MAIN, MODE_PRIVATE) super.onCreate() } } diff --git a/android-app/app/src/main/java/com/nimtome/app/SelectSpellsActivity.kt b/android-app/app/src/main/java/com/nimtome/app/SelectSpellsActivity.kt index f24e476..f0a3ce4 100644 --- a/android-app/app/src/main/java/com/nimtome/app/SelectSpellsActivity.kt +++ b/android-app/app/src/main/java/com/nimtome/app/SelectSpellsActivity.kt @@ -77,7 +77,7 @@ class SelectSpellsActivity : ComponentActivity() { fun SelectSpellsContent( spells: List, character: DndCharacter, - updateCharacter: (DndCharacter) -> Unit = {} + updateCharacter: (DndCharacter) -> Unit = {}, ) { val scope = rememberCoroutineScope() val scaffoldState = rememberBottomSheetScaffoldState() @@ -148,7 +148,7 @@ fun SelectSpellsContent( private fun SpellCardWithCheckBox( spell: Spell, checked: Boolean, - onCheck: (Boolean) -> Unit + onCheck: (Boolean) -> Unit, ) { Card( modifier = Modifier diff --git a/android-app/app/src/main/java/com/nimtome/app/SpellDetailsActivity.kt b/android-app/app/src/main/java/com/nimtome/app/SpellDetailsActivity.kt index a41d925..074e142 100644 --- a/android-app/app/src/main/java/com/nimtome/app/SpellDetailsActivity.kt +++ b/android-app/app/src/main/java/com/nimtome/app/SpellDetailsActivity.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModelProvider +import com.nimtome.app.DndApplication.Companion.colorPalette import com.nimtome.app.model.Spell import com.nimtome.app.ui.components.DndTopBar import com.nimtome.app.ui.theme.DndSpellsTheme @@ -46,7 +47,8 @@ class SpellDetailsActivity : ComponentActivity() { .observeAsState(Spell()) .value - DndSpellsTheme { + DndSpellsTheme(darkColors = colorPalette.darkColors, + lightColors = colorPalette.lightColors) { // A surface container using the 'background' color from the theme Surface(color = MaterialTheme.colors.background) { SpellDetails(spell = spell) diff --git a/android-app/app/src/main/java/com/nimtome/app/database/CharacterDao.kt b/android-app/app/src/main/java/com/nimtome/app/database/CharacterDao.kt index 174a2ef..6e89693 100644 --- a/android-app/app/src/main/java/com/nimtome/app/database/CharacterDao.kt +++ b/android-app/app/src/main/java/com/nimtome/app/database/CharacterDao.kt @@ -29,6 +29,6 @@ interface CharacterDao { @Delete fun deleteCharacter( - character: RoomCharacter + character: RoomCharacter, ) } diff --git a/android-app/app/src/main/java/com/nimtome/app/database/RoomSpell.kt b/android-app/app/src/main/java/com/nimtome/app/database/RoomSpell.kt index 0760100..9cd9e9c 100644 --- a/android-app/app/src/main/java/com/nimtome/app/database/RoomSpell.kt +++ b/android-app/app/src/main/java/com/nimtome/app/database/RoomSpell.kt @@ -18,5 +18,5 @@ data class RoomSpell( val ritual: Boolean, val duration: String, val classes: String, - val roll: String? + val roll: String?, ) diff --git a/android-app/app/src/main/java/com/nimtome/app/model/DndClass.kt b/android-app/app/src/main/java/com/nimtome/app/model/DndClass.kt index 250a24a..1c89589 100644 --- a/android-app/app/src/main/java/com/nimtome/app/model/DndClass.kt +++ b/android-app/app/src/main/java/com/nimtome/app/model/DndClass.kt @@ -12,5 +12,6 @@ enum class DndClass(val legibleName: String) { Sorcerer("Sorcerer"), Warlock("Warlock"), Wizard("Wizard"), - None("None"), ; + None("None"), + ; } diff --git a/android-app/app/src/main/java/com/nimtome/app/model/Spell.kt b/android-app/app/src/main/java/com/nimtome/app/model/Spell.kt index 3f3ce1d..28d87ee 100644 --- a/android-app/app/src/main/java/com/nimtome/app/model/Spell.kt +++ b/android-app/app/src/main/java/com/nimtome/app/model/Spell.kt @@ -11,7 +11,7 @@ data class Spell( val ritual: Boolean, val duration: String, val classes: String, - val roll: String? + val roll: String?, ) { constructor() : this( name = "", diff --git a/android-app/app/src/main/java/com/nimtome/app/model/SpellImporter.kt b/android-app/app/src/main/java/com/nimtome/app/model/SpellImporter.kt index 14690a1..4ad83a3 100644 --- a/android-app/app/src/main/java/com/nimtome/app/model/SpellImporter.kt +++ b/android-app/app/src/main/java/com/nimtome/app/model/SpellImporter.kt @@ -51,6 +51,7 @@ class SpellImporter { } } } + @Suppress("ComplexMethod") private fun readSpell(parser: XmlPullParser): Spell { parser.require(XmlPullParser.START_TAG, null, "spell") diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/ClassSelector.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/ClassSelector.kt index c781b6b..39ef7cb 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/components/ClassSelector.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/ClassSelector.kt @@ -21,7 +21,7 @@ fun ClassSelector( modifier: Modifier, allClasses: List, onClassChange: (DndClass) -> Unit, - starterClass: DndClass + starterClass: DndClass, ) { var expandedState by remember { mutableStateOf(false) } var selectedOption by remember { mutableStateOf(starterClass) } diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorPaletteSelector.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorPaletteSelector.kt new file mode 100644 index 0000000..57fab91 --- /dev/null +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorPaletteSelector.kt @@ -0,0 +1,59 @@ +package com.nimtome.app.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Card +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.nimtome.app.ui.theme.CARD_INNER_FILL_RATIO +import com.nimtome.app.ui.theme.ColorPalette + +@Composable +fun ColorPaletteSelector( + modifier: Modifier = Modifier, + selected: ColorPalette, + onChanged: (ColorPalette) -> Unit, +) { + Card( + modifier, + backgroundColor = Color.Transparent, + elevation = 0.dp + ) { + LazyRow( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(CARD_INNER_FILL_RATIO) + ) { + this.items( + items = ColorPalette.values(), + itemContent = { colorPalette -> + ColorSelectorRadio( + selected = colorPalette == selected, + onClick = { onChanged(colorPalette) }, + colors = colorPalette.lightColors, + ) + } + ) + } + } +} + +@Preview +@Composable +fun ColorPaletteSelectorPreview() { + var colorPalette by remember { mutableStateOf(ColorPalette.Purple) } + Surface { + ColorPaletteSelector(selected = colorPalette, + onChanged = { colorPalette = it }, + modifier = Modifier.fillMaxWidth(CARD_INNER_FILL_RATIO)) + } +} \ No newline at end of file diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorSelectorRadio.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorSelectorRadio.kt new file mode 100644 index 0000000..88dd7c4 --- /dev/null +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/ColorSelectorRadio.kt @@ -0,0 +1,31 @@ +package com.nimtome.app.ui.components + +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Card +import androidx.compose.material.Colors +import androidx.compose.material.MaterialTheme +import androidx.compose.material.RadioButton +import androidx.compose.material.RadioButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +@Composable +fun ColorSelectorRadio( + selected: Boolean, + onClick: () -> Unit, + colors: Colors, + backgroundColor: Color = MaterialTheme.colors.background, +) { + Card( + shape = CircleShape, + backgroundColor = backgroundColor + ) { + RadioButton( + selected = selected, + onClick = onClick, + colors = RadioButtonDefaults.colors(selectedColor = colors.primary, + unselectedColor = colors.primary), + ) + } + +} \ No newline at end of file diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/DndTopBar.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/DndTopBar.kt index fac5722..fd27f61 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/components/DndTopBar.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/DndTopBar.kt @@ -18,7 +18,7 @@ import com.nimtome.app.R @Composable fun DndTopBar( titleText: String? = null, - actions: @Composable RowScope.() -> Unit = {} + actions: @Composable RowScope.() -> Unit = {}, ) { val activity = (LocalContext.current as? Activity) diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/LevelSelector.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/LevelSelector.kt index a248301..644be4e 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/components/LevelSelector.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/LevelSelector.kt @@ -43,7 +43,7 @@ private const val LEVELS_COUNT = 20f @Composable private fun LevelSlider( starterValue: Int, - onValueChange: (Int) -> Unit + onValueChange: (Int) -> Unit, ) { var sliderPosition by remember { mutableStateOf(starterValue / LEVELS_COUNT) } diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelector.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelector.kt new file mode 100644 index 0000000..4b278e7 --- /dev/null +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelector.kt @@ -0,0 +1,38 @@ +package com.nimtome.app.ui.components + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +enum class MainMenuElement(val legibleName: String) { + + CHARACTERS("Characters"), + SPELLS("Spells"),; +} + +@ExperimentalMaterialApi +@Composable +fun MainMenuContentSelector( + modifier: Modifier = Modifier, + selectedElement: MainMenuElement, + onSelectedElementChanged: (MainMenuElement) -> Unit, +) { + LazyColumn( + modifier, + contentPadding = PaddingValues(1.dp) + ) { + items(MainMenuElement.values()) { mainMenuElement -> + MainMenuContentSelectorButton( + modifier = Modifier.fillMaxWidth(), + selected = mainMenuElement == selectedElement, + onClick = { onSelectedElementChanged(mainMenuElement) }, + text = mainMenuElement.legibleName + ) + } + } +} \ No newline at end of file diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelectorButton.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelectorButton.kt new file mode 100644 index 0000000..77e9d21 --- /dev/null +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuContentSelectorButton.kt @@ -0,0 +1,84 @@ +package com.nimtome.app.ui.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Card +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color + +@ExperimentalMaterialApi +@Composable +fun MainMenuContentSelectorButton( + modifier: Modifier = Modifier, + selected: Boolean, + onClick: () -> Unit, + text: String, +) { + val backgroundColor: Color + val outlineColor: Color + val textColor: Color + if (selected) { + backgroundColor = MaterialTheme.colors.primaryVariant + outlineColor = Color.Transparent + textColor = MaterialTheme.colors.onPrimary + } else { + backgroundColor = MaterialTheme.colors.primary + outlineColor = MaterialTheme.colors.primary + textColor = MaterialTheme.colors.onPrimary + } + + Card( + modifier = modifier, + elevation = 0.dp, + backgroundColor = backgroundColor, + border = BorderStroke(2.dp, outlineColor), + onClick = onClick, + ) { + Row( + Modifier + .padding(3.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = text, + color = textColor, + style = MaterialTheme.typography.h6 + ) + } + } +} + +@ExperimentalMaterialApi +@Preview +@Composable +fun ContentSelectedButtonPreview() { + MainMenuContentSelectorButton( + selected = true, + onClick = { /*TODO*/ }, + text = "Spells" + ) +} + +@ExperimentalMaterialApi +@Preview +@Composable +fun ContentUnselectedButtonPreview() { + MainMenuContentSelectorButton( + selected = false, + onClick = { /*TODO*/ }, + text = "Spells" + ) +} + + + diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuSpellCard.kt b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuSpellCard.kt index 473c753..2c93556 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuSpellCard.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/components/MainMenuSpellCard.kt @@ -28,7 +28,7 @@ fun MainMenuSpellCard( modifier: Modifier = Modifier, onClick: (Spell) -> Unit, onEditClick: (Spell) -> Unit, - isEditMode: Boolean = false + isEditMode: Boolean = false, ) { Card( elevation = CARD_ELEVATION, diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/theme/Color.kt b/android-app/app/src/main/java/com/nimtome/app/ui/theme/Color.kt index 72181dd..74365e0 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/theme/Color.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/theme/Color.kt @@ -4,9 +4,34 @@ import androidx.compose.ui.graphics.Color @Suppress("MagicNumber") val Purple200 = Color(0xFFBB86FC) + @Suppress("MagicNumber") val Purple500 = Color(0xFF6200EE) + @Suppress("MagicNumber") val Purple700 = Color(0xFF3700B3) + @Suppress("MagicNumber") val Teal200 = Color(0xFF03DAC5) + +@Suppress("MagicNumber") +val Blue200 = Color(0xFF6ec5ff) + +@Suppress("MagicNumber") +val Blue700 = Color(0xff0068bf) + +@Suppress("MagicNumber") +val Blue500 = Color(0xff2195f2) + +@Suppress("MagicNumber") +val Orange300 = Color(0xffffb74d) + +@Suppress("MagicNumber") +val Orange300Dark = Color(0xffc88719) + +@Suppress("MagicNumber") +val Orange300Light = Color(0xffffe97d) +val Red300 = Color(0xffe57373) +val Red300Dark = Color(0xffaf4448) + + diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/theme/ColorPalettes.kt b/android-app/app/src/main/java/com/nimtome/app/ui/theme/ColorPalettes.kt new file mode 100644 index 0000000..1cf3edf --- /dev/null +++ b/android-app/app/src/main/java/com/nimtome/app/ui/theme/ColorPalettes.kt @@ -0,0 +1,64 @@ +package com.nimtome.app.ui.theme + +import androidx.compose.material.Colors +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.ui.graphics.Color + +val DarkPurpleColorPalette = darkColors( + primary = Purple200, + primaryVariant = Purple700, + secondary = Teal200 +) + +val LightPurpleColorPalette = lightColors( + primary = Purple500, + primaryVariant = Purple700, + secondary = Teal200 + + /* Other default colors to override + background = Color.White, + surface = Color.White, + onPrimary = Color.White, + onSecondary = Color.Black, + onBackground = Color.Black, + onSurface = Color.Black, + */ +) + +val DarkBlueColorPalette = darkColors( + primary = Blue200, + primaryVariant = Blue700, + secondary = Teal200 +) + +val LightBlueColorPalette = lightColors( + primary = Blue500, + primaryVariant = Blue700, + secondary = Teal200, +) + +val DarkOrangeColorPalette = darkColors( + primary = Orange300Light, + primaryVariant = Orange300Dark, + secondary = Red300, + secondaryVariant = Red300Dark, +) + +val LightOrangeColorPalette = lightColors( + primary = Orange300, + primaryVariant = Orange300Dark, + secondary = Red300, + secondaryVariant = Red300Dark, + onPrimary = Color.Black + +) + +enum class ColorPalette( + val darkColors: Colors, + val lightColors: Colors, +) { + Orange(DarkOrangeColorPalette, LightOrangeColorPalette), + Blue(DarkBlueColorPalette, LightBlueColorPalette), + Purple(DarkPurpleColorPalette, LightPurpleColorPalette), +} \ No newline at end of file diff --git a/android-app/app/src/main/java/com/nimtome/app/ui/theme/Theme.kt b/android-app/app/src/main/java/com/nimtome/app/ui/theme/Theme.kt index a8b295f..a29586a 100644 --- a/android-app/app/src/main/java/com/nimtome/app/ui/theme/Theme.kt +++ b/android-app/app/src/main/java/com/nimtome/app/ui/theme/Theme.kt @@ -1,44 +1,23 @@ package com.nimtome.app.ui.theme import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material.Colors import androidx.compose.material.MaterialTheme -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors -import androidx.compose.material3.TopAppBarColors -import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.graphics.Color - -private val DarkColorPalette = darkColors( - primary = Purple200, - primaryVariant = Purple700, - secondary = Teal200 -) - -private val LightColorPalette = lightColors( - primary = Purple500, - primaryVariant = Purple700, - secondary = Teal200 - - /* Other default colors to override - background = Color.White, - surface = Color.White, - onPrimary = Color.White, - onSecondary = Color.Black, - onBackground = Color.Black, - onSurface = Color.Black, - */ -) +import androidx.compose.runtime.SideEffect +import com.google.accompanist.systemuicontroller.rememberSystemUiController @Composable -fun DndSpellsTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) { +fun DndSpellsTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + darkColors: Colors = DarkPurpleColorPalette, + lightColors: Colors = LightPurpleColorPalette, + content: @Composable() () -> Unit, +) { val colors = if (darkTheme) { - DarkColorPalette + darkColors } else { - LightColorPalette + lightColors } MaterialTheme( @@ -47,31 +26,19 @@ fun DndSpellsTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composa shapes = Shapes, content = content ) -} -class CharacterListTopbarColors : TopAppBarColors { - @Composable - override fun actionIconContentColor(scrollFraction: Float): State { - return TopAppBarDefaults.centerAlignedTopAppBarColors().actionIconContentColor( - scrollFraction = scrollFraction + val systemUiController = rememberSystemUiController() + val useDarkIcons = !colors.isLight + val systemBarColor = colors.primary + SideEffect { + systemUiController.setStatusBarColor( + color = systemBarColor, + darkIcons = useDarkIcons ) - } - @Composable - override fun containerColor(scrollFraction: Float): State { - val color = MaterialTheme.colors.primary - return remember { mutableStateOf(color) } - } - - @Composable - override fun navigationIconContentColor(scrollFraction: Float): State { - return TopAppBarDefaults.centerAlignedTopAppBarColors() - .navigationIconContentColor(scrollFraction = scrollFraction) - } - - @Composable - override fun titleContentColor(scrollFraction: Float): State { - return TopAppBarDefaults.centerAlignedTopAppBarColors() - .titleContentColor(scrollFraction = scrollFraction) + systemUiController.setNavigationBarColor( + color = colors.background, + ) } } +