mirror of
https://github.com/jrpie/Launcher.git
synced 2025-02-23 14:31:30 +01:00
serialize to json
This commit is contained in:
parent
36ee8033ed
commit
970c160f4a
12 changed files with 668 additions and 572 deletions
|
@ -1,9 +1,9 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
||||||
dataBinding {
|
dataBinding {
|
||||||
enabled = true
|
enabled = true
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ dependencies {
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||||
implementation 'com.google.android.material:material:1.12.0'
|
implementation 'com.google.android.material:material:1.12.0'
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
|
||||||
implementation "eu.jonahbauer:android-preference-annotations:1.1.2"
|
implementation "eu.jonahbauer:android-preference-annotations:1.1.2"
|
||||||
annotationProcessor "eu.jonahbauer:android-preference-annotations:1.1.2"
|
annotationProcessor "eu.jonahbauer:android-preference-annotations:1.1.2"
|
||||||
annotationProcessor "com.android.databinding:compiler:$android_plugin_version"
|
annotationProcessor "com.android.databinding:compiler:$android_plugin_version"
|
||||||
|
|
|
@ -8,61 +8,36 @@ import android.graphics.Rect
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import de.jrpie.android.launcher.R
|
import de.jrpie.android.launcher.R
|
||||||
import de.jrpie.android.launcher.apps.AppInfo
|
|
||||||
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
|
|
||||||
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
interface Action {
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface Action {
|
||||||
fun invoke(context: Context, rect: Rect? = null): Boolean
|
fun invoke(context: Context, rect: Rect? = null): Boolean
|
||||||
fun bindToGesture(prefEditor: Editor, id: String)
|
|
||||||
fun label(context: Context): String
|
fun label(context: Context): String
|
||||||
fun getIcon(context: Context): Drawable?
|
fun getIcon(context: Context): Drawable?
|
||||||
fun isAvailable(context: Context): Boolean
|
fun isAvailable(context: Context): Boolean
|
||||||
|
|
||||||
fun writeToIntent(intent: Intent)
|
|
||||||
|
fun bindToGesture(prefEditor: Editor, id: String) {
|
||||||
|
prefEditor.putString(id, Json.encodeToString(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeToIntent(intent: Intent) {
|
||||||
|
intent.putExtra("action", Json.encodeToString(this))
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
|
||||||
* Get an action for a specific id.
|
|
||||||
* An id is of the form:
|
|
||||||
* - "launcher:${launcher_action_name}", see [LauncherAction]
|
|
||||||
* - "${package_name}", see [AppAction]
|
|
||||||
* - "${package_name}:${activity_name}", see [AppAction]
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @param user a user id, ignored if the action is a [LauncherAction].
|
|
||||||
* @param context used to complete [AppInfo] if possible
|
|
||||||
*/
|
|
||||||
private fun fromId(id: String, user: Int?, context: Context? = null): Action? {
|
|
||||||
if (id.isEmpty()) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (LauncherAction.isOtherAction(id)) {
|
|
||||||
return LauncherAction.byId(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
val values = id.split(";")
|
|
||||||
|
|
||||||
var info = AppInfo(values[0], values.getOrNull(1), user ?: INVALID_USER)
|
|
||||||
|
|
||||||
// try to complete an incomplete AppInfo if a context is provided
|
|
||||||
if (context != null && (info.user == INVALID_USER || info.activityName == null)) {
|
|
||||||
info = DetailedAppInfo.fromAppInfo(info, context)?.app?:info
|
|
||||||
}
|
|
||||||
|
|
||||||
return AppAction(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forGesture(gesture: Gesture): Action? {
|
fun forGesture(gesture: Gesture): Action? {
|
||||||
val id = gesture.id
|
val id = gesture.id
|
||||||
|
|
||||||
val preferences = LauncherPreferences.getSharedPreferences()
|
val preferences = LauncherPreferences.getSharedPreferences()
|
||||||
val actionId = preferences.getString("$id.app", "")!!
|
val json = preferences.getString(id, "null")!!
|
||||||
var u: Int? = preferences.getInt("$id.user", INVALID_USER)
|
return Json.decodeFromString(json)
|
||||||
u = if (u == INVALID_USER) null else u
|
|
||||||
|
|
||||||
return fromId(actionId, u)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetToDefaultActions(context: Context) {
|
fun resetToDefaultActions(context: Context) {
|
||||||
|
@ -72,11 +47,11 @@ interface Action {
|
||||||
context.resources
|
context.resources
|
||||||
.getStringArray(gesture.defaultsResource)
|
.getStringArray(gesture.defaultsResource)
|
||||||
.filterNot { boundActions.contains(it) }
|
.filterNot { boundActions.contains(it) }
|
||||||
.map { Pair(it, fromId(it, null, context)) }
|
.map { Pair(it, Json.decodeFromString<Action>(it)) }
|
||||||
.firstOrNull { it.second?.isAvailable(context) ?: false }
|
.firstOrNull { it.second.isAvailable(context) }
|
||||||
?.apply {
|
?.apply {
|
||||||
boundActions.add(first)
|
boundActions.add(first)
|
||||||
second?.bindToGesture(editor, gesture.id)
|
second.bindToGesture(editor, gesture.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
@ -94,8 +69,7 @@ interface Action {
|
||||||
|
|
||||||
fun clearActionForGesture(gesture: Gesture) {
|
fun clearActionForGesture(gesture: Gesture) {
|
||||||
LauncherPreferences.getSharedPreferences().edit()
|
LauncherPreferences.getSharedPreferences().edit()
|
||||||
.putString(gesture.id + ".app", "")
|
.remove(gesture.id)
|
||||||
.putInt(gesture.id + ".user", INVALID_USER)
|
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +93,8 @@ interface Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromIntent(data: Intent): Action? {
|
fun fromIntent(data: Intent): Action? {
|
||||||
val value = data.getStringExtra("action_id") ?: return null
|
val json = data.getStringExtra("action") ?: return null
|
||||||
val user = data.getIntExtra("user", INVALID_USER)
|
return Json.decodeFromString(json)
|
||||||
return fromId(value, user)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@ import android.app.AlertDialog
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.content.pm.LauncherApps
|
import android.content.pm.LauncherApps
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
@ -14,16 +13,20 @@ 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.apps.DetailedAppInfo
|
import de.jrpie.android.launcher.apps.DetailedAppInfo
|
||||||
import de.jrpie.android.launcher.ui.list.apps.openSettings
|
import de.jrpie.android.launcher.ui.list.apps.openSettings
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
class AppAction(val appInfo: AppInfo) : Action {
|
@Serializable
|
||||||
|
@SerialName("action:app")
|
||||||
|
class AppAction(val app: AppInfo) : Action {
|
||||||
|
|
||||||
override fun invoke(context: Context, rect: Rect?): Boolean {
|
override fun invoke(context: Context, rect: Rect?): Boolean {
|
||||||
val packageName = appInfo.packageName.toString()
|
val packageName = app.packageName
|
||||||
if (appInfo.user != INVALID_USER) {
|
if (app.user != INVALID_USER) {
|
||||||
val launcherApps =
|
val launcherApps =
|
||||||
context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
|
context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
|
||||||
appInfo.getLauncherActivityInfo(context)?.let { app ->
|
app.getLauncherActivityInfo(context)?.let { app ->
|
||||||
Log.i("Launcher", "Starting $appInfo")
|
Log.i("Launcher", "Starting ${this.app}")
|
||||||
launcherApps.startMainActivity(app.componentName, app.user, rect, null)
|
launcherApps.startMainActivity(app.componentName, app.user, rect, null)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -44,7 +47,7 @@ class AppAction(val appInfo: AppInfo) : Action {
|
||||||
.setTitle(context.getString(R.string.alert_cant_open_title))
|
.setTitle(context.getString(R.string.alert_cant_open_title))
|
||||||
.setMessage(context.getString(R.string.alert_cant_open_message))
|
.setMessage(context.getString(R.string.alert_cant_open_message))
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
appInfo.openSettings(context)
|
app.openSettings(context)
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setIcon(android.R.drawable.ic_dialog_info)
|
.setIcon(android.R.drawable.ic_dialog_info)
|
||||||
|
@ -55,33 +58,15 @@ class AppAction(val appInfo: AppInfo) : Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun label(context: Context): String {
|
override fun label(context: Context): String {
|
||||||
return DetailedAppInfo.fromAppInfo(appInfo, context)?.getCustomLabel(context).toString()
|
return DetailedAppInfo.fromAppInfo(app, context)?.getCustomLabel(context).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getIcon(context: Context): Drawable? {
|
override fun getIcon(context: Context): Drawable? {
|
||||||
return DetailedAppInfo.fromAppInfo(appInfo, context)?.icon
|
return DetailedAppInfo.fromAppInfo(app, context)?.icon
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isAvailable(context: Context): Boolean {
|
override fun isAvailable(context: Context): Boolean {
|
||||||
// check if app is installed
|
// check if app is installed
|
||||||
return DetailedAppInfo.fromAppInfo(appInfo, context) != null
|
return DetailedAppInfo.fromAppInfo(app, context) != null
|
||||||
}
|
|
||||||
|
|
||||||
override fun bindToGesture(editor: SharedPreferences.Editor, id: String) {
|
|
||||||
val u = appInfo.user
|
|
||||||
|
|
||||||
// TODO: replace this by AppInfo#serialize (breaking change to SharedPreferences!)
|
|
||||||
var app = appInfo.packageName.toString()
|
|
||||||
if (appInfo.activityName != null) {
|
|
||||||
app += ";${appInfo.activityName}"
|
|
||||||
}
|
|
||||||
editor
|
|
||||||
.putString("$id.app", app)
|
|
||||||
.putInt("$id.user", u)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToIntent(intent: Intent) {
|
|
||||||
intent.putExtra("action_id", "${appInfo.packageName};${appInfo.activityName}")
|
|
||||||
intent.putExtra("user", appInfo.user)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@ package de.jrpie.android.launcher.actions
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences.Editor
|
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
@ -13,11 +12,20 @@ import android.widget.Toast
|
||||||
import de.jrpie.android.launcher.Application
|
import de.jrpie.android.launcher.Application
|
||||||
import de.jrpie.android.launcher.R
|
import de.jrpie.android.launcher.R
|
||||||
import de.jrpie.android.launcher.apps.AppFilter
|
import de.jrpie.android.launcher.apps.AppFilter
|
||||||
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.ui.list.ListActivity
|
import de.jrpie.android.launcher.ui.list.ListActivity
|
||||||
import de.jrpie.android.launcher.ui.settings.SettingsActivity
|
import de.jrpie.android.launcher.ui.settings.SettingsActivity
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.SerializationException
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
@Serializable(with = LauncherActionSerializer::class)
|
||||||
|
@SerialName("action:launcher")
|
||||||
enum class LauncherAction(
|
enum class LauncherAction(
|
||||||
val id: String,
|
val id: String,
|
||||||
val label: Int,
|
val label: Int,
|
||||||
|
@ -25,68 +33,68 @@ enum class LauncherAction(
|
||||||
val launch: (Context) -> Unit
|
val launch: (Context) -> Unit
|
||||||
) : Action {
|
) : Action {
|
||||||
SETTINGS(
|
SETTINGS(
|
||||||
"launcher:settings",
|
"settings",
|
||||||
R.string.list_other_settings,
|
R.string.list_other_settings,
|
||||||
R.drawable.baseline_settings_24,
|
R.drawable.baseline_settings_24,
|
||||||
::openSettings
|
::openSettings
|
||||||
),
|
),
|
||||||
CHOOSE(
|
CHOOSE(
|
||||||
"launcher:choose",
|
"choose",
|
||||||
R.string.list_other_list,
|
R.string.list_other_list,
|
||||||
R.drawable.baseline_menu_24,
|
R.drawable.baseline_menu_24,
|
||||||
::openAppsList
|
::openAppsList
|
||||||
),
|
),
|
||||||
CHOOSE_FROM_FAVORITES(
|
CHOOSE_FROM_FAVORITES(
|
||||||
"launcher:chooseFromFavorites",
|
"choose_from_favorites",
|
||||||
R.string.list_other_list_favorites,
|
R.string.list_other_list_favorites,
|
||||||
R.drawable.baseline_favorite_24,
|
R.drawable.baseline_favorite_24,
|
||||||
{ context -> openAppsList(context, true) }
|
{ context -> openAppsList(context, true) }
|
||||||
),
|
),
|
||||||
VOLUME_UP(
|
VOLUME_UP(
|
||||||
"launcher:volumeUp",
|
"volume_up",
|
||||||
R.string.list_other_volume_up,
|
R.string.list_other_volume_up,
|
||||||
R.drawable.baseline_volume_up_24, ::audioVolumeUp
|
R.drawable.baseline_volume_up_24, ::audioVolumeUp
|
||||||
),
|
),
|
||||||
VOLUME_DOWN(
|
VOLUME_DOWN(
|
||||||
"launcher:volumeDown",
|
"volume_down",
|
||||||
R.string.list_other_volume_down,
|
R.string.list_other_volume_down,
|
||||||
R.drawable.baseline_volume_down_24, ::audioVolumeDown
|
R.drawable.baseline_volume_down_24, ::audioVolumeDown
|
||||||
),
|
),
|
||||||
TRACK_NEXT(
|
TRACK_NEXT(
|
||||||
"launcher:nextTrack",
|
"next_track",
|
||||||
R.string.list_other_track_next,
|
R.string.list_other_track_next,
|
||||||
R.drawable.baseline_skip_next_24, ::audioNextTrack
|
R.drawable.baseline_skip_next_24, ::audioNextTrack
|
||||||
),
|
),
|
||||||
TRACK_PREV(
|
TRACK_PREV(
|
||||||
"launcher:previousTrack",
|
"previous_track",
|
||||||
R.string.list_other_track_previous,
|
R.string.list_other_track_previous,
|
||||||
R.drawable.baseline_skip_previous_24, ::audioPreviousTrack
|
R.drawable.baseline_skip_previous_24, ::audioPreviousTrack
|
||||||
),
|
),
|
||||||
EXPAND_NOTIFICATIONS_PANEL(
|
EXPAND_NOTIFICATIONS_PANEL(
|
||||||
"launcher:expandNotificationsPanel",
|
"expand_notifications_panel",
|
||||||
R.string.list_other_expand_notifications_panel,
|
R.string.list_other_expand_notifications_panel,
|
||||||
R.drawable.baseline_notifications_24,
|
R.drawable.baseline_notifications_24,
|
||||||
::expandNotificationsPanel
|
::expandNotificationsPanel
|
||||||
),
|
),
|
||||||
EXPAND_SETTINGS_PANEL(
|
EXPAND_SETTINGS_PANEL(
|
||||||
"launcher:expandSettingsPanel",
|
"expand_settings_panel",
|
||||||
R.string.list_other_expand_settings_panel,
|
R.string.list_other_expand_settings_panel,
|
||||||
R.drawable.baseline_settings_applications_24,
|
R.drawable.baseline_settings_applications_24,
|
||||||
::expandSettingsPanel
|
::expandSettingsPanel
|
||||||
),
|
),
|
||||||
LOCK_SCREEN(
|
LOCK_SCREEN(
|
||||||
"launcher:lockScreen",
|
"lock_screen",
|
||||||
R.string.list_other_lock_screen,
|
R.string.list_other_lock_screen,
|
||||||
R.drawable.baseline_lock_24px,
|
R.drawable.baseline_lock_24px,
|
||||||
{ c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) }
|
{ c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) }
|
||||||
),
|
),
|
||||||
TORCH(
|
TORCH(
|
||||||
"launcher:toggleTorch",
|
"toggle_torch",
|
||||||
R.string.list_other_torch,
|
R.string.list_other_torch,
|
||||||
R.drawable.baseline_flashlight_on_24,
|
R.drawable.baseline_flashlight_on_24,
|
||||||
::toggleTorch
|
::toggleTorch
|
||||||
),
|
),
|
||||||
NOP("launcher:nop", R.string.list_other_nop, R.drawable.baseline_not_interested_24, {});
|
NOP("nop", R.string.list_other_nop, R.drawable.baseline_not_interested_24, {});
|
||||||
|
|
||||||
override fun invoke(context: Context, rect: Rect?): Boolean {
|
override fun invoke(context: Context, rect: Rect?): Boolean {
|
||||||
launch(context)
|
launch(context)
|
||||||
|
@ -101,16 +109,6 @@ enum class LauncherAction(
|
||||||
return context.getDrawable(icon)
|
return context.getDrawable(icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindToGesture(editor: Editor, id: String) {
|
|
||||||
editor
|
|
||||||
.putString("$id.app", this.id)
|
|
||||||
.putInt("$id.user", INVALID_USER)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToIntent(intent: Intent) {
|
|
||||||
intent.putExtra("action_id", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isAvailable(context: Context): Boolean {
|
override fun isAvailable(context: Context): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -119,10 +117,6 @@ enum class LauncherAction(
|
||||||
fun byId(id: String): LauncherAction? {
|
fun byId(id: String): LauncherAction? {
|
||||||
return entries.singleOrNull { it.id == id }
|
return entries.singleOrNull { it.id == id }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isOtherAction(id: String): Boolean {
|
|
||||||
return id.startsWith("launcher")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,3 +247,31 @@ fun openAppsList(context: Context, favorite: Boolean = false, hidden: Boolean =
|
||||||
|
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LauncherAction can't be serialized directly, since it needs a type annotation.
|
||||||
|
* Thus this hack is needed.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
private class LauncherActionWrapper(val id: String)
|
||||||
|
|
||||||
|
private class LauncherActionSerializer() : KSerializer<LauncherAction> {
|
||||||
|
override val descriptor: SerialDescriptor = buildClassSerialDescriptor(
|
||||||
|
"action:launcher",
|
||||||
|
) {
|
||||||
|
element("id", LauncherActionWrapper.serializer().descriptor)
|
||||||
|
}
|
||||||
|
override fun deserialize(decoder: Decoder): LauncherAction {
|
||||||
|
val wrapper = decoder.decodeSerializableValue(LauncherActionWrapper.serializer())
|
||||||
|
return LauncherAction.byId(wrapper.id) ?: throw SerializationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: LauncherAction) {
|
||||||
|
encoder.encodeSerializableValue(
|
||||||
|
LauncherActionWrapper.serializer(),
|
||||||
|
LauncherActionWrapper(value.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ class AppFilter(
|
||||||
if (LauncherPreferences.apps().hideBoundApps()) {
|
if (LauncherPreferences.apps().hideBoundApps()) {
|
||||||
val boundApps = Gesture.entries
|
val boundApps = Gesture.entries
|
||||||
.filter(Gesture::isEnabled)
|
.filter(Gesture::isEnabled)
|
||||||
.mapNotNull { g -> (Action.forGesture(g) as? AppAction)?.appInfo }
|
.mapNotNull { g -> (Action.forGesture(g) as? AppAction)?.app }
|
||||||
.toSet()
|
.toSet()
|
||||||
apps = apps.filterNot { info -> boundApps.contains(info.app) }
|
apps = apps.filterNot { info -> boundApps.contains(info.app) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,19 @@ import android.content.Context
|
||||||
import android.content.pm.LauncherActivityInfo
|
import android.content.pm.LauncherActivityInfo
|
||||||
import android.content.pm.LauncherApps
|
import android.content.pm.LauncherApps
|
||||||
import de.jrpie.android.launcher.getUserFromId
|
import de.jrpie.android.launcher.getUserFromId
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an app installed on the users device.
|
* Represents an app installed on the users device.
|
||||||
* Contains the minimal amount of data required to identify the app.
|
* Contains the minimal amount of data required to identify the app.
|
||||||
*/
|
*/
|
||||||
class AppInfo(val packageName: CharSequence, val activityName: CharSequence?, val user: Int = INVALID_USER) {
|
@Serializable
|
||||||
|
class AppInfo(val packageName: String, val activityName: String?, val user: Int = INVALID_USER) {
|
||||||
// TODO: make activityName non nullable (breaking change to SharedPreferences!)
|
|
||||||
|
|
||||||
fun serialize(): String {
|
fun serialize(): String {
|
||||||
val u = user
|
return Json.encodeToString(this)
|
||||||
var ret = "$packageName;$u"
|
|
||||||
activityName?.let { ret += ";$activityName" }
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
|
@ -39,7 +37,7 @@ class AppInfo(val packageName: CharSequence, val activityName: CharSequence?, va
|
||||||
): LauncherActivityInfo? {
|
): LauncherActivityInfo? {
|
||||||
val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
|
val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
|
||||||
val userHandle = getUserFromId(user, context)
|
val userHandle = getUserFromId(user, context)
|
||||||
val activityList = launcherApps.getActivityList(packageName.toString(), userHandle)
|
val activityList = launcherApps.getActivityList(packageName, userHandle)
|
||||||
return activityList.firstOrNull { app -> app.name == activityName }
|
return activityList.firstOrNull { app -> app.name == activityName }
|
||||||
?: activityList.firstOrNull()
|
?: activityList.firstOrNull()
|
||||||
}
|
}
|
||||||
|
@ -53,11 +51,7 @@ class AppInfo(val packageName: CharSequence, val activityName: CharSequence?, va
|
||||||
const val INVALID_USER = -1
|
const val INVALID_USER = -1
|
||||||
|
|
||||||
fun deserialize(serialized: String): AppInfo {
|
fun deserialize(serialized: String): AppInfo {
|
||||||
val values = serialized.split(";")
|
return Json.decodeFromString(serialized)
|
||||||
val packageName = values[0]
|
|
||||||
val user = Integer.valueOf(values[1])
|
|
||||||
val activityName = values.getOrNull(2)
|
|
||||||
return AppInfo(packageName, activityName, user)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -107,6 +107,7 @@ public final class LauncherPreferences$Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO migrate to version 2
|
||||||
public static class MapAppInfoStringSerializer implements PreferenceSerializer<HashMap<AppInfo, String>, Set<String>> {
|
public static class MapAppInfoStringSerializer implements PreferenceSerializer<HashMap<AppInfo, String>, Set<String>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,57 +1,24 @@
|
||||||
package de.jrpie.android.launcher.preferences
|
package de.jrpie.android.launcher.preferences
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import de.jrpie.android.launcher.BuildConfig
|
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.theme.Background
|
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersionUnknown
|
||||||
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1
|
||||||
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.
|
||||||
* Increase when breaking changes are introduced and write an appropriate case in
|
* Increase when breaking changes are introduced and write an appropriate case in
|
||||||
* `migratePreferencesToNewVersion`
|
* `migratePreferencesToNewVersion`
|
||||||
*/
|
*/
|
||||||
const val PREFERENCE_VERSION = 1
|
const val PREFERENCE_VERSION = 2
|
||||||
const val UNKNOWN_PREFERENCE_VERSION = -1
|
const val UNKNOWN_PREFERENCE_VERSION = -1
|
||||||
private const val TAG = "Launcher - Preferences"
|
private const val TAG = "Launcher - Preferences"
|
||||||
|
|
||||||
|
|
||||||
private fun migrateStringPreference(
|
|
||||||
oldPrefs: SharedPreferences,
|
|
||||||
newPreferences: SharedPreferences.Editor,
|
|
||||||
oldKey: String,
|
|
||||||
newKey: String,
|
|
||||||
default: String
|
|
||||||
) {
|
|
||||||
val s = oldPrefs.getString(oldKey, default)
|
|
||||||
newPreferences.putString(newKey, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateIntPreference(
|
|
||||||
oldPrefs: SharedPreferences,
|
|
||||||
newPreferences: SharedPreferences.Editor,
|
|
||||||
oldKey: String,
|
|
||||||
newKey: String,
|
|
||||||
default: Int
|
|
||||||
) {
|
|
||||||
val s = oldPrefs.getInt(oldKey, default)
|
|
||||||
newPreferences.putInt(newKey, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun migrateBooleanPreference(
|
|
||||||
oldPrefs: SharedPreferences,
|
|
||||||
newPreferences: SharedPreferences.Editor,
|
|
||||||
oldKey: String,
|
|
||||||
newKey: String,
|
|
||||||
default: Boolean
|
|
||||||
) {
|
|
||||||
val s = oldPrefs.getBoolean(oldKey, default)
|
|
||||||
newPreferences.putBoolean(newKey, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun migratePreferencesToNewVersion(context: Context) {
|
fun migratePreferencesToNewVersion(context: Context) {
|
||||||
when (LauncherPreferences.internal().versionCode()) {
|
when (LauncherPreferences.internal().versionCode()) {
|
||||||
|
@ -60,356 +27,23 @@ fun migratePreferencesToNewVersion(context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
UNKNOWN_PREFERENCE_VERSION -> { /* still using the old preferences file */
|
UNKNOWN_PREFERENCE_VERSION -> { /* still using the old preferences file */
|
||||||
Log.i(
|
migratePreferencesFromVersionUnknown(context)
|
||||||
TAG,
|
|
||||||
"Unknown preference version, trying to restore preferences from old version."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
val oldPrefs = context.getSharedPreferences(
|
|
||||||
"V3RYR4ND0MK3YCR4P",
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
if (!oldPrefs.contains("startedBefore")) {
|
|
||||||
Log.i(TAG, "No old preferences found.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val newPrefs = LauncherPreferences.getSharedPreferences().edit()
|
|
||||||
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"startedBefore",
|
|
||||||
"internal.started_before",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_volumeUpApp",
|
|
||||||
"action.volume_up.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_volumeUpApp_user",
|
|
||||||
"action.volume_up.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_volumeDownApp",
|
|
||||||
"action.volume_down.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_volumeDownApp_user",
|
|
||||||
"action.volume_down.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_timeApp", "action.time.app", "")
|
|
||||||
migrateIntPreference(oldPrefs, newPrefs, "action_timeApp_user", "action.time.user", -1)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_dateApp", "action.date.app", "")
|
|
||||||
migrateIntPreference(oldPrefs, newPrefs, "action_dateApp_user", "action.date.user", -1)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_longClickApp",
|
|
||||||
"action.long_click.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_longClickApp_user",
|
|
||||||
"action.long_click.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleClickApp",
|
|
||||||
"action.double_click.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleClickApp_user",
|
|
||||||
"action.double_click.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_upApp", "action.up.app", "")
|
|
||||||
migrateIntPreference(oldPrefs, newPrefs, "action_upApp_user", "action.up.user", -1)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_up_leftApp",
|
|
||||||
"action.up_left.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_up_leftApp_user",
|
|
||||||
"action.up_left.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_up_rightApp",
|
|
||||||
"action.up_right.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_up_rightApp_user",
|
|
||||||
"action.up_right.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleUpApp",
|
|
||||||
"action.double_up.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleUpApp_user",
|
|
||||||
"action.double_up.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_downApp", "action.down.app", "")
|
|
||||||
migrateIntPreference(oldPrefs, newPrefs, "action_downApp_user", "action.down.user", -1)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_down_leftApp",
|
|
||||||
"action.down_left.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_down_leftApp_user",
|
|
||||||
"action.down_left.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_down_rightApp",
|
|
||||||
"action.down_right.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_down_rightApp_user",
|
|
||||||
"action.down_right.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleDownApp",
|
|
||||||
"action.double_down.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleDownApp_user",
|
|
||||||
"action.double_down.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_leftApp", "action.left.app", "")
|
|
||||||
migrateIntPreference(oldPrefs, newPrefs, "action_leftApp_user", "action.left.user", -1)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_left_topApp",
|
|
||||||
"action.left_top.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_left_topApp_user",
|
|
||||||
"action.left_top.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_left_bottomApp",
|
|
||||||
"action.left_bottom.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_left_bottomApp_user",
|
|
||||||
"action.left_bottom.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleLeftApp",
|
|
||||||
"action.double_left.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleLeftApp_user",
|
|
||||||
"action.double_left.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(oldPrefs, newPrefs, "action_rightApp", "action.right.app", "")
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_rightApp_user",
|
|
||||||
"action.right.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_right_topApp",
|
|
||||||
"action.right_top.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_right_topApp_user",
|
|
||||||
"action.right_top.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_right_bottomApp",
|
|
||||||
"action.right_bottom.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_right_bottomApp_user",
|
|
||||||
"action.right_bottom.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateStringPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleRightApp",
|
|
||||||
"action.double_right.app",
|
|
||||||
""
|
|
||||||
)
|
|
||||||
migrateIntPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"action_doubleRightApp_user",
|
|
||||||
"action.double_right.user",
|
|
||||||
-1
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(oldPrefs, newPrefs, "timeVisible", "clock.time_visible", true)
|
|
||||||
migrateBooleanPreference(oldPrefs, newPrefs, "dateVisible", "clock.date_visible", true)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"dateLocalized",
|
|
||||||
"clock.date_localized",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"dateTimeFlip",
|
|
||||||
"clock.date_time_flip",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"disableTimeout",
|
|
||||||
"display.disable_timeout",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"useFullScreen",
|
|
||||||
"display.use_full_screen",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"enableDoubleActions",
|
|
||||||
"enabled_gestures.double_actions",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"enableEdgeActions",
|
|
||||||
"enabled_gestures.edge_actions",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"searchAutoLaunch",
|
|
||||||
"functionality.search_auto_launch",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
migrateBooleanPreference(
|
|
||||||
oldPrefs,
|
|
||||||
newPrefs,
|
|
||||||
"searchAutoKeyboard",
|
|
||||||
"functionality.search_auto_keyboard",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
newPrefs.apply()
|
|
||||||
|
|
||||||
when (oldPrefs.getString("theme", "finn")) {
|
|
||||||
"finn" -> {
|
|
||||||
LauncherPreferences.theme().colorTheme(ColorTheme.DEFAULT)
|
|
||||||
LauncherPreferences.theme().monochromeIcons(false)
|
|
||||||
LauncherPreferences.theme().background(Background.DIM)
|
|
||||||
}
|
|
||||||
|
|
||||||
"dark" -> {
|
|
||||||
LauncherPreferences.theme().colorTheme(ColorTheme.DARK)
|
|
||||||
LauncherPreferences.theme().monochromeIcons(true)
|
|
||||||
LauncherPreferences.theme().background(Background.DIM)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LauncherPreferences.internal().versionCode(PREFERENCE_VERSION)
|
|
||||||
Log.i(TAG, "migration of preferences complete.")
|
Log.i(TAG, "migration of preferences complete.")
|
||||||
|
}
|
||||||
// show the new tutorial
|
1 -> {
|
||||||
// context.startActivity(Intent(context, TutorialActivity::class.java))
|
migratePreferencesFromVersion1()
|
||||||
|
Log.i(TAG, "migration of preferences complete.")
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"Shared preferences were written by a newer version of the app (${
|
||||||
|
LauncherPreferences.internal().versionCode()
|
||||||
|
})!"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package de.jrpie.android.launcher.preferences.legacy
|
||||||
|
|
||||||
|
import de.jrpie.android.launcher.actions.Action
|
||||||
|
import de.jrpie.android.launcher.actions.AppAction
|
||||||
|
import de.jrpie.android.launcher.actions.Gesture
|
||||||
|
import de.jrpie.android.launcher.actions.LauncherAction
|
||||||
|
import de.jrpie.android.launcher.apps.AppInfo
|
||||||
|
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
|
||||||
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
val oldLauncherActionIds: Map<String, LauncherAction> =
|
||||||
|
mapOf(
|
||||||
|
Pair("launcher:settings", LauncherAction.SETTINGS),
|
||||||
|
Pair("launcher:choose", LauncherAction.CHOOSE),
|
||||||
|
Pair("launcher:chooseFromFavorites", LauncherAction.CHOOSE_FROM_FAVORITES),
|
||||||
|
Pair("launcher:volumeUp", LauncherAction.VOLUME_UP),
|
||||||
|
Pair("launcher:volumeDown", LauncherAction.VOLUME_DOWN),
|
||||||
|
Pair("launcher:nextTrack", LauncherAction.TRACK_NEXT),
|
||||||
|
Pair("launcher:previousTrack", LauncherAction.TRACK_PREV),
|
||||||
|
Pair("launcher:expandNotificationsPanel", LauncherAction.EXPAND_NOTIFICATIONS_PANEL),
|
||||||
|
Pair("launcher:expandSettingsPanel", LauncherAction.EXPAND_SETTINGS_PANEL),
|
||||||
|
Pair("launcher:lockScreen", LauncherAction.LOCK_SCREEN),
|
||||||
|
Pair("launcher:toggleTorch", LauncherAction.TORCH),
|
||||||
|
Pair("launcher:nop", LauncherAction.NOP),
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun AppInfo.Companion.legacyDeserialize(serialized: String): AppInfo {
|
||||||
|
val values = serialized.split(";")
|
||||||
|
val packageName = values[0]
|
||||||
|
val user = Integer.valueOf(values[1])
|
||||||
|
val activityName = values.getOrNull(2) ?: "" // TODO
|
||||||
|
return AppInfo(packageName, activityName, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an action for a specific id.
|
||||||
|
* An id is of the form:
|
||||||
|
* - "launcher:${launcher_action_name}", see [LauncherAction]
|
||||||
|
* - "${package_name}", see [AppAction]
|
||||||
|
* - "${package_name}:${activity_name}", see [AppAction]
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @param user a user id, ignored if the action is a [LauncherAction].
|
||||||
|
*/
|
||||||
|
private fun Action.Companion.fromId(id: String, user: Int?): Action? {
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
oldLauncherActionIds[id]?.let { return it }
|
||||||
|
|
||||||
|
val values = id.split(";")
|
||||||
|
|
||||||
|
return AppAction(
|
||||||
|
AppInfo(
|
||||||
|
values[0], values.getOrNull(1) ?: "", user ?: INVALID_USER
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Action.Companion.legacyFromPreference(id: String): Action? {
|
||||||
|
val preferences = LauncherPreferences.getSharedPreferences()
|
||||||
|
val actionId = preferences.getString("$id.app", "")!!
|
||||||
|
var u: Int? = preferences.getInt(
|
||||||
|
"$id.user",
|
||||||
|
AppInfo.INVALID_USER
|
||||||
|
)
|
||||||
|
u = if (u == AppInfo.INVALID_USER) null else u
|
||||||
|
|
||||||
|
return Action.fromId(actionId, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateAppInfoSet(key: String) {
|
||||||
|
(LauncherPreferences.getSharedPreferences().getStringSet(key, setOf()) ?: return)
|
||||||
|
.map(AppInfo.Companion::legacyDeserialize)
|
||||||
|
.map(AppInfo::serialize)
|
||||||
|
.toSet()
|
||||||
|
.let { LauncherPreferences.getSharedPreferences().edit().putStringSet(key, it).apply() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateAction(key: String) {
|
||||||
|
Action.legacyFromPreference(key)?.let { action ->
|
||||||
|
LauncherPreferences.getSharedPreferences().edit()
|
||||||
|
.putString(key, Json.encodeToString(action)).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun migratePreferencesFromVersion1() {
|
||||||
|
Gesture.entries.forEach { g -> migrateAction(g.id) }
|
||||||
|
migrateAppInfoSet(LauncherPreferences.apps().keys().hidden())
|
||||||
|
migrateAppInfoSet(LauncherPreferences.apps().keys().favorites())
|
||||||
|
}
|
|
@ -0,0 +1,390 @@
|
||||||
|
package de.jrpie.android.launcher.preferences.legacy
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Log
|
||||||
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
import de.jrpie.android.launcher.preferences.theme.Background
|
||||||
|
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
||||||
|
|
||||||
|
private fun migrateStringPreference(
|
||||||
|
oldPrefs: SharedPreferences,
|
||||||
|
newPreferences: SharedPreferences.Editor,
|
||||||
|
oldKey: String,
|
||||||
|
newKey: String,
|
||||||
|
default: String
|
||||||
|
) {
|
||||||
|
val s = oldPrefs.getString(oldKey, default)
|
||||||
|
newPreferences.putString(newKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateIntPreference(
|
||||||
|
oldPrefs: SharedPreferences,
|
||||||
|
newPreferences: SharedPreferences.Editor,
|
||||||
|
oldKey: String,
|
||||||
|
newKey: String,
|
||||||
|
default: Int
|
||||||
|
) {
|
||||||
|
val s = oldPrefs.getInt(oldKey, default)
|
||||||
|
newPreferences.putInt(newKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateBooleanPreference(
|
||||||
|
oldPrefs: SharedPreferences,
|
||||||
|
newPreferences: SharedPreferences.Editor,
|
||||||
|
oldKey: String,
|
||||||
|
newKey: String,
|
||||||
|
default: Boolean
|
||||||
|
) {
|
||||||
|
val s = oldPrefs.getBoolean(oldKey, default)
|
||||||
|
newPreferences.putBoolean(newKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val TAG = "Preferences ? -> 1"
|
||||||
|
|
||||||
|
fun migratePreferencesFromVersionUnknown(context: Context) {
|
||||||
|
Log.i(
|
||||||
|
TAG,
|
||||||
|
"Unknown preference version, trying to restore preferences from old version."
|
||||||
|
)
|
||||||
|
|
||||||
|
val oldPrefs = context.getSharedPreferences(
|
||||||
|
"V3RYR4ND0MK3YCR4P",
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
if (!oldPrefs.contains("startedBefore")) {
|
||||||
|
Log.i(TAG, "No old preferences found. Probably this is a fresh installation.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val newPrefs = LauncherPreferences.getSharedPreferences().edit()
|
||||||
|
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"startedBefore",
|
||||||
|
"internal.started_before",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_volumeUpApp",
|
||||||
|
"action.volume_up.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_volumeUpApp_user",
|
||||||
|
"action.volume_up.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_volumeDownApp",
|
||||||
|
"action.volume_down.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_volumeDownApp_user",
|
||||||
|
"action.volume_down.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_timeApp", "action.time.app", "")
|
||||||
|
migrateIntPreference(oldPrefs, newPrefs, "action_timeApp_user", "action.time.user", -1)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_dateApp", "action.date.app", "")
|
||||||
|
migrateIntPreference(oldPrefs, newPrefs, "action_dateApp_user", "action.date.user", -1)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_longClickApp",
|
||||||
|
"action.long_click.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_longClickApp_user",
|
||||||
|
"action.long_click.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleClickApp",
|
||||||
|
"action.double_click.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleClickApp_user",
|
||||||
|
"action.double_click.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_upApp", "action.up.app", "")
|
||||||
|
migrateIntPreference(oldPrefs, newPrefs, "action_upApp_user", "action.up.user", -1)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_up_leftApp",
|
||||||
|
"action.up_left.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_up_leftApp_user",
|
||||||
|
"action.up_left.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_up_rightApp",
|
||||||
|
"action.up_right.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_up_rightApp_user",
|
||||||
|
"action.up_right.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleUpApp",
|
||||||
|
"action.double_up.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleUpApp_user",
|
||||||
|
"action.double_up.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_downApp", "action.down.app", "")
|
||||||
|
migrateIntPreference(oldPrefs, newPrefs, "action_downApp_user", "action.down.user", -1)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_down_leftApp",
|
||||||
|
"action.down_left.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_down_leftApp_user",
|
||||||
|
"action.down_left.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_down_rightApp",
|
||||||
|
"action.down_right.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_down_rightApp_user",
|
||||||
|
"action.down_right.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleDownApp",
|
||||||
|
"action.double_down.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleDownApp_user",
|
||||||
|
"action.double_down.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_leftApp", "action.left.app", "")
|
||||||
|
migrateIntPreference(oldPrefs, newPrefs, "action_leftApp_user", "action.left.user", -1)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_left_topApp",
|
||||||
|
"action.left_top.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_left_topApp_user",
|
||||||
|
"action.left_top.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_left_bottomApp",
|
||||||
|
"action.left_bottom.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_left_bottomApp_user",
|
||||||
|
"action.left_bottom.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleLeftApp",
|
||||||
|
"action.double_left.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleLeftApp_user",
|
||||||
|
"action.double_left.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(oldPrefs, newPrefs, "action_rightApp", "action.right.app", "")
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_rightApp_user",
|
||||||
|
"action.right.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_right_topApp",
|
||||||
|
"action.right_top.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_right_topApp_user",
|
||||||
|
"action.right_top.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_right_bottomApp",
|
||||||
|
"action.right_bottom.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_right_bottomApp_user",
|
||||||
|
"action.right_bottom.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateStringPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleRightApp",
|
||||||
|
"action.double_right.app",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
migrateIntPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"action_doubleRightApp_user",
|
||||||
|
"action.double_right.user",
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(oldPrefs, newPrefs, "timeVisible", "clock.time_visible", true)
|
||||||
|
migrateBooleanPreference(oldPrefs, newPrefs, "dateVisible", "clock.date_visible", true)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"dateLocalized",
|
||||||
|
"clock.date_localized",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"dateTimeFlip",
|
||||||
|
"clock.date_time_flip",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"disableTimeout",
|
||||||
|
"display.disable_timeout",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"useFullScreen",
|
||||||
|
"display.use_full_screen",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"enableDoubleActions",
|
||||||
|
"enabled_gestures.double_actions",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"enableEdgeActions",
|
||||||
|
"enabled_gestures.edge_actions",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"searchAutoLaunch",
|
||||||
|
"functionality.search_auto_launch",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
migrateBooleanPreference(
|
||||||
|
oldPrefs,
|
||||||
|
newPrefs,
|
||||||
|
"searchAutoKeyboard",
|
||||||
|
"functionality.search_auto_keyboard",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
newPrefs.apply()
|
||||||
|
|
||||||
|
when (oldPrefs.getString("theme", "finn")) {
|
||||||
|
"finn" -> {
|
||||||
|
LauncherPreferences.theme().colorTheme(ColorTheme.DEFAULT)
|
||||||
|
LauncherPreferences.theme().monochromeIcons(false)
|
||||||
|
LauncherPreferences.theme().background(Background.DIM)
|
||||||
|
}
|
||||||
|
|
||||||
|
"dark" -> {
|
||||||
|
LauncherPreferences.theme().colorTheme(ColorTheme.DARK)
|
||||||
|
LauncherPreferences.theme().monochromeIcons(true)
|
||||||
|
LauncherPreferences.theme().background(Background.DIM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LauncherPreferences.internal().versionCode(1)
|
||||||
|
Log.i(TAG, "migrated preferences to version 1.")
|
||||||
|
|
||||||
|
migratePreferencesFromVersion1()
|
||||||
|
}
|
|
@ -5,145 +5,145 @@
|
||||||
|
|
||||||
<!-- Swipe up - Apps list -->
|
<!-- Swipe up - Apps list -->
|
||||||
<string-array name="default_up">
|
<string-array name="default_up">
|
||||||
<item>launcher:choose</item> <!-- All Apps -->
|
<item>{\"type\": \"action:launcher\", \"id\": \"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>launcher:chooseFromFavorites</item>
|
<item>{\"type\": \"action:launcher\", \"id\": \"choose_from_favorites\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe up (right edge) - Maps -->
|
<!-- Swipe up (right edge) - Maps -->
|
||||||
<string-array name="default_up_right">
|
<string-array name="default_up_right">
|
||||||
<item>app.organicmaps</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"app.organicmaps\", \"activityName\": null}}</item>
|
||||||
<item>com.graphhopper.maps</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.graphhopper.maps\", \"activityName\": null}}</item>
|
||||||
<item>net.osmand.plus</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"net.osmand.plus\", \"activityName\": null}}</item>
|
||||||
<item>com.google.android.apps.maps</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.apps.maps\", \"activityName\": null}}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe double up - Transportation -->
|
<!-- Swipe double up - Transportation -->
|
||||||
<string-array name="default_double_up">
|
<string-array name="default_double_up">
|
||||||
<item>de.schildbach.oeffi</item> <!-- Öffi -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"de.schildbach.oeffi\", \"activityName\": null}}</item> <!-- Öffi -->
|
||||||
<item>de.hafas.android.db</item> <!-- DB Navigator -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"de.hafas.android.db\", \"activityName\": null}}</item> <!-- DB Navigator -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe down - Browser -->
|
<!-- Swipe down - Browser -->
|
||||||
<string-array name="default_down">
|
<string-array name="default_down">
|
||||||
<item>org.mozilla.firefox</item> <!-- Firefox -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.mozilla.firefox\", \"activityName\": null}}</item> <!-- Firefox -->
|
||||||
<item>org.mozilla.fennec</item> <!-- Fennec -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.mozilla.fennec\", \"activityName\": null}}</item> <!-- Fennec -->
|
||||||
<item>org.mozilla.fennec_fdroid</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.mozilla.fennec_fdroid\", \"activityName\": null}}</item>
|
||||||
<item>com.brave.browser</item> <!-- Brave Browser -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.brave.browser\", \"activityName\": null}}</item> <!-- Brave Browser -->
|
||||||
<item>com.duckduckgo.mobile.android</item> <!-- DuckDuckGo Browser -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.duckduckgo.mobile.android\", \"activityName\": null}}</item> <!-- DuckDuckGo Browser -->
|
||||||
<item>com.sec.android.app.sbrowser</item> <!-- Samsung Internet -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.sec.android.app.sbrowser\", \"activityName\": null}}</item> <!-- Samsung Internet -->
|
||||||
<item>com.android.chrome</item> <!-- Chrome -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.chrome\", \"activityName\": null}}</item> <!-- Chrome -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe down (left edge) - Translation -->
|
<!-- Swipe down (left edge) - Translation -->
|
||||||
<string-array name="default_down_left">
|
<string-array name="default_down_left">
|
||||||
<item>com.bnyro.translate</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.bnyro.translate\", \"activityName\": null}}</item>
|
||||||
<item>com.deepl.mobiletranslator</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.deepl.mobiletranslator\", \"activityName\": null}}</item>
|
||||||
<item>com.google.android.apps.translate</item> <!-- Google Translate -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.apps.translate\", \"activityName\": null}}</item> <!-- Google Translate -->
|
||||||
<item>com.microsoft.translator</item> <!-- Microsoft Translate -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.microsoft.translator\", \"activityName\": null}}</item> <!-- Microsoft Translate -->
|
||||||
<item>translate.speech.text.translation.voicetranslator</item> <!-- MindMover Translate -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"translate.speech.text.translation.voicetranslator\", \"activityName\": null}}</item> <!-- MindMover Translate -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="default_down_right">
|
<string-array name="default_down_right">
|
||||||
<item>org.fdroid.fdroid</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.fdroid.fdroid\", \"activityName\": null}}</item>
|
||||||
<item>org.fdroid.basic</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.fdroid.basic\", \"activityName\": null}}</item>
|
||||||
<item>dev.imranr.obtainium</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"dev.imranr.obtainium\", \"activityName\": null}}</item>
|
||||||
<item>dev.imranr.obtainium.fdroid</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"dev.imranr.obtainium.fdroid\", \"activityName\": null}}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe double down - Secure Browser -->
|
<!-- Swipe double down - Secure Browser -->
|
||||||
<string-array name="default_double_down">
|
<string-array name="default_double_down">
|
||||||
<item>org.torproject.torbrowser</item> <!-- Tor Browser -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.torproject.torbrowser\", \"activityName\": null}}</item> <!-- Tor Browser -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe right - Mail -->
|
<!-- Swipe right - Mail -->
|
||||||
<string-array name="default_right">
|
<string-array name="default_right">
|
||||||
<item>net.thunderbird.android</item> <!-- Thunderbird -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"net.thunderbird.android\", \"activityName\": null}}</item> <!-- Thunderbird -->
|
||||||
<item>com.fsck.k9</item> <!-- k9-mail -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.fsck.k9\", \"activityName\": null}}</item> <!-- k9-mail -->
|
||||||
<item>de.web.mobile.android.mail</item> <!-- WebMail -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"de.web.mobile.android.mail\", \"activityName\": null}}</item> <!-- WebMail -->
|
||||||
<item>com.samsung.android.email.provider</item> <!-- Samsung Mail -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.email.provider\", \"activityName\": null}}</item> <!-- Samsung Mail -->
|
||||||
<item>com.google.android.gm</item> <!-- Google Mail -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.gm\", \"activityName\": null}}</item> <!-- Google Mail -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe right (top) -->
|
<!-- Swipe right (top) -->
|
||||||
<string-array name="default_right_top">
|
<string-array name="default_right_top">
|
||||||
<item>com.android.calculator2</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.calculator2\", \"activityName\": null}}</item>
|
||||||
<item>com.sec.android.app.popupcalculator</item> <!-- Samsung Calculator -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.sec.android.app.popupcalculator\", \"activityName\": null}}</item> <!-- Samsung Calculator -->
|
||||||
<item>org.mian.gitnex</item> <!-- GitNex -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.mian.gitnex\", \"activityName\": null}}</item> <!-- GitNex -->
|
||||||
<item>com.github.android</item> <!-- GitHub Android -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.github.android\", \"activityName\": null}}</item> <!-- GitHub Android -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe right (bottom) -->
|
<!-- Swipe right (bottom) -->
|
||||||
<string-array name="default_right_bottom">
|
<string-array name="default_right_bottom">
|
||||||
<item>com.android.documentsui</item> <!-- File Manager -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.documentsui\", \"activityName\": null}}</item> <!-- File Manager -->
|
||||||
<item>com.android.google.documentsui</item> <!-- File Manager -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.google.documentsui\", \"activityName\": null}}</item> <!-- File Manager -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Swipe double right -->
|
<!-- Swipe double right -->
|
||||||
<string-array name="default_double_right">
|
<string-array name="default_double_right">
|
||||||
<item>be.chvp.nanoledger</item> <!-- NanoLedger -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"be.chvp.nanoledger\", \"activityName\": null}}</item> <!-- NanoLedger -->
|
||||||
<item>info.tangential.cone</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"info.tangential.cone\", \"activityName\": null}}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="default_messengers">
|
<string-array name="default_messengers">
|
||||||
<item>de.spiritcroc.riotx</item> <!-- SchildiChat -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"de.spiritcroc.riotx\", \"activityName\": null}}</item> <!-- SchildiChat -->
|
||||||
<item>io.element.android.x</item> <!-- Element X -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"io.element.android.x\", \"activityName\": null}}</item> <!-- Element X -->
|
||||||
<item>im.vector.app</item> <!-- Element -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"im.vector.app\", \"activityName\": null}}</item> <!-- Element -->
|
||||||
<item>org.thoughtcrime.securesms</item> <!-- Signal -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.thoughtcrime.securesms\", \"activityName\": null}}</item> <!-- Signal -->
|
||||||
<item>org.briarproject.briar.android</item> <!-- Briar -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.briarproject.briar.android\", \"activityName\": null}}</item> <!-- Briar -->
|
||||||
<item>eu.siacs.conversations</item> <!-- Conversations -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"eu.siacs.conversations\", \"activityName\": null}}</item> <!-- Conversations -->
|
||||||
<item>ch.threema.app.libre</item> <!-- Threema -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"ch.threema.app.libre\", \"activityName\": null}}</item> <!-- Threema -->
|
||||||
<item>com.android.messaging</item> <!-- SMS -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.messaging\", \"activityName\": null}}</item> <!-- SMS -->
|
||||||
<item>com.google.android.apps.messaging</item> <!-- SMS -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.apps.messaging\", \"activityName\": null}}</item> <!-- SMS -->
|
||||||
<item>com.samsung.android.messaging</item> <!-- Samsung SMS -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.messaging\", \"activityName\": null}}</item> <!-- Samsung SMS -->
|
||||||
<item>com.whatsapp</item> <!-- WhatsApp -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.whatsapp\", \"activityName\": null}}</item> <!-- WhatsApp -->
|
||||||
<item>org.telegram.messenger</item> <!-- Telegram -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.telegram.messenger\", \"activityName\": null}}</item> <!-- Telegram -->
|
||||||
<item>com.discord</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.discord\", \"activityName\": null}}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Volume up -->
|
<!-- Volume up -->
|
||||||
<string-array name="default_volume_up">
|
<string-array name="default_volume_up">
|
||||||
<item>launcher:volumeUp</item>
|
<item>{\"type\": \"action:launcher\", \"id\": \"volume_up\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Volume down -->
|
<!-- Volume down -->
|
||||||
<string-array name="default_volume_down">
|
<string-array name="default_volume_down">
|
||||||
<item>launcher:volumeDown</item>
|
<item>{\"type\": \"action:launcher\", \"id\": \"volume_down\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Double click - Notes -->
|
<!-- Double click - Notes -->
|
||||||
<string-array name="default_double_click">
|
<string-array name="default_double_click">
|
||||||
<item>it.niedermann.owncloud.notes</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"it.niedermann.owncloud.notes\", \"activityName\": null}}</item>
|
||||||
<item>com.samsung.android.app.notes</item> <!-- Samsung Notes -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.app.notes\", \"activityName\": null}}</item> <!-- Samsung Notes -->
|
||||||
<item>com.sec.android.widgetapp.diotek.smemo</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>launcher:lockScreen</item>
|
<item>{\"type\": \"action:launcher\", \"id\": \"lock_screen\"}</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Long click - Security -->
|
<!-- Long click - Security -->
|
||||||
<string-array name="default_long_click">
|
<string-array name="default_long_click">
|
||||||
<item>com.beemdevelopment.aegis</item> <!-- Aegis 2FA -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.beemdevelopment.aegis\", \"activityName\": null}}</item> <!-- Aegis 2FA -->
|
||||||
<item>org.fedorahosted.freeotp</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.fedorahosted.freeotp\", \"activityName\": null}}</item>
|
||||||
<item>proton.android.pass.fdroid</item> <!-- Proton Pass -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"proton.android.pass.fdroid\", \"activityName\": null}}</item> <!-- Proton Pass -->
|
||||||
<item>com.kunzisoft.keepass.libre</item> <!-- KeePassDX -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.kunzisoft.keepass.libre\", \"activityName\": null}}</item> <!-- KeePassDX -->
|
||||||
<item>launcher:settings</item> <!-- Launcher Settings -->
|
<item>{\"type\": \"action:launcher\", \"id\": \"settings\"}</item> <!-- Launcher Settings -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Time / Clock -->
|
<!-- Time / Clock -->
|
||||||
<string-array name="default_time">
|
<string-array name="default_time">
|
||||||
<item>com.android.deskclock</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.android.deskclock\", \"activityName\": null}}</item>
|
||||||
<item>com.google.android.deskclock</item>
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.deskclock\", \"activityName\": null}}</item>
|
||||||
<item>com.sec.android.app.clockpackage</item> <!-- Android Clock -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.sec.android.app.clockpackage\", \"activityName\": null}}</item> <!-- Android Clock -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- Date / Calendar -->
|
<!-- Date / Calendar -->
|
||||||
<string-array name="default_date">
|
<string-array name="default_date">
|
||||||
<item>org.lineageos.etar</item> <!-- LineageOS Calendar -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"org.lineageos.etar\", \"activityName\": null}}</item> <!-- LineageOS Calendar -->
|
||||||
<item>ws.xsoh.etar</item> <!-- Etar -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"ws.xsoh.etar\", \"activityName\": null}}</item> <!-- Etar -->
|
||||||
<item>com.google.android.calendar</item> <!-- Google Calendar -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.google.android.calendar\", \"activityName\": null}}</item> <!-- Google Calendar -->
|
||||||
<item>com.samsung.android.calendar</item> <!-- Samsung Calendar -->
|
<item>{\"type\": \"action:app\", \"app\": {\"packageName\": \"com.samsung.android.calendar\", \"activityName\": null}}</item> <!-- Samsung Calendar -->
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -13,6 +13,8 @@ buildscript {
|
||||||
classpath 'com.android.tools.build:gradle:8.7.3'
|
classpath 'com.android.tools.build:gradle:8.7.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "com.android.tools.build:gradle:$android_plugin_version"
|
classpath "com.android.tools.build:gradle:$android_plugin_version"
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|
Loading…
Add table
Reference in a new issue