Added error dialog when trying to load an invalid theme file

Fixes #26
This commit is contained in:
Abdelilah El Aissaoui 2023-03-18 19:11:26 +01:00
parent 3a473142ae
commit 856df1e64a
No known key found for this signature in database
GPG Key ID: 7587FC860F594869
5 changed files with 107 additions and 62 deletions

View File

@ -166,17 +166,13 @@ class AppSettings @Inject constructor() {
} }
fun saveCustomTheme(filePath: String) { fun saveCustomTheme(filePath: String) {
try { val file = File(filePath)
val file = File(filePath) val content = file.readText()
val content = file.readText()
Json.decodeFromString<ColorsScheme>(content) // Load to see if it's valid (it will crash if not) Json.decodeFromString<ColorsScheme>(content) // Load to see if it's valid (it will crash if not)
preferences.put(PREF_CUSTOM_THEME, content) preferences.put(PREF_CUSTOM_THEME, content)
loadCustomTheme() loadCustomTheme()
} catch (ex: Exception) {
ex.printStackTrace()
}
} }
fun loadCustomTheme() { fun loadCustomTheme() {

View File

@ -2,26 +2,21 @@ package com.jetpackduba.gitnuro.ui
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Box
import androidx.compose.material.Icon import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.width
import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.res.painterResource
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 com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.LoadingRepository import com.jetpackduba.gitnuro.LoadingRepository
import com.jetpackduba.gitnuro.LocalTabScope
import com.jetpackduba.gitnuro.credentials.CredentialsAccepted import com.jetpackduba.gitnuro.credentials.CredentialsAccepted
import com.jetpackduba.gitnuro.credentials.CredentialsRequested import com.jetpackduba.gitnuro.credentials.CredentialsRequested
import com.jetpackduba.gitnuro.credentials.CredentialsState import com.jetpackduba.gitnuro.credentials.CredentialsState
import com.jetpackduba.gitnuro.ui.components.PrimaryButton
import com.jetpackduba.gitnuro.ui.dialogs.* import com.jetpackduba.gitnuro.ui.dialogs.*
import com.jetpackduba.gitnuro.ui.dialogs.settings.SettingsDialog import com.jetpackduba.gitnuro.ui.dialogs.settings.SettingsDialog
import com.jetpackduba.gitnuro.viewmodels.RepositorySelectionStatus import com.jetpackduba.gitnuro.viewmodels.RepositorySelectionStatus
@ -115,47 +110,10 @@ fun AppTab(
val safeLastError = lastError val safeLastError = lastError
if (safeLastError != null && showError) { if (safeLastError != null && showError) {
MaterialDialog { ErrorDialog(
Column( error = safeLastError,
modifier = Modifier onAccept = { tabViewModel.showError.value = false }
.width(580.dp) )
) {
Row {
Text(
text = "Error",
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colors.onBackground,
)
Spacer(modifier = Modifier.weight(1f))
Icon(
painterResource(AppIcons.ERROR),
contentDescription = null,
tint = MaterialTheme.colors.error,
modifier = Modifier.size(24.dp)
)
}
Text(
text = lastError?.message ?: "",
color = MaterialTheme.colors.onBackground,
modifier = Modifier
.padding(top = 16.dp)
.widthIn(max = 600.dp),
style = MaterialTheme.typography.body2,
)
Row(
modifier = Modifier
.align(Alignment.End)
.padding(top = 32.dp)
) {
PrimaryButton(text = "OK", onClick = { tabViewModel.showError.value = false })
}
}
}
} }
} }
} }

View File

@ -0,0 +1,67 @@
package com.jetpackduba.gitnuro.ui.dialogs
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.Error
import com.jetpackduba.gitnuro.ui.components.PrimaryButton
@Composable
fun ErrorDialog(
error: Error,
onAccept: () -> Unit,
) {
MaterialDialog {
Column(
modifier = Modifier
.width(580.dp)
) {
Row {
Text(
text = "Error",
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colors.onBackground,
)
Spacer(modifier = Modifier.weight(1f))
Icon(
painterResource(AppIcons.ERROR),
contentDescription = null,
tint = MaterialTheme.colors.error,
modifier = Modifier.size(24.dp)
)
}
Text(
text = error.message,
color = MaterialTheme.colors.onBackground,
modifier = Modifier
.padding(top = 16.dp)
.widthIn(max = 600.dp),
style = MaterialTheme.typography.body2,
)
Row(
modifier = Modifier
.align(Alignment.End)
.padding(top = 32.dp)
) {
PrimaryButton(
text = "OK",
onClick = onAccept
)
}
}
}
}

View File

@ -13,6 +13,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppIcons import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.Error
import com.jetpackduba.gitnuro.extensions.handMouseClickable import com.jetpackduba.gitnuro.extensions.handMouseClickable
import com.jetpackduba.gitnuro.preferences.DEFAULT_UI_SCALE import com.jetpackduba.gitnuro.preferences.DEFAULT_UI_SCALE
import com.jetpackduba.gitnuro.theme.* import com.jetpackduba.gitnuro.theme.*
@ -20,6 +21,7 @@ import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField
import com.jetpackduba.gitnuro.ui.components.PrimaryButton import com.jetpackduba.gitnuro.ui.components.PrimaryButton
import com.jetpackduba.gitnuro.ui.components.ScrollableColumn import com.jetpackduba.gitnuro.ui.components.ScrollableColumn
import com.jetpackduba.gitnuro.ui.components.gitnuroViewModel import com.jetpackduba.gitnuro.ui.components.gitnuroViewModel
import com.jetpackduba.gitnuro.ui.dialogs.ErrorDialog
import com.jetpackduba.gitnuro.ui.dialogs.MaterialDialog import com.jetpackduba.gitnuro.ui.dialogs.MaterialDialog
import com.jetpackduba.gitnuro.ui.dropdowns.DropDownOption import com.jetpackduba.gitnuro.ui.dropdowns.DropDownOption
import com.jetpackduba.gitnuro.ui.dropdowns.ScaleDropDown import com.jetpackduba.gitnuro.ui.dropdowns.ScaleDropDown
@ -161,6 +163,7 @@ fun GitSettings(settingsViewModel: SettingsViewModel) {
@Composable @Composable
fun UiSettings(settingsViewModel: SettingsViewModel) { fun UiSettings(settingsViewModel: SettingsViewModel) {
val currentTheme by settingsViewModel.themeState.collectAsState() val currentTheme by settingsViewModel.themeState.collectAsState()
val (errorToDisplay, setErrorToDisplay) = remember { mutableStateOf<Error?>(null) }
SettingDropDown( SettingDropDown(
title = "Theme", title = "Theme",
@ -181,7 +184,13 @@ fun UiSettings(settingsViewModel: SettingsViewModel) {
val filePath = openFileDialog() val filePath = openFileDialog()
if (filePath != null) { if (filePath != null) {
settingsViewModel.saveCustomTheme(filePath) val error = settingsViewModel.saveCustomTheme(filePath)
// We check if it's null because setting errorToDisplay to null could possibly hide
// other errors that are being displayed
if (error != null) {
setErrorToDisplay(error)
}
} }
} }
) )
@ -233,6 +242,13 @@ fun UiSettings(settingsViewModel: SettingsViewModel) {
settingsViewModel.scaleUi = newValue.value settingsViewModel.scaleUi = newValue.value
} }
) )
if (errorToDisplay != null) {
ErrorDialog(
errorToDisplay,
onAccept = { setErrorToDisplay(null) }
)
}
} }
@Composable @Composable

View File

@ -1,6 +1,8 @@
package com.jetpackduba.gitnuro.viewmodels package com.jetpackduba.gitnuro.viewmodels
import com.jetpackduba.gitnuro.Error
import com.jetpackduba.gitnuro.di.qualifiers.AppCoroutineScope import com.jetpackduba.gitnuro.di.qualifiers.AppCoroutineScope
import com.jetpackduba.gitnuro.newErrorNow
import com.jetpackduba.gitnuro.preferences.AppSettings import com.jetpackduba.gitnuro.preferences.AppSettings
import com.jetpackduba.gitnuro.theme.Theme import com.jetpackduba.gitnuro.theme.Theme
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -51,8 +53,14 @@ class SettingsViewModel @Inject constructor(
appSettings.theme = value appSettings.theme = value
} }
fun saveCustomTheme(filePath: String) { fun saveCustomTheme(filePath: String): Error? {
appSettings.saveCustomTheme(filePath) return try {
appSettings.saveCustomTheme(filePath)
null
} catch (ex: Exception) {
ex.printStackTrace()
newErrorNow(ex, "Failed to parse selected theme JSON. Please check if it's valid and try again.")
}
} }