Added settings dialog & improved dark theme
This commit is contained in:
parent
c7954af9ad
commit
0565bf1a33
@ -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"),
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
@ -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,
|
||||||
|
)
|
@ -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
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
72
src/main/kotlin/app/ui/dialogs/SettingsDialog.kt
Normal file
72
src/main/kotlin/app/ui/dialogs/SettingsDialog.kt
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user