finish appearance screen

This commit is contained in:
Helium314 2025-02-05 18:01:17 +01:00
parent 443223de6a
commit 6e3bedaf5c
2 changed files with 84 additions and 75 deletions

View file

@ -15,9 +15,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
// todo (roughly in order) // todo (roughly in order)
// make all prefs actually work // make all prefs actually work
// appearance
// click on bg image does nothing when already set (but works after reload)
// have large bg image, and first-time load the keyboard on new search field -> bg image expands full size
// advanced // advanced
// preferences // preferences
// try moving the recomposition of pref change somewhere else, so it's not duplicated everywhere // try moving the recomposition of pref change somewhere else, so it's not duplicated everywhere
@ -37,6 +34,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
// there is a lot more ambiguous naming... // there is a lot more ambiguous naming...
// animations when stuff (dis)appears // animations when stuff (dis)appears
// LaunchedEffect, AnimatedVisibility // LaunchedEffect, AnimatedVisibility
// bg image inconsistent about being on toolbar or not
// performance // performance
// find a nice way of testing (probably add logs for measuring time and recompositions) // find a nice way of testing (probably add logs for measuring time and recompositions)
// consider that stuff in composables can get called quite often on any changes // consider that stuff in composables can get called quite often on any changes

View file

@ -10,10 +10,8 @@ import android.net.Uri
import android.os.Build import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -217,77 +215,10 @@ fun createAppearancePrefs(context: Context) = listOf(
SwitchPreference(def, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) SwitchPreference(def, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
}, },
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE, R.string.customize_background_image) { def -> PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE, R.string.customize_background_image) { def ->
var showDayNightDialog by remember { mutableStateOf(false) } BackgroundImagePref(def, false)
var showSelectionDialog by remember { mutableStateOf(false) }
var showErrorDialog by remember { mutableStateOf(false) }
var isNight by remember { mutableStateOf(false) }
val ctx = LocalContext.current
val dayNightPref = Settings.readDayNightPref(ctx.prefs(), ctx.resources)
val scope = rememberCoroutineScope()
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
showSelectionDialog = false
showDayNightDialog = false
scope.launch(Dispatchers.IO) {
if (!setBackgroundImage(ctx, uri, isNight, false))
showErrorDialog = true
}
}
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("image/*")
Preference(
name = def.title,
onClick = {
if (dayNightPref) {
showDayNightDialog = true
} else if (!Settings.getCustomBackgroundFile(ctx, false, false).exists()) {
launcher.launch(intent)
} else {
showSelectionDialog = true
}
}
)
if (showDayNightDialog) {
// dialog to set isNight and then show other dialog if image exists
AlertDialog(
onDismissRequest = { showDayNightDialog = false },
confirmButton = {
TextButton(onClick = {
showDayNightDialog = false
isNight = false
if (Settings.getCustomBackgroundFile(ctx, isNight, false).exists())
showSelectionDialog = true
else launcher.launch(intent)
}) { Text(stringResource(R.string.day_or_night_day)) }
},
dismissButton = {
TextButton(onClick = {
showDayNightDialog = false
isNight = true
if (Settings.getCustomBackgroundFile(ctx, isNight, false).exists())
showSelectionDialog = true
else launcher.launch(intent)
}) { Text(stringResource(R.string.day_or_night_night)) }
},
title = { Text(stringResource(R.string.day_or_night_image)) },
)
}
if (showSelectionDialog) {
// todo: delete file or start launcher
}
if (showErrorDialog) {
// todo: infoDialog(requireContext(), R.string.file_read_error)
}
}, },
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE_LANDSCAPE, R.string.customize_background_image_landscape, R.string.summary_customize_background_image_landscape) { def -> PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE_LANDSCAPE, R.string.customize_background_image_landscape, R.string.summary_customize_background_image_landscape) { def ->
var showDialog by remember { mutableStateOf(false) } BackgroundImagePref(def, true)
Preference(
name = def.title,
description = def.description,
onClick = { showDialog = true }
) // todo: create and show the dialog
}, },
PrefDef(context, Settings.PREF_ENABLE_SPLIT_KEYBOARD, R.string.enable_split_keyboard) { PrefDef(context, Settings.PREF_ENABLE_SPLIT_KEYBOARD, R.string.enable_split_keyboard) {
SwitchPreference(it, false) SwitchPreference(it, false)
@ -393,8 +324,88 @@ fun createAppearancePrefs(context: Context) = listOf(
}, },
) )
@Composable
private fun BackgroundImagePref(def: PrefDef, isLandscape: Boolean) {
var showDayNightDialog by remember { mutableStateOf(false) }
var showSelectionDialog by remember { mutableStateOf(false) }
var showErrorDialog by remember { mutableStateOf(false) }
var isNight by remember { mutableStateOf(false) }
val ctx = LocalContext.current
fun getFile() = Settings.getCustomBackgroundFile(ctx, isNight, isLandscape)
val b = (ctx.getActivity() as? SettingsActivity2)?.prefChanged?.collectAsState()
if ((b?.value ?: 0) < 0) // necessary to reload dayNightPref
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
val dayNightPref = Settings.readDayNightPref(ctx.prefs(), ctx.resources)
if (!dayNightPref)
isNight = false
val scope = rememberCoroutineScope()
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
showSelectionDialog = false
showDayNightDialog = false
scope.launch(Dispatchers.IO) {
if (!setBackgroundImage(ctx, uri, isNight, isLandscape))
showErrorDialog = true
}
}
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("image/*")
Preference(
name = def.title,
onClick = {
if (dayNightPref) {
showDayNightDialog = true
} else if (!getFile().exists()) {
launcher.launch(intent)
} else {
showSelectionDialog = true
}
}
)
if (showDayNightDialog) {
ConfirmationDialog(
onDismissRequest = { showDayNightDialog = false },
onConfirmed = {
isNight = false
if (getFile().exists())
showSelectionDialog = true
else launcher.launch(intent)
},
confirmButtonText = stringResource(R.string.day_or_night_day),
cancelButtonText = "",
onNeutral = {
isNight = true
if (getFile().exists())
showSelectionDialog = true
else launcher.launch(intent)
},
neutralButtonText = stringResource(R.string.day_or_night_night),
title = { Text(stringResource(R.string.day_or_night_image)) },
)
}
if (showSelectionDialog) {
ConfirmationDialog(
onDismissRequest = { showSelectionDialog = false },
title = { Text(stringResource(R.string.customize_background_image)) },
confirmButtonText = stringResource(R.string.button_load_custom),
onConfirmed = { launcher.launch(intent) },
neutralButtonText = stringResource(R.string.delete),
onNeutral = {
getFile().delete()
Settings.clearCachedBackgroundImages()
keyboardNeedsReload = true
}
)
}
if (showErrorDialog) {
InfoDialog(stringResource(R.string.file_read_error)) { showErrorDialog = false }
}
}
private fun setBackgroundImage(ctx: Context, uri: Uri, isNight: Boolean, isLandscape: Boolean): Boolean { private fun setBackgroundImage(ctx: Context, uri: Uri, isNight: Boolean, isLandscape: Boolean): Boolean {
val imageFile = Settings.getCustomBackgroundFile(ctx, isNight, false) val imageFile = Settings.getCustomBackgroundFile(ctx, isNight, isLandscape)
FileUtils.copyContentUriToNewFile(uri, ctx, imageFile) FileUtils.copyContentUriToNewFile(uri, ctx, imageFile)
keyboardNeedsReload = true keyboardNeedsReload = true
try { try {