Added settings dialog & improved dark theme

This commit is contained in:
Abdelilah El Aissaoui 2021-12-08 19:04:16 +01:00
parent c7954af9ad
commit 0565bf1a33
11 changed files with 153 additions and 18 deletions

View File

@ -28,6 +28,7 @@ import app.theme.AppTheme
import app.ui.AppTab import app.ui.AppTab
import app.ui.components.RepositoriesTabPanel import app.ui.components.RepositoriesTabPanel
import app.ui.components.TabInformation import app.ui.components.TabInformation
import app.ui.dialogs.SettingsDialog
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider import javax.inject.Provider
@ -40,6 +41,9 @@ class Main {
@Inject @Inject
lateinit var appStateManager: AppStateManager lateinit var appStateManager: AppStateManager
@Inject
lateinit var appPreferences: AppPreferences
init { init {
appComponent.inject(this) appComponent.inject(this)
@ -48,7 +52,7 @@ class Main {
fun start() = application { fun start() = application {
var isOpen by remember { mutableStateOf(true) } var isOpen by remember { mutableStateOf(true) }
val theme by appPreferences.themeState.collectAsState()
if (isOpen) { if (isOpen) {
Window( Window(
title = "Gitnuro", title = "Gitnuro",
@ -61,9 +65,22 @@ class Main {
), ),
icon = painterResource("logo.svg"), icon = painterResource("logo.svg"),
) { ) {
AppTheme { var showSettingsDialog by remember { mutableStateOf(false) }
Box {
AppTabs() AppTheme(theme = theme) {
Box (modifier = Modifier.background(MaterialTheme.colors.background)) {
AppTabs(
onOpenSettings = {
showSettingsDialog = true
}
)
}
if(showSettingsDialog) {
SettingsDialog(
appPreferences = appPreferences,
onDismiss = { showSettingsDialog = false }
)
} }
} }
} }
@ -71,8 +88,12 @@ class Main {
} }
@Composable @Composable
fun AppTabs() { fun AppTabs(
onOpenSettings: () -> Unit,
) {
val tabs = remember { val tabs = remember {
val repositoriesSavedTabs = appStateManager.openRepositoriesPathsTabs val repositoriesSavedTabs = appStateManager.openRepositoriesPathsTabs
var repoTabs = repositoriesSavedTabs.map { repositoryTab -> var repoTabs = repositoriesSavedTabs.map { repositoryTab ->
@ -99,6 +120,7 @@ class Main {
Tabs( Tabs(
tabs = tabs, tabs = tabs,
selectedTabKey = selectedTabKey, selectedTabKey = selectedTabKey,
onOpenSettings = onOpenSettings
) )
TabsContent(tabs.value, selectedTabKey.value) TabsContent(tabs.value, selectedTabKey.value)
@ -109,6 +131,7 @@ class Main {
fun Tabs( fun Tabs(
tabs: MutableState<List<TabInformation>>, tabs: MutableState<List<TabInformation>>,
selectedTabKey: MutableState<Int>, selectedTabKey: MutableState<Int>,
onOpenSettings: () -> Unit,
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -140,7 +163,7 @@ class Main {
modifier = Modifier modifier = Modifier
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
.size(24.dp), .size(24.dp),
onClick = {} onClick = onOpenSettings
) { ) {
Icon( Icon(
painter = painterResource("settings.svg"), painter = painterResource("settings.svg"),

View File

@ -1,5 +1,8 @@
package app package app
import app.theme.Themes
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import java.util.prefs.Preferences import java.util.prefs.Preferences
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -8,11 +11,15 @@ private const val PREFERENCES_NAME = "GitnuroConfig"
private const val PREF_LATEST_REPOSITORIES_TABS_OPENED = "latestRepositoriesTabsOpened" private const val PREF_LATEST_REPOSITORIES_TABS_OPENED = "latestRepositoriesTabsOpened"
private const val PREF_LAST_OPENED_REPOSITORIES_PATH = "lastOpenedRepositoriesList" private const val PREF_LAST_OPENED_REPOSITORIES_PATH = "lastOpenedRepositoriesList"
private const val PREF_THEME = "theme"
@Singleton @Singleton
class AppPreferences @Inject constructor() { class AppPreferences @Inject constructor() {
private val preferences: Preferences = Preferences.userRoot().node(PREFERENCES_NAME) private val preferences: Preferences = Preferences.userRoot().node(PREFERENCES_NAME)
private val _themeState = MutableStateFlow(theme)
val themeState: StateFlow<Themes> = _themeState
var latestTabsOpened: String var latestTabsOpened: String
get() = preferences.get(PREF_LATEST_REPOSITORIES_TABS_OPENED, "") get() = preferences.get(PREF_LATEST_REPOSITORIES_TABS_OPENED, "")
set(value) { set(value) {
@ -24,4 +31,14 @@ class AppPreferences @Inject constructor() {
set(value) { set(value) {
preferences.put(PREF_LAST_OPENED_REPOSITORIES_PATH, value) preferences.put(PREF_LAST_OPENED_REPOSITORIES_PATH, value)
} }
var theme: Themes
get() {
val lastTheme = preferences.get(PREF_THEME, Themes.LIGHT.toString())
return Themes.valueOf(lastTheme)
}
set(value) {
preferences.put(PREF_THEME, value.toString())
_themeState.value = value
}
} }

View File

@ -24,11 +24,10 @@ private val LightColorPalette = lightColors(
) )
@Composable @Composable
fun AppTheme(darkTheme: Boolean = false, content: @Composable() () -> Unit) { fun AppTheme(theme: Themes = Themes.LIGHT, content: @Composable() () -> Unit) {
val colors = if (darkTheme) { val colors = when(theme) {
DarkColorPalette Themes.LIGHT -> LightColorPalette
} else { Themes.DARK -> DarkColorPalette
LightColorPalette
} }
MaterialTheme( MaterialTheme(
@ -91,3 +90,12 @@ val Colors.tabColorInactive: Color
get() = if (isLight) primaryLight else tabColorInactiveDark get() = if (isLight) primaryLight else tabColorInactiveDark
enum class Themes(val displayName: String) {
LIGHT("Light"),
DARK("Dark")
}
val themesList = listOf(
Themes.LIGHT,
Themes.DARK,
)

View File

@ -74,10 +74,9 @@ fun AppTab(
Box { Box {
Column( Column(
modifier = Modifier modifier = Modifier
.background(tabBackground) .background(MaterialTheme.colors.surface)
.fillMaxSize() .fillMaxSize()
) { ) {
val linearProgressAlpha = if (isProcessing) val linearProgressAlpha = if (isProcessing)
DefaultAlpha DefaultAlpha
else else

View File

@ -38,6 +38,7 @@ import app.git.StageStatus
import org.eclipse.jgit.diff.DiffEntry import org.eclipse.jgit.diff.DiffEntry
import app.theme.headerBackground import app.theme.headerBackground
import app.theme.headerText import app.theme.headerText
import app.theme.primaryTextColor
@OptIn(ExperimentalAnimationApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class) @OptIn(ExperimentalAnimationApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class)
@Composable @Composable
@ -311,6 +312,7 @@ private fun FileEntry(
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
fontSize = 14.sp, fontSize = 14.sp,
color = MaterialTheme.colors.primaryTextColor,
) )
} }
} }

View File

@ -11,6 +11,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.git.CloneStatus import app.git.CloneStatus
import app.git.GitManager import app.git.GitManager
import app.theme.primaryTextColor
import java.io.File import java.io.File
@Composable @Composable
@ -30,7 +31,10 @@ fun CloneDialog(
onClose() onClose()
} }
Text("Clone a repository") Text(
"Clone a repository",
color = MaterialTheme.colors.primaryTextColor,
)
OutlinedTextField( OutlinedTextField(
modifier = Modifier modifier = Modifier

View File

@ -15,6 +15,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import app.theme.primaryTextColor
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@ -41,18 +42,21 @@ fun MergeDialog(
Text( Text(
text = mergeBranchName, text = mergeBranchName,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium,
color = MaterialTheme.colors.primaryTextColor,
) )
Text( Text(
text = "will be merged into", text = "will be merged into",
modifier = Modifier.padding(horizontal = 8.dp) modifier = Modifier.padding(horizontal = 8.dp),
color = MaterialTheme.colors.primaryTextColor,
) )
Text( Text(
text = currentBranchName, text = currentBranchName,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium,
color = MaterialTheme.colors.primaryTextColor,
) )
} }

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import app.theme.primaryTextColor
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
@ -39,6 +40,7 @@ fun PasswordDialog(
text = "Introduce your default SSH key's password", text = "Introduce your default SSH key's password",
modifier = Modifier modifier = Modifier
.padding(vertical = 8.dp), .padding(vertical = 8.dp),
color = MaterialTheme.colors.primaryTextColor,
) )
OutlinedTextField( OutlinedTextField(
modifier = Modifier.padding(bottom = 8.dp) modifier = Modifier.padding(bottom = 8.dp)

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import app.git.ResetType import app.git.ResetType
import app.theme.primaryTextColor
@Composable @Composable
fun ResetBranchDialog( fun ResetBranchDialog(
@ -109,7 +110,8 @@ fun RadioButtonText(
Text( Text(
text = text, text = text,
modifier = Modifier.padding(horizontal = 8.dp) modifier = Modifier.padding(horizontal = 8.dp),
color = MaterialTheme.colors.primaryTextColor,
) )
} }
} }

View File

@ -0,0 +1,72 @@
@file:Suppress("UNUSED_PARAMETER")
package app.ui.dialogs
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import app.AppPreferences
import androidx.compose.ui.Alignment
import app.theme.Themes
import app.theme.primaryTextColor
import app.theme.themesList
@Composable
fun SettingsDialog(
appPreferences: AppPreferences,
onDismiss: () -> Unit,
) {
var showThemeDropdown by remember { mutableStateOf(false) }
val currentTheme by appPreferences.themeState.collectAsState()
MaterialDialog {
Column {
Text(
text = "Settings",
color = MaterialTheme.colors.primaryTextColor,
)
Row(
modifier = Modifier.padding(top = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Theme",
color = MaterialTheme.colors.primaryTextColor,
)
Spacer(modifier = Modifier.width(300.dp))
OutlinedButton(onClick = { showThemeDropdown = true }) {
Text(
currentTheme.displayName,
color = MaterialTheme.colors.primaryTextColor,
)
DropdownMenu(
expanded = showThemeDropdown,
onDismissRequest = { showThemeDropdown = false },
) {
for (theme in themesList) {
DropdownMenuItem(
onClick = {
appPreferences.theme = theme
showThemeDropdown = false
}
) { Text(theme.displayName) }
}
}
}
}
TextButton(
modifier = Modifier
.padding(end = 8.dp)
.align(Alignment.End),
onClick = onDismiss
) {
Text("Close")
}
}
}
}

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import app.theme.primaryTextColor
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
@ -43,6 +44,7 @@ fun UserPasswordDialog(
text = "Introduce your remote server credentials", text = "Introduce your remote server credentials",
modifier = Modifier modifier = Modifier
.padding(vertical = 8.dp), .padding(vertical = 8.dp),
color = MaterialTheme.colors.primaryTextColor,
) )
OutlinedTextField( OutlinedTextField(