diff --git a/app/src/main/java/com/bnyro/wallpaper/db/obj/BackupFile.kt b/app/src/main/java/com/bnyro/wallpaper/db/obj/BackupFile.kt new file mode 100644 index 00000000..13183423 --- /dev/null +++ b/app/src/main/java/com/bnyro/wallpaper/db/obj/BackupFile.kt @@ -0,0 +1,5 @@ +package com.bnyro.wallpaper.db.obj + +data class BackupFile( + val favorites: List = emptyList() +) diff --git a/app/src/main/java/com/bnyro/wallpaper/db/obj/Wallpaper.kt b/app/src/main/java/com/bnyro/wallpaper/db/obj/Wallpaper.kt index 4687bc63..3f24c1e9 100644 --- a/app/src/main/java/com/bnyro/wallpaper/db/obj/Wallpaper.kt +++ b/app/src/main/java/com/bnyro/wallpaper/db/obj/Wallpaper.kt @@ -6,7 +6,7 @@ import androidx.room.PrimaryKey @Entity(tableName = "favorites") data class Wallpaper( - @PrimaryKey val imgSrc: String, + @PrimaryKey val imgSrc: String = "", @ColumnInfo val title: String? = null, @ColumnInfo val url: String? = null, @ColumnInfo var author: String? = null, diff --git a/app/src/main/java/com/bnyro/wallpaper/ext/Context.kt b/app/src/main/java/com/bnyro/wallpaper/ext/Context.kt new file mode 100644 index 00000000..e4ceb61b --- /dev/null +++ b/app/src/main/java/com/bnyro/wallpaper/ext/Context.kt @@ -0,0 +1,11 @@ +package com.bnyro.wallpaper.ext + +import android.content.Context +import android.widget.Toast +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +suspend fun Context.toastFromMainThread(text: String?, length: Int = Toast.LENGTH_SHORT) += withContext(Dispatchers.Main) { + Toast.makeText(this@toastFromMainThread, text, length).show() +} \ No newline at end of file diff --git a/app/src/main/java/com/bnyro/wallpaper/ui/pages/SettingsPage.kt b/app/src/main/java/com/bnyro/wallpaper/ui/pages/SettingsPage.kt index d2c634fe..f96399fd 100644 --- a/app/src/main/java/com/bnyro/wallpaper/ui/pages/SettingsPage.kt +++ b/app/src/main/java/com/bnyro/wallpaper/ui/pages/SettingsPage.kt @@ -1,13 +1,20 @@ package com.bnyro.wallpaper.ui.pages +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -25,8 +32,11 @@ import com.bnyro.wallpaper.ui.components.prefs.CheckboxPref import com.bnyro.wallpaper.ui.components.prefs.ListPreference import com.bnyro.wallpaper.ui.components.prefs.SettingsCategory import com.bnyro.wallpaper.ui.models.MainModel +import com.bnyro.wallpaper.util.BackupHelper import com.bnyro.wallpaper.util.Preferences import com.bnyro.wallpaper.util.WorkerHelper +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @Composable fun SettingsPage( @@ -36,6 +46,20 @@ fun SettingsPage( val wallpaperConfigs = remember { Preferences.getWallpaperConfigs().toMutableStateList() } + val scope = rememberCoroutineScope() + + val createFavoritesBackup = + rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument(BackupHelper.JSON_MIME)) { + scope.launch(Dispatchers.IO) { + BackupHelper.backupFavorites(it ?: return@launch, context) + } + } + val restoreFavoritesBackup = + rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { + scope.launch(Dispatchers.IO) { + BackupHelper.restoreFavorites(it ?: return@launch, context) + } + } val scrollState = rememberScrollState() Column( @@ -169,5 +193,29 @@ fun SettingsPage( } } } + + AboutContainer { + SettingsCategory( + title = stringResource(R.string.import_export) + ) + Spacer(modifier = Modifier.height(6.dp)) + Row { + Button( + onClick = { + restoreFavoritesBackup.launch(arrayOf(BackupHelper.JSON_MIME)) + } + ) { + Text(stringResource(R.string.import_favorites)) + } + Spacer(modifier = Modifier.width(6.dp)) + Button( + onClick = { + createFavoritesBackup.launch("wall_you_favorites_backup.json") + } + ) { + Text(stringResource(R.string.export_favorites)) + } + } + } } } diff --git a/app/src/main/java/com/bnyro/wallpaper/util/BackupHelper.kt b/app/src/main/java/com/bnyro/wallpaper/util/BackupHelper.kt new file mode 100644 index 00000000..86500b77 --- /dev/null +++ b/app/src/main/java/com/bnyro/wallpaper/util/BackupHelper.kt @@ -0,0 +1,42 @@ +package com.bnyro.wallpaper.util + +import android.content.Context +import android.net.Uri +import com.bnyro.wallpaper.R +import com.bnyro.wallpaper.db.DatabaseHolder +import com.bnyro.wallpaper.db.obj.BackupFile +import com.bnyro.wallpaper.ext.toastFromMainThread +import com.fasterxml.jackson.databind.ObjectMapper + +object BackupHelper { + const val JSON_MIME = "application/json" + private val mapper by lazy { + ObjectMapper() + } + + suspend fun backupFavorites(uri: Uri, context: Context) { + try { + val favorites = DatabaseHolder.Database.favoritesDao().getAll() + val backupFile = BackupFile(favorites = favorites) + context.contentResolver.openOutputStream(uri)?.use { + val favoritesJson = mapper.writeValueAsBytes(backupFile) + it.write(favoritesJson) + } + context.toastFromMainThread(context.getString(R.string.success)) + } catch (e: Exception) { + context.toastFromMainThread(e.localizedMessage) + } + } + + suspend fun restoreFavorites(uri: Uri, context: Context) { + try { + context.contentResolver.openInputStream(uri)?.use { + val backupFile = mapper.readValue(it.readBytes(), BackupFile::class.java) + DatabaseHolder.Database.favoritesDao().insertAll(*backupFile.favorites.toTypedArray()) + } + context.toastFromMainThread(context.getString(R.string.success)) + } catch (e: Exception) { + context.toastFromMainThread(e.localizedMessage) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3057e66c..4980c6c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,6 +49,10 @@ Combined wallpaper changer Use the same wallpaper for home and lockscreen. Show color palette + Import & export + Import favorites + Export favorites + Success! Online Local