mirror of
https://github.com/jrpie/Launcher.git
synced 2025-02-23 14:31:30 +01:00
improve json serialization
This commit is contained in:
parent
970c160f4a
commit
4ddb893d41
10 changed files with 169 additions and 138 deletions
|
@ -13,6 +13,8 @@ import de.jrpie.android.launcher.actions.TorchManager
|
||||||
import de.jrpie.android.launcher.apps.AppInfo
|
import de.jrpie.android.launcher.apps.AppInfo
|
||||||
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
|
||||||
|
import de.jrpie.android.launcher.preferences.resetPreferences
|
||||||
|
|
||||||
class Application : android.app.Application() {
|
class Application : android.app.Application() {
|
||||||
val apps = MutableLiveData<List<DetailedAppInfo>>()
|
val apps = MutableLiveData<List<DetailedAppInfo>>()
|
||||||
|
@ -85,6 +87,19 @@ class Application : android.app.Application() {
|
||||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
LauncherPreferences.init(preferences, this.resources)
|
LauncherPreferences.init(preferences, this.resources)
|
||||||
|
|
||||||
|
|
||||||
|
// Try to restore old preferences
|
||||||
|
migratePreferencesToNewVersion(this)
|
||||||
|
|
||||||
|
// First time opening the app: set defaults and start tutorial
|
||||||
|
if (!LauncherPreferences.internal().started()) {
|
||||||
|
resetPreferences(this)
|
||||||
|
|
||||||
|
LauncherPreferences.internal().started(true)
|
||||||
|
openTutorial(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LauncherPreferences.getSharedPreferences()
|
LauncherPreferences.getSharedPreferences()
|
||||||
.registerOnSharedPreferenceChangeListener(listener)
|
.registerOnSharedPreferenceChangeListener(listener)
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,9 @@ fun openInBrowser(url: String, context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openTutorial(context: Context) {
|
fun openTutorial(context: Context) {
|
||||||
context.startActivity(Intent(context, TutorialActivity::class.java))
|
context.startActivity(Intent(context, TutorialActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,13 @@ import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.encoding.decodeStructure
|
||||||
|
import kotlinx.serialization.encoding.encodeStructure
|
||||||
|
|
||||||
@Serializable(with = LauncherActionSerializer::class)
|
@Serializable(with = LauncherActionSerializer::class)
|
||||||
@SerialName("action:launcher")
|
@SerialName("action:launcher")
|
||||||
|
@ -248,30 +251,27 @@ fun openAppsList(context: Context, favorite: Boolean = false, hidden: Boolean =
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A custom serializer is required to store type information,
|
||||||
/**
|
see https://github.com/Kotlin/kotlinx.serialization/issues/1486
|
||||||
* LauncherAction can't be serialized directly, since it needs a type annotation.
|
|
||||||
* Thus this hack is needed.
|
|
||||||
*/
|
*/
|
||||||
@Serializable
|
private class LauncherActionSerializer : KSerializer<LauncherAction> {
|
||||||
private class LauncherActionWrapper(val id: String)
|
|
||||||
|
|
||||||
private class LauncherActionSerializer() : KSerializer<LauncherAction> {
|
|
||||||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor(
|
override val descriptor: SerialDescriptor = buildClassSerialDescriptor(
|
||||||
"action:launcher",
|
"action:launcher",
|
||||||
) {
|
) {
|
||||||
element("id", LauncherActionWrapper.serializer().descriptor)
|
element("value", String.serializer().descriptor)
|
||||||
}
|
}
|
||||||
override fun deserialize(decoder: Decoder): LauncherAction {
|
override fun deserialize(decoder: Decoder): LauncherAction {
|
||||||
val wrapper = decoder.decodeSerializableValue(LauncherActionWrapper.serializer())
|
val s = decoder.decodeStructure(descriptor) {
|
||||||
return LauncherAction.byId(wrapper.id) ?: throw SerializationException()
|
decodeElementIndex(descriptor)
|
||||||
|
decodeSerializableElement(descriptor, 0, String.serializer())
|
||||||
|
}
|
||||||
|
return LauncherAction.byId(s) ?: throw SerializationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serialize(encoder: Encoder, value: LauncherAction) {
|
override fun serialize(encoder: Encoder, value: LauncherAction) {
|
||||||
encoder.encodeSerializableValue(
|
encoder.encodeStructure(descriptor) {
|
||||||
LauncherActionWrapper.serializer(),
|
encodeSerializableElement(descriptor, 0, String.serializer(), value.id)
|
||||||
LauncherActionWrapper(value.id)
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,23 +1,18 @@
|
||||||
package de.jrpie.android.launcher.preferences;
|
package de.jrpie.android.launcher.preferences;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.jrpie.android.launcher.R;
|
import de.jrpie.android.launcher.R;
|
||||||
import de.jrpie.android.launcher.actions.lock.LockMethod;
|
import de.jrpie.android.launcher.actions.lock.LockMethod;
|
||||||
import de.jrpie.android.launcher.apps.AppInfo;
|
import de.jrpie.android.launcher.preferences.serialization.SetAppInfoPreferenceSerializer;
|
||||||
|
import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer;
|
||||||
import de.jrpie.android.launcher.preferences.theme.Background;
|
import de.jrpie.android.launcher.preferences.theme.Background;
|
||||||
import de.jrpie.android.launcher.preferences.theme.ColorTheme;
|
import de.jrpie.android.launcher.preferences.theme.ColorTheme;
|
||||||
import de.jrpie.android.launcher.preferences.theme.Font;
|
import de.jrpie.android.launcher.preferences.theme.Font;
|
||||||
import eu.jonahbauer.android.preference.annotations.Preference;
|
import eu.jonahbauer.android.preference.annotations.Preference;
|
||||||
import eu.jonahbauer.android.preference.annotations.PreferenceGroup;
|
import eu.jonahbauer.android.preference.annotations.PreferenceGroup;
|
||||||
import eu.jonahbauer.android.preference.annotations.Preferences;
|
import eu.jonahbauer.android.preference.annotations.Preferences;
|
||||||
import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializationException;
|
|
||||||
import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializer;
|
|
||||||
|
|
||||||
@Preferences(
|
@Preferences(
|
||||||
name = "de.jrpie.android.launcher.preferences.LauncherPreferences",
|
name = "de.jrpie.android.launcher.preferences.LauncherPreferences",
|
||||||
|
@ -30,9 +25,9 @@ import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSeriali
|
||||||
@Preference(name = "version_code", type = int.class, defaultValue = "-1"),
|
@Preference(name = "version_code", type = int.class, defaultValue = "-1"),
|
||||||
}),
|
}),
|
||||||
@PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = {
|
@PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = {
|
||||||
@Preference(name = "favorites", type = Set.class, serializer = LauncherPreferences$Config.AppInfoSetSerializer.class),
|
@Preference(name = "favorites", type = Set.class, serializer = SetAppInfoPreferenceSerializer.class),
|
||||||
@Preference(name = "hidden", type = Set.class, serializer = LauncherPreferences$Config.AppInfoSetSerializer.class),
|
@Preference(name = "hidden", type = Set.class, serializer = SetAppInfoPreferenceSerializer.class),
|
||||||
@Preference(name = "custom_names", type = HashMap.class, serializer = LauncherPreferences$Config.MapAppInfoStringSerializer.class),
|
@Preference(name = "custom_names", type = HashMap.class, serializer = MapAppInfoStringPreferenceSerializer.class),
|
||||||
@Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"),
|
@Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"),
|
||||||
}),
|
}),
|
||||||
@PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = {
|
@PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = {
|
||||||
|
@ -78,74 +73,4 @@ import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSeriali
|
||||||
@Preference(name = "lock_method", type = LockMethod.class, defaultValue = "DEVICE_ADMIN"),
|
@Preference(name = "lock_method", type = LockMethod.class, defaultValue = "DEVICE_ADMIN"),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
public final class LauncherPreferences$Config {
|
public final class LauncherPreferences$Config {}
|
||||||
public static class AppInfoSetSerializer implements PreferenceSerializer<Set<AppInfo>, Set<String>> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> serialize(Set<AppInfo> value) throws PreferenceSerializationException {
|
|
||||||
if (value == null) return null;
|
|
||||||
|
|
||||||
var serialized = new HashSet<String>(value.size());
|
|
||||||
for (var app : value) {
|
|
||||||
serialized.add(app.serialize());
|
|
||||||
}
|
|
||||||
|
|
||||||
return serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<AppInfo> deserialize(Set<String> value) throws PreferenceSerializationException {
|
|
||||||
if (value == null) return null;
|
|
||||||
|
|
||||||
var deserialized = new HashSet<AppInfo>(value.size());
|
|
||||||
|
|
||||||
for (var s : value) {
|
|
||||||
deserialized.add(AppInfo.Companion.deserialize(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
return deserialized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO migrate to version 2
|
|
||||||
public static class MapAppInfoStringSerializer implements PreferenceSerializer<HashMap<AppInfo, String>, Set<String>> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> serialize(HashMap<AppInfo, String> value) throws PreferenceSerializationException {
|
|
||||||
if (value == null) return null;
|
|
||||||
|
|
||||||
var serialized = new HashSet<String>(value.size());
|
|
||||||
|
|
||||||
for (var entry : value.entrySet()) {
|
|
||||||
JSONObject obj = new JSONObject();
|
|
||||||
try {
|
|
||||||
obj.put("key", entry.getKey().serialize());
|
|
||||||
obj.put("value", entry.getValue());
|
|
||||||
serialized.add(obj.toString());
|
|
||||||
} catch (JSONException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return serialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HashMap<AppInfo, String> deserialize(Set<String> value) throws PreferenceSerializationException {
|
|
||||||
if (value == null) return null;
|
|
||||||
|
|
||||||
var deserialized = new HashMap<AppInfo, String>();
|
|
||||||
|
|
||||||
for (var entry : value) {
|
|
||||||
try {
|
|
||||||
JSONObject obj = new JSONObject(entry);
|
|
||||||
AppInfo info = AppInfo.Companion.deserialize(obj.getString("key"));
|
|
||||||
String s = obj.getString("value");
|
|
||||||
deserialized.put(info, s);
|
|
||||||
} catch (JSONException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return deserialized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,8 +6,8 @@ import de.jrpie.android.launcher.BuildConfig
|
||||||
import de.jrpie.android.launcher.actions.Action
|
import de.jrpie.android.launcher.actions.Action
|
||||||
import de.jrpie.android.launcher.apps.AppInfo
|
import de.jrpie.android.launcher.apps.AppInfo
|
||||||
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
||||||
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersionUnknown
|
|
||||||
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1
|
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1
|
||||||
|
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersionUnknown
|
||||||
import de.jrpie.android.launcher.ui.HomeActivity
|
import de.jrpie.android.launcher.ui.HomeActivity
|
||||||
|
|
||||||
/* Current version of the structure of preferences.
|
/* Current version of the structure of preferences.
|
||||||
|
@ -19,8 +19,12 @@ const val UNKNOWN_PREFERENCE_VERSION = -1
|
||||||
private const val TAG = "Launcher - Preferences"
|
private const val TAG = "Launcher - Preferences"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tries to detect preferences written by older versions of the app
|
||||||
|
* and migrate them to the current format.
|
||||||
|
*/
|
||||||
fun migratePreferencesToNewVersion(context: Context) {
|
fun migratePreferencesToNewVersion(context: Context) {
|
||||||
|
try {
|
||||||
when (LauncherPreferences.internal().versionCode()) {
|
when (LauncherPreferences.internal().versionCode()) {
|
||||||
// Check versions, make sure transitions between versions go well
|
// Check versions, make sure transitions between versions go well
|
||||||
PREFERENCE_VERSION -> { /* the version installed and used previously are the same */
|
PREFERENCE_VERSION -> { /* the version installed and used previously are the same */
|
||||||
|
@ -31,6 +35,7 @@ fun migratePreferencesToNewVersion(context: Context) {
|
||||||
|
|
||||||
Log.i(TAG, "migration of preferences complete.")
|
Log.i(TAG, "migration of preferences complete.")
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
migratePreferencesFromVersion1()
|
migratePreferencesFromVersion1()
|
||||||
Log.i(TAG, "migration of preferences complete.")
|
Log.i(TAG, "migration of preferences complete.")
|
||||||
|
@ -45,6 +50,10 @@ fun migratePreferencesToNewVersion(context: Context) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Unable to restore preferences:\n${e.stackTrace}")
|
||||||
|
resetPreferences(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetPreferences(context: Context) {
|
fun resetPreferences(context: Context) {
|
||||||
|
|
|
@ -7,8 +7,12 @@ import de.jrpie.android.launcher.actions.LauncherAction
|
||||||
import de.jrpie.android.launcher.apps.AppInfo
|
import de.jrpie.android.launcher.apps.AppInfo
|
||||||
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
|
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
|
||||||
|
import de.jrpie.android.launcher.preferences.serialization.MapAppInfoStringPreferenceSerializer
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
val oldLauncherActionIds: Map<String, LauncherAction> =
|
val oldLauncherActionIds: Map<String, LauncherAction> =
|
||||||
mapOf(
|
mapOf(
|
||||||
|
@ -44,7 +48,7 @@ private fun AppInfo.Companion.legacyDeserialize(serialized: String): AppInfo {
|
||||||
* @param id
|
* @param id
|
||||||
* @param user a user id, ignored if the action is a [LauncherAction].
|
* @param user a user id, ignored if the action is a [LauncherAction].
|
||||||
*/
|
*/
|
||||||
private fun Action.Companion.fromId(id: String, user: Int?): Action? {
|
private fun Action.Companion.legacyFromId(id: String, user: Int?): Action? {
|
||||||
if (id.isEmpty()) {
|
if (id.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -68,7 +72,25 @@ private fun Action.Companion.legacyFromPreference(id: String): Action? {
|
||||||
)
|
)
|
||||||
u = if (u == AppInfo.INVALID_USER) null else u
|
u = if (u == AppInfo.INVALID_USER) null else u
|
||||||
|
|
||||||
return Action.fromId(actionId, u)
|
return Action.legacyFromId(actionId, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateAppInfoStringMap(key: String) {
|
||||||
|
val preferences = LauncherPreferences.getSharedPreferences()
|
||||||
|
MapAppInfoStringPreferenceSerializer().serialize(
|
||||||
|
preferences.getStringSet(key, setOf())?.mapNotNull { entry ->
|
||||||
|
try {
|
||||||
|
val obj = JSONObject(entry);
|
||||||
|
val info = AppInfo.legacyDeserialize(obj.getString("key"))
|
||||||
|
val value = obj.getString("value");
|
||||||
|
Pair(info, value)
|
||||||
|
} catch (_: JSONException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}?.toMap(HashMap())
|
||||||
|
)?.let {
|
||||||
|
preferences.edit().putStringSet(key, it as Set<String>).apply()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun migrateAppInfoSet(key: String) {
|
private fun migrateAppInfoSet(key: String) {
|
||||||
|
@ -82,13 +104,24 @@ private fun migrateAppInfoSet(key: String) {
|
||||||
private fun migrateAction(key: String) {
|
private fun migrateAction(key: String) {
|
||||||
Action.legacyFromPreference(key)?.let { action ->
|
Action.legacyFromPreference(key)?.let { action ->
|
||||||
LauncherPreferences.getSharedPreferences().edit()
|
LauncherPreferences.getSharedPreferences().edit()
|
||||||
.putString(key, Json.encodeToString(action)).apply()
|
.putString(key, Json.encodeToString(action))
|
||||||
|
.remove("$key.app")
|
||||||
|
.remove("$key.user")
|
||||||
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate preferences from version 1 (used until version j-0.0.18) to the current format
|
||||||
|
* (see [PREFERENCE_VERSION])
|
||||||
|
*/
|
||||||
fun migratePreferencesFromVersion1() {
|
fun migratePreferencesFromVersion1() {
|
||||||
|
assert(PREFERENCE_VERSION == 2)
|
||||||
|
assert(LauncherPreferences.internal().versionCode() == 1)
|
||||||
Gesture.entries.forEach { g -> migrateAction(g.id) }
|
Gesture.entries.forEach { g -> migrateAction(g.id) }
|
||||||
migrateAppInfoSet(LauncherPreferences.apps().keys().hidden())
|
migrateAppInfoSet(LauncherPreferences.apps().keys().hidden())
|
||||||
migrateAppInfoSet(LauncherPreferences.apps().keys().favorites())
|
migrateAppInfoSet(LauncherPreferences.apps().keys().favorites())
|
||||||
|
migrateAppInfoStringMap(LauncherPreferences.apps().keys().customNames())
|
||||||
|
LauncherPreferences.internal().versionCode(2)
|
||||||
}
|
}
|
|
@ -4,9 +4,12 @@ import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
|
||||||
import de.jrpie.android.launcher.preferences.theme.Background
|
import de.jrpie.android.launcher.preferences.theme.Background
|
||||||
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun migrateStringPreference(
|
private fun migrateStringPreference(
|
||||||
oldPrefs: SharedPreferences,
|
oldPrefs: SharedPreferences,
|
||||||
newPreferences: SharedPreferences.Editor,
|
newPreferences: SharedPreferences.Editor,
|
||||||
|
@ -42,7 +45,13 @@ private fun migrateBooleanPreference(
|
||||||
|
|
||||||
private const val TAG = "Preferences ? -> 1"
|
private const val TAG = "Preferences ? -> 1"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to migrate from a very old preference version, where no version number was stored
|
||||||
|
* and a different file was used.
|
||||||
|
*/
|
||||||
fun migratePreferencesFromVersionUnknown(context: Context) {
|
fun migratePreferencesFromVersionUnknown(context: Context) {
|
||||||
|
assert(PREFERENCE_VERSION == 2)
|
||||||
|
|
||||||
Log.i(
|
Log.i(
|
||||||
TAG,
|
TAG,
|
||||||
"Unknown preference version, trying to restore preferences from old version."
|
"Unknown preference version, trying to restore preferences from old version."
|
|
@ -0,0 +1,49 @@
|
||||||
|
@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||||
|
|
||||||
|
package de.jrpie.android.launcher.preferences.serialization
|
||||||
|
|
||||||
|
import de.jrpie.android.launcher.apps.AppInfo
|
||||||
|
import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializationException
|
||||||
|
import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
|
||||||
|
// Serializers for [LauncherPreference$Config]
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
class SetAppInfoPreferenceSerializer :
|
||||||
|
PreferenceSerializer<java.util.Set<AppInfo>?, java.util.Set<java.lang.String>?> {
|
||||||
|
@Throws(PreferenceSerializationException::class)
|
||||||
|
override fun serialize(value: java.util.Set<AppInfo>?): java.util.Set<java.lang.String>? {
|
||||||
|
return value?.map(AppInfo::serialize)?.toHashSet() as java.util.Set<java.lang.String>
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(PreferenceSerializationException::class)
|
||||||
|
override fun deserialize(value: java.util.Set<java.lang.String>?): java.util.Set<AppInfo>? {
|
||||||
|
return value?.map (java.lang.String::toString)?.map(AppInfo::deserialize)?.toHashSet() as? java.util.Set<AppInfo>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
class MapAppInfoStringPreferenceSerializer :
|
||||||
|
PreferenceSerializer<java.util.HashMap<AppInfo, String>?, java.util.Set<java.lang.String>?> {
|
||||||
|
|
||||||
|
@Serializable()
|
||||||
|
private class MapEntry(val key: AppInfo, val value: String)
|
||||||
|
|
||||||
|
@Throws(PreferenceSerializationException::class)
|
||||||
|
override fun serialize(value: java.util.HashMap<AppInfo, String>?): java.util.Set<java.lang.String>? {
|
||||||
|
return value?.map { (key, value) ->
|
||||||
|
Json.encodeToString(MapEntry(key, value))
|
||||||
|
}?.toHashSet() as? java.util.Set<java.lang.String>
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(PreferenceSerializationException::class)
|
||||||
|
override fun deserialize(value: java.util.Set<java.lang.String>?): java.util.HashMap<AppInfo, String>? {
|
||||||
|
return value?.associateTo(HashMap()) {
|
||||||
|
val entry = Json.decodeFromString<MapEntry>(it.toString())
|
||||||
|
Pair(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,17 +76,6 @@ class HomeActivity : UIObject, AppCompatActivity(),
|
||||||
super<AppCompatActivity>.onCreate(savedInstanceState)
|
super<AppCompatActivity>.onCreate(savedInstanceState)
|
||||||
super<UIObject>.onCreate()
|
super<UIObject>.onCreate()
|
||||||
|
|
||||||
// Try to restore old preferences
|
|
||||||
migratePreferencesToNewVersion(this)
|
|
||||||
|
|
||||||
// First time opening the app: set defaults and start tutorial
|
|
||||||
if (!LauncherPreferences.internal().started()) {
|
|
||||||
resetPreferences(this)
|
|
||||||
|
|
||||||
LauncherPreferences.internal().started(true)
|
|
||||||
openTutorial(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise layout
|
// Initialise layout
|
||||||
binding = HomeBinding.inflate(layoutInflater)
|
binding = HomeBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
<!-- Swipe up - Apps list -->
|
<!-- Swipe up - Apps list -->
|
||||||
<string-array name="default_up">
|
<string-array name="default_up">
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"choose\"}</item> <!-- All Apps -->
|
<item>{\"type\": \"action:launcher\", \"value\": \"choose\"}</item> <!-- All Apps -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe up (left edge) - Favorite Apps -->
|
<!-- Swipe up (left edge) - Favorite Apps -->
|
||||||
<string-array name="default_up_left">
|
<string-array name="default_up_left">
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"choose_from_favorites\"}</item>
|
<item>{\"type\": \"action:launcher\", \"value\": \"choose_from_favorites\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe up (right edge) - Maps -->
|
<!-- Swipe up (right edge) - Maps -->
|
||||||
|
@ -106,12 +106,12 @@
|
||||||
|
|
||||||
<!-- Volume up -->
|
<!-- Volume up -->
|
||||||
<string-array name="default_volume_up">
|
<string-array name="default_volume_up">
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"volume_up\"}</item>
|
<item>{\"type\": \"action:launcher\", \"value\": \"volume_up\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Volume down -->
|
<!-- Volume down -->
|
||||||
<string-array name="default_volume_down">
|
<string-array name="default_volume_down">
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"volume_down\"}</item>
|
<item>{\"type\": \"action:launcher\", \"value\": \"volume_down\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Double click - Notes -->
|
<!-- Double click - Notes -->
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"it.niedermann.owncloud.notes\", \"activityName\": null}}</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"it.niedermann.owncloud.notes\", \"activityName\": null}}</item>
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.app.notes\", \"activityName\": null}}</item> <!-- Samsung Notes -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.app.notes\", \"activityName\": null}}</item> <!-- Samsung Notes -->
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.sec.android.widgetapp.diotek.smemo\", \"activityName\": null}}</item> <!-- S Memo (older devices) -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.sec.android.widgetapp.diotek.smemo\", \"activityName\": null}}</item> <!-- S Memo (older devices) -->
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"lock_screen\"}</item>
|
<item>{\"type\": \"action:launcher\", \"value\": \"lock_screen\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Long click - Security -->
|
<!-- Long click - Security -->
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.fedorahosted.freeotp\", \"activityName\": null}}</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.fedorahosted.freeotp\", \"activityName\": null}}</item>
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"proton.android.pass.fdroid\", \"activityName\": null}}</item> <!-- Proton Pass -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"proton.android.pass.fdroid\", \"activityName\": null}}</item> <!-- Proton Pass -->
|
||||||
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.kunzisoft.keepass.libre\", \"activityName\": null}}</item> <!-- KeePassDX -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.kunzisoft.keepass.libre\", \"activityName\": null}}</item> <!-- KeePassDX -->
|
||||||
<item>{\"type\": \"action:launcher\", \"id\": \"settings\"}</item> <!-- Launcher Settings -->
|
<item>{\"type\": \"action:launcher\", \"value\": \"settings\"}</item> <!-- Launcher Settings -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Time / Clock -->
|
<!-- Time / Clock -->
|
||||||
|
|
Loading…
Add table
Reference in a new issue