2024-01-31 19:49:50 +01:00
|
|
|
// SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
2024-01-31 18:32:43 +01:00
|
|
|
package helium314.keyboard.latin
|
2024-01-28 13:55:11 +01:00
|
|
|
|
|
|
|
import android.app.Application
|
|
|
|
import android.content.Context
|
|
|
|
import androidx.core.content.edit
|
2024-01-28 18:05:38 +01:00
|
|
|
import androidx.preference.PreferenceManager
|
2024-01-31 18:32:43 +01:00
|
|
|
import helium314.keyboard.latin.common.LocaleUtils.constructLocale
|
|
|
|
import helium314.keyboard.latin.settings.Settings
|
|
|
|
import helium314.keyboard.latin.settings.USER_DICTIONARY_SUFFIX
|
2024-02-20 08:44:12 +01:00
|
|
|
import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX
|
2024-01-31 18:32:43 +01:00
|
|
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
|
|
|
import helium314.keyboard.latin.utils.DictionaryInfoUtils
|
|
|
|
import helium314.keyboard.latin.utils.upgradeToolbarPref
|
2024-01-28 18:05:38 +01:00
|
|
|
import java.io.File
|
2024-01-28 13:55:11 +01:00
|
|
|
|
|
|
|
class App : Application() {
|
|
|
|
override fun onCreate() {
|
|
|
|
super.onCreate()
|
|
|
|
checkVersionUpgrade(this)
|
2024-01-28 18:05:38 +01:00
|
|
|
app = this
|
|
|
|
}
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
// used so JniUtils can access application once
|
|
|
|
private var app: App? = null
|
|
|
|
fun getApp(): App? {
|
|
|
|
val application = app
|
|
|
|
app = null
|
|
|
|
return application
|
|
|
|
}
|
2024-01-28 13:55:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun checkVersionUpgrade(context: Context) {
|
|
|
|
val prefs = DeviceProtectedUtils.getSharedPreferences(context)
|
2024-01-28 14:23:38 +01:00
|
|
|
val oldVersion = prefs.getInt(Settings.PREF_VERSION_CODE, 0)
|
|
|
|
if (oldVersion == BuildConfig.VERSION_CODE)
|
2024-01-28 13:55:11 +01:00
|
|
|
return
|
|
|
|
upgradeToolbarPref(prefs)
|
|
|
|
// clear extracted dictionaries, in case updated version contains newer ones
|
2024-01-29 14:32:51 +01:00
|
|
|
DictionaryInfoUtils.getCachedDirectoryList(context)?.forEach {
|
2024-01-28 13:55:11 +01:00
|
|
|
if (!it.isDirectory) return@forEach
|
|
|
|
val files = it.listFiles() ?: return@forEach
|
|
|
|
for (file in files) {
|
|
|
|
if (!file.name.endsWith(USER_DICTIONARY_SUFFIX))
|
|
|
|
file.delete()
|
|
|
|
}
|
|
|
|
}
|
2024-01-28 14:23:38 +01:00
|
|
|
if (oldVersion == 0) // new install or restoring settings from old app name
|
2024-01-28 18:05:38 +01:00
|
|
|
upgradesWhenComingFromOldAppName(context)
|
2024-03-06 22:07:38 +01:00
|
|
|
if (oldVersion <= 1000) { // upgrade old custom layouts name
|
2024-02-20 08:44:12 +01:00
|
|
|
val layoutsDir = Settings.getLayoutsDir(context)
|
|
|
|
val oldShiftSymbolsFile = File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}shift_symbols")
|
|
|
|
if (oldShiftSymbolsFile.exists()) {
|
|
|
|
oldShiftSymbolsFile.renameTo(File(layoutsDir, "${CUSTOM_LAYOUT_PREFIX}symbols_shifted"))
|
|
|
|
}
|
2024-03-06 22:07:38 +01:00
|
|
|
|
|
|
|
// rename subtype setting, and clean old subtypes that might remain in some cases
|
|
|
|
val subtypesPref = prefs.getString("enabled_input_styles", "")!!
|
|
|
|
.split(";").filter { it.isNotEmpty() }
|
|
|
|
.map {
|
|
|
|
val localeAndLayout = it.split(":").toMutableList()
|
|
|
|
localeAndLayout[0] = localeAndLayout[0].constructLocale().toLanguageTag()
|
|
|
|
localeAndLayout.joinToString(":")
|
|
|
|
}.toSet().joinToString(";")
|
|
|
|
val selectedSubtype = prefs.getString("selected_input_style", "")
|
|
|
|
prefs.edit {
|
|
|
|
remove("enabled_input_styles")
|
|
|
|
putString(Settings.PREF_ENABLED_SUBTYPES, subtypesPref)
|
|
|
|
remove("selected_input_style")
|
|
|
|
putString(Settings.PREF_SELECTED_SUBTYPE, selectedSubtype)
|
|
|
|
}
|
2024-02-20 08:44:12 +01:00
|
|
|
}
|
2024-01-28 13:55:11 +01:00
|
|
|
prefs.edit { putInt(Settings.PREF_VERSION_CODE, BuildConfig.VERSION_CODE) }
|
|
|
|
}
|
2024-01-28 14:23:38 +01:00
|
|
|
|
|
|
|
// todo (later): remove it when most users probably have upgraded
|
2024-01-28 18:05:38 +01:00
|
|
|
private fun upgradesWhenComingFromOldAppName(context: Context) {
|
|
|
|
// move layout files
|
|
|
|
try {
|
|
|
|
val layoutsDir = Settings.getLayoutsDir(context)
|
|
|
|
File(context.filesDir, "layouts").listFiles()?.forEach {
|
|
|
|
it.copyTo(File(layoutsDir, it.name), true)
|
|
|
|
it.delete()
|
|
|
|
}
|
|
|
|
} catch (_: Exception) {}
|
|
|
|
// move background images
|
|
|
|
try {
|
|
|
|
val bgDay = File(context.filesDir, "custom_background_image")
|
|
|
|
if (bgDay.isFile) {
|
|
|
|
bgDay.copyTo(Settings.getCustomBackgroundFile(context, false), true)
|
|
|
|
bgDay.delete()
|
|
|
|
}
|
|
|
|
val bgNight = File(context.filesDir, "custom_background_image_night")
|
|
|
|
if (bgNight.isFile) {
|
|
|
|
bgNight.copyTo(Settings.getCustomBackgroundFile(context, true), true)
|
|
|
|
bgNight.delete()
|
|
|
|
}
|
|
|
|
} catch (_: Exception) {}
|
|
|
|
// upgrade prefs
|
|
|
|
val prefs = DeviceProtectedUtils.getSharedPreferences(context)
|
2024-01-28 14:23:38 +01:00
|
|
|
if (prefs.all.containsKey("theme_variant")) {
|
|
|
|
prefs.edit().putString(Settings.PREF_THEME_COLORS, prefs.getString("theme_variant", "")).apply()
|
|
|
|
prefs.edit().remove("theme_variant").apply()
|
|
|
|
}
|
|
|
|
if (prefs.all.containsKey("theme_variant_night")) {
|
|
|
|
prefs.edit().putString(Settings.PREF_THEME_COLORS_NIGHT, prefs.getString("theme_variant_night", "")).apply()
|
|
|
|
prefs.edit().remove("theme_variant_night").apply()
|
|
|
|
}
|
|
|
|
prefs.all.toMap().forEach {
|
|
|
|
if (it.key.startsWith("pref_key_") && it.key != "pref_key_longpress_timeout") {
|
2024-01-28 18:05:38 +01:00
|
|
|
var remove = true
|
2024-01-28 14:23:38 +01:00
|
|
|
when (val value = it.value) {
|
|
|
|
is Boolean -> prefs.edit().putBoolean(it.key.substringAfter("pref_key_"), value).apply()
|
|
|
|
is Int -> prefs.edit().putInt(it.key.substringAfter("pref_key_"), value).apply()
|
|
|
|
is Long -> prefs.edit().putLong(it.key.substringAfter("pref_key_"), value).apply()
|
|
|
|
is String -> prefs.edit().putString(it.key.substringAfter("pref_key_"), value).apply()
|
|
|
|
is Float -> prefs.edit().putFloat(it.key.substringAfter("pref_key_"), value).apply()
|
2024-01-28 18:05:38 +01:00
|
|
|
else -> remove = false
|
2024-01-28 14:23:38 +01:00
|
|
|
}
|
2024-01-28 18:05:38 +01:00
|
|
|
if (remove)
|
|
|
|
prefs.edit().remove(it.key).apply()
|
2024-01-28 14:23:38 +01:00
|
|
|
} else if (it.key.startsWith("pref_")) {
|
2024-01-28 18:05:38 +01:00
|
|
|
var remove = true
|
2024-01-28 14:23:38 +01:00
|
|
|
when (val value = it.value) {
|
|
|
|
is Boolean -> prefs.edit().putBoolean(it.key.substringAfter("pref_"), value).apply()
|
|
|
|
is Int -> prefs.edit().putInt(it.key.substringAfter("pref_"), value).apply()
|
|
|
|
is Long -> prefs.edit().putLong(it.key.substringAfter("pref_"), value).apply()
|
|
|
|
is String -> prefs.edit().putString(it.key.substringAfter("pref_"), value).apply()
|
|
|
|
is Float -> prefs.edit().putFloat(it.key.substringAfter("pref_"), value).apply()
|
2024-01-28 18:05:38 +01:00
|
|
|
else -> remove = false
|
2024-01-28 14:23:38 +01:00
|
|
|
}
|
2024-01-28 18:05:38 +01:00
|
|
|
if (remove)
|
|
|
|
prefs.edit().remove(it.key).apply()
|
2024-01-28 14:23:38 +01:00
|
|
|
}
|
|
|
|
}
|
2024-01-31 16:54:31 +01:00
|
|
|
// change more_keys to popup_keys
|
|
|
|
if (prefs.contains("more_keys_order")) {
|
2024-02-05 09:33:06 +01:00
|
|
|
prefs.edit().putString(Settings.PREF_POPUP_KEYS_ORDER, prefs.getString("more_keys_order", "")?.replace("more_", "popup_")).apply()
|
2024-01-31 16:54:31 +01:00
|
|
|
prefs.edit().remove("more_keys_order").apply()
|
|
|
|
}
|
|
|
|
if (prefs.contains("more_keys_labels_order")) {
|
2024-02-05 09:33:06 +01:00
|
|
|
prefs.edit().putString(Settings.PREF_POPUP_KEYS_LABELS_ORDER, prefs.getString("more_keys_labels_order", "")?.replace("more_", "popup_")).apply()
|
2024-01-31 16:54:31 +01:00
|
|
|
prefs.edit().remove("more_keys_labels_order").apply()
|
|
|
|
}
|
|
|
|
if (prefs.contains("more_more_keys")) {
|
2024-01-31 19:49:50 +01:00
|
|
|
prefs.edit().putString(Settings.PREF_MORE_POPUP_KEYS, prefs.getString("more_more_keys", "")).apply()
|
2024-01-31 16:54:31 +01:00
|
|
|
prefs.edit().remove("more_more_keys").apply()
|
|
|
|
}
|
2024-02-01 08:51:17 +01:00
|
|
|
if (prefs.contains("spellcheck_use_contacts")) {
|
|
|
|
prefs.edit().putBoolean(Settings.PREF_USE_CONTACTS, prefs.getBoolean("spellcheck_use_contacts", false)).apply()
|
|
|
|
prefs.edit().remove("spellcheck_use_contacts").apply()
|
|
|
|
}
|
2024-01-28 18:05:38 +01:00
|
|
|
// upgrade additional subtype locale strings
|
|
|
|
val additionalSubtypes = mutableListOf<String>()
|
|
|
|
Settings.readPrefAdditionalSubtypes(prefs, context.resources).split(";").forEach {
|
|
|
|
val localeString = it.substringBefore(":")
|
|
|
|
additionalSubtypes.add(it.replace(localeString, localeString.constructLocale().toLanguageTag()))
|
|
|
|
}
|
|
|
|
Settings.writePrefAdditionalSubtypes(prefs, additionalSubtypes.joinToString(";"))
|
2024-02-13 08:23:07 +01:00
|
|
|
// move pinned clips to credential protected storage if device is not locked (should never happen)
|
2024-01-28 18:05:38 +01:00
|
|
|
if (!prefs.contains(Settings.PREF_PINNED_CLIPS)) return
|
2024-02-13 08:23:07 +01:00
|
|
|
try {
|
|
|
|
val defaultPrefs = PreferenceManager.getDefaultSharedPreferences(context)
|
|
|
|
defaultPrefs.edit { putString(Settings.PREF_PINNED_CLIPS, prefs.getString(Settings.PREF_PINNED_CLIPS, "")) }
|
|
|
|
prefs.edit { remove(Settings.PREF_PINNED_CLIPS) }
|
|
|
|
} catch (_: IllegalStateException) {
|
|
|
|
// SharedPreferences in credential encrypted storage are not available until after user is unlocked
|
|
|
|
}
|
2024-01-28 14:23:38 +01:00
|
|
|
}
|