Add color scheme import/export

This commit is contained in:
MM20
2023-08-26 15:11:10 +02:00
parent d8e108cb70
commit 6c040bccce
5 changed files with 140 additions and 3 deletions
@@ -1,5 +1,7 @@
package de.mm20.launcher2.ui.settings.colorscheme
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
@@ -13,10 +15,12 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ContentCopy
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.Download
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.MoreVert
import androidx.compose.material.icons.rounded.RadioButtonChecked
import androidx.compose.material.icons.rounded.RadioButtonUnchecked
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
@@ -33,6 +37,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -51,13 +56,25 @@ import de.mm20.launcher2.ui.theme.colorscheme.lightColorSchemeOf
fun ThemesSettingsScreen() {
val viewModel: ThemesSettingsScreenVM = viewModel()
val navController = LocalNavController.current
val context = LocalContext.current
val selectedTheme by viewModel.selectedTheme.collectAsStateWithLifecycle(null)
val themes by viewModel.themes.collectAsStateWithLifecycle(emptyList())
var deleteTheme by remember { mutableStateOf<Theme?>(null) }
PreferenceScreen(title = stringResource(R.string.preference_screen_colors)) {
val importIntentLauncher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
viewModel.importTheme(context, it)
}
PreferenceScreen(
title = stringResource(R.string.preference_screen_colors),
topBarActions = {
IconButton(onClick = { importIntentLauncher.launch(arrayOf("*/*")) }) {
Icon(Icons.Rounded.Download, null)
}
}
) {
item {
PreferenceCategory {
for (theme in themes) {
@@ -102,6 +119,16 @@ fun ThemesSettingsScreen() {
}
)
if (!theme.builtIn) {
DropdownMenuItem(
leadingIcon = {
Icon(Icons.Rounded.Share, null)
},
text = { Text(stringResource(R.string.menu_share)) },
onClick = {
viewModel.exportTheme(context, theme)
showMenu = false
}
)
DropdownMenuItem(
leadingIcon = {
Icon(Icons.Rounded.Delete, null)
@@ -127,7 +154,14 @@ fun ThemesSettingsScreen() {
if (deleteTheme != null) {
AlertDialog(
onDismissRequest = { deleteTheme = null },
text = { Text(stringResource(R.string.confirmation_delete_color_scheme, deleteTheme!!.name)) },
text = {
Text(
stringResource(
R.string.confirmation_delete_color_scheme,
deleteTheme!!.name
)
)
},
confirmButton = {
TextButton(
onClick = {
@@ -1,20 +1,30 @@
package de.mm20.launcher2.ui.settings.colorscheme
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.core.content.FileProvider
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.protobuf.ByteString
import de.mm20.launcher2.ktx.toBytes
import de.mm20.launcher2.ktx.tryStartActivity
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.themes.DefaultThemeId
import de.mm20.launcher2.themes.Theme
import de.mm20.launcher2.themes.ThemeRepository
import de.mm20.launcher2.themes.fromJson
import de.mm20.launcher2.themes.toJson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.io.File
import java.util.UUID
class ThemesSettingsScreenVM : ViewModel(), KoinComponent {
@@ -57,4 +67,33 @@ class ThemesSettingsScreenVM : ViewModel(), KoinComponent {
fun delete(theme: Theme) {
themeRepository.deleteTheme(theme)
}
fun exportTheme(context: Context, theme: Theme) {
viewModelScope.launch {
val file = withContext(Dispatchers.IO) {
val file = File(context.cacheDir, "${theme.name}.kvtheme")
file.writeText(theme.toJson())
file
}
context.tryStartActivity(Intent().apply {
action = Intent.ACTION_SEND
type = "application/json"
putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(
context,
context.applicationContext.packageName + ".fileprovider",
file
))
}.let { Intent.createChooser(it, null) })
}
}
fun importTheme(context: Context, uri: Uri?) {
uri ?: return
viewModelScope.launch(Dispatchers.IO) {
context.contentResolver.openInputStream(uri)?.use {
val theme = Theme.fromJson(it.readBytes().toString(Charsets.UTF_8))
themeRepository.createTheme(theme.copy(id = UUID.randomUUID()))
}
}
}
}