diff --git a/app/build.gradle b/app/build.gradle index 8e6f551..c75bb3d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -95,7 +95,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.activity:activity-ktx:1.8.0' + implementation 'androidx.activity:activity:1.8.0' implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'androidx.core:core-ktx:1.15.0' implementation 'androidx.constraintlayout:constraintlayout:2.2.0' diff --git a/app/src/main/java/de/jrpie/android/launcher/Application.kt b/app/src/main/java/de/jrpie/android/launcher/Application.kt index e6cce23..e674e4e 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -7,8 +7,11 @@ import android.content.IntentFilter import android.content.SharedPreferences import android.content.pm.LauncherApps import android.content.pm.ShortcutInfo +import android.os.AsyncTask import android.os.Build import android.os.Build.VERSION_CODES +import android.os.Handler +import android.os.Looper import android.os.UserHandle import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData @@ -20,9 +23,6 @@ import de.jrpie.android.launcher.apps.isPrivateSpaceLocked import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion import de.jrpie.android.launcher.preferences.resetPreferences -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch class Application : android.app.Application() { val apps = MutableLiveData>() @@ -153,8 +153,6 @@ class Application : android.app.Application() { private fun loadApps() { privateSpaceLocked.postValue(isPrivateSpaceLocked(this)) - CoroutineScope(Dispatchers.Default).launch { - apps.postValue(getApps(packageManager, applicationContext)) - } + AsyncTask.execute { apps.postValue(getApps(packageManager, applicationContext)) } } } diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 7bbbdb5..d5e8d13 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -12,6 +12,7 @@ import android.content.pm.LauncherApps import android.content.pm.LauncherApps.ShortcutQuery import android.content.pm.PackageManager import android.content.pm.ShortcutInfo +import android.net.Uri import android.os.Build import android.os.Bundle import android.os.UserHandle @@ -33,9 +34,15 @@ import de.jrpie.android.launcher.apps.getPrivateSpaceUser import de.jrpie.android.launcher.apps.isPrivateSpaceSupported import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity -import androidx.core.net.toUri +/* REQUEST CODES */ + +const val REQUEST_CHOOSE_APP = 1 +const val REQUEST_UNINSTALL = 2 + +const val REQUEST_SET_DEFAULT_HOME = 42 + const val LOG_TAG = "Launcher" fun isDefaultHomeScreen(context: Context): Boolean { @@ -62,8 +69,9 @@ fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) { && !isDefault // using role manager only works when µLauncher is not already the default. ) { val roleManager = context.getSystemService(RoleManager::class.java) - context.startActivity( - roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME) + context.startActivityForResult( + roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME), + REQUEST_SET_DEFAULT_HOME ) return } @@ -117,7 +125,7 @@ fun removeUnusedShortcuts(context: Context) { } fun openInBrowser(url: String, context: Context) { - val intent = Intent(Intent.ACTION_VIEW, url.toUri()) + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) intent.putExtras(Bundle().apply { putBoolean("new_window", true) }) try { context.startActivity(intent) @@ -204,6 +212,14 @@ fun getApps( return loadList } + +// Used in Tutorial and Settings `ActivityOnResult` +fun saveListActivityChoice(data: Intent?) { + val forGesture = data?.getStringExtra("forGesture") ?: return + Gesture.byId(forGesture)?.let { Action.setActionForGesture(it, Action.fromIntent(data)) } +} + + // used for the bug report button fun getDeviceInfo(): String { return """ diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt b/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt index 9a2dc62..ddef92a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt @@ -2,6 +2,7 @@ package de.jrpie.android.launcher.actions import android.app.Activity import android.content.Context +import android.content.Intent import android.content.SharedPreferences.Editor import android.graphics.Rect import android.graphics.drawable.Drawable @@ -11,7 +12,6 @@ import de.jrpie.android.launcher.preferences.LauncherPreferences import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import androidx.core.content.edit @Serializable @@ -29,6 +29,10 @@ sealed interface Action { prefEditor.putString(id, Json.encodeToString(this)) } + fun writeToIntent(intent: Intent) { + intent.putExtra("action", Json.encodeToString(this)) + } + companion object { fun forGesture(gesture: Gesture): Action? { @@ -40,23 +44,23 @@ sealed interface Action { } fun resetToDefaultActions(context: Context) { - LauncherPreferences.getSharedPreferences().edit { - val boundActions = HashSet() - Gesture.entries.forEach { gesture -> - context.resources - .getStringArray(gesture.defaultsResource) - .filterNot { boundActions.contains(it) } - .map { Pair(it, Json.decodeFromString(it)) } - .firstOrNull { it.second.isAvailable(context) } - ?.apply { - // allow to bind CHOOSE to multiple gestures - if (second != LauncherAction.CHOOSE) { - boundActions.add(first) - } - second.bindToGesture(this@edit, gesture.id) + val editor = LauncherPreferences.getSharedPreferences().edit() + val boundActions = HashSet() + Gesture.entries.forEach { gesture -> + context.resources + .getStringArray(gesture.defaultsResource) + .filterNot { boundActions.contains(it) } + .map { Pair(it, Json.decodeFromString(it)) } + .firstOrNull { it.second.isAvailable(context) } + ?.apply { + // allow to bind CHOOSE to multiple gestures + if (second != LauncherAction.CHOOSE) { + boundActions.add(first) } - } + second.bindToGesture(editor, gesture.id) + } } + editor.apply() } fun setActionForGesture(gesture: Gesture, action: Action?) { @@ -64,15 +68,15 @@ sealed interface Action { clearActionForGesture(gesture) return } - LauncherPreferences.getSharedPreferences().edit { - action.bindToGesture(this, gesture.id) - } + val editor = LauncherPreferences.getSharedPreferences().edit() + action.bindToGesture(editor, gesture.id) + editor.apply() } fun clearActionForGesture(gesture: Gesture) { - LauncherPreferences.getSharedPreferences().edit { - remove(gesture.id) - } + LauncherPreferences.getSharedPreferences().edit() + .remove(gesture.id) + .apply() } fun launch( @@ -83,9 +87,6 @@ sealed interface Action { ) { if (action != null && action.invoke(context)) { if (context is Activity) { - // There does not seem to be a good alternative to overridePendingTransition. - // Note that we can't use overrideActivityTransition here. - @Suppress("deprecation") context.overridePendingTransition(animationIn, animationOut) } } else { @@ -96,5 +97,10 @@ sealed interface Action { ).show() } } + + fun fromIntent(data: Intent): Action? { + val json = data.getStringExtra("action") ?: return null + return Json.decodeFromString(json) + } } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt b/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt index a2434e1..110e4f8 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt @@ -250,7 +250,7 @@ enum class Gesture( "action.back", R.string.settings_gesture_back, R.string.settings_gesture_description_back, - R.array.default_back + R.array.default_up ); enum class Edge { diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt index 541510a..8ae2415 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/lock/LockMethod.kt @@ -9,6 +9,7 @@ import de.jrpie.android.launcher.R import de.jrpie.android.launcher.preferences.LauncherPreferences +@Suppress("unused") enum class LockMethod( private val lock: (Context) -> Unit, private val isEnabled: (Context) -> Boolean, diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt index 9534431..944cfaa 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/AppInfo.kt @@ -15,7 +15,19 @@ import kotlinx.serialization.Serializable */ @Serializable @SerialName("app") -data class AppInfo(val packageName: String, val activityName: String?, val user: Int = INVALID_USER): AbstractAppInfo { +class AppInfo(val packageName: String, val activityName: String?, val user: Int = INVALID_USER): AbstractAppInfo { + + override fun equals(other: Any?): Boolean { + if(other is AppInfo) { + return other.user == user && other.packageName == packageName + && other.activityName == activityName + } + return super.equals(other) + } + + override fun hashCode(): Int { + return packageName.hashCode() + } fun getLauncherActivityInfo( context: Context @@ -26,4 +38,10 @@ data class AppInfo(val packageName: String, val activityName: String?, val user: return activityList.firstOrNull { app -> app.name == activityName } ?: activityList.firstOrNull() } + + + override fun toString(): String { + return "AppInfo {package=$packageName, activity=$activityName, user=$user}" + } + } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt index 54230ae..1dc1e1f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt @@ -16,7 +16,7 @@ import kotlinx.serialization.Serializable @RequiresApi(Build.VERSION_CODES.N_MR1) @Serializable @SerialName("shortcut") -data class PinnedShortcutInfo( +class PinnedShortcutInfo( val id: String, val packageName: String, val activityName: String, @@ -43,4 +43,25 @@ data class PinnedShortcutInfo( null } } + + override fun equals(other: Any?): Boolean { + return (other as? PinnedShortcutInfo)?.let { + packageName == this.packageName && + activityName == this.activityName && + id == this.id && + user == this.user + } ?: false + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + packageName.hashCode() + result = 31 * result + activityName.hashCode() + result = 31 * result + user + return result + } + + override fun toString(): String { + return "PinnedShortcutInfo { package=$packageName, activity=$activityName, user=$user, id=$id}" + } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt index 24665d7..e44ff1c 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt @@ -123,7 +123,6 @@ fun togglePrivateSpaceLock(context: Context) { } } -@Suppress("SameReturnValue") fun hidePrivateSpaceWhenLocked(context: Context): Boolean { // Trying to access the setting as a 3rd party launcher raises a security exception. // This is an Android bug: https://issuetracker.google.com/issues/352276244#comment5 diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/ColorPreference.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/ColorPreference.kt index 0f95efd..a21d458 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/ColorPreference.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/ColorPreference.kt @@ -17,7 +17,6 @@ import androidx.core.graphics.green import androidx.core.graphics.red import androidx.preference.Preference import de.jrpie.android.launcher.R -import androidx.core.graphics.toColorInt class ColorPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { @@ -53,7 +52,7 @@ class ColorPreference(context: Context, attrs: AttributeSet?) : AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { setView(R.layout.dialog_choose_color) setTitle(R.string.dialog_choose_color_title) - setPositiveButton(android.R.string.ok) { _, _ -> + setPositiveButton(R.string.dialog_select_color_ok) { _, _ -> persistInt(currentColor) summary = currentColor.getHex() } @@ -84,10 +83,10 @@ class ColorPreference(context: Context, attrs: AttributeSet?) : override fun onTextChanged(text: CharSequence?, p1: Int, p2: Int, p3: Int) {} override fun afterTextChanged(editable: Editable?) { preview.hasFocus() || return - val newText = editable?.toString() ?: return - newText.isBlank() && return + val newText = editable?.toString() + newText.isNullOrBlank() && return try { - val newColor = newText.toColorInt() + val newColor = Color.parseColor(newText.toString()) currentColor = newColor updateColor(false) } catch (_: IllegalArgumentException) { diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/ListLayout.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/ListLayout.kt index 5f7b9d6..e20945a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/ListLayout.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/ListLayout.kt @@ -1,7 +1,6 @@ package de.jrpie.android.launcher.preferences import android.content.Context -import android.util.TypedValue import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -28,10 +27,8 @@ enum class ListLayout( GRID( { c -> val displayMetrics = c.resources.displayMetrics - val widthColumnPx = - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 90f, displayMetrics) - val numColumns = (displayMetrics.widthPixels / widthColumnPx).toInt() - GridLayoutManager(c, numColumns) + val widthSp = displayMetrics.widthPixels / displayMetrics.scaledDensity + GridLayoutManager(c, (widthSp / 90).toInt()) }, R.layout.list_apps_row_variant_grid, false diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt index a1cb022..6252811 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt @@ -13,11 +13,9 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.json.JSONException import org.json.JSONObject -import androidx.core.content.edit @Serializable -@Suppress("unused") private class LegacyMapEntry(val key: AppInfo, val value: String) private fun serializeMapAppInfo(value: Map?): Set? { @@ -102,7 +100,7 @@ private fun migrateAppInfoStringMap(key: String) { } }?.toMap(HashMap()) )?.let { - preferences.edit { putStringSet(key, it) } + preferences.edit().putStringSet(key, it).apply() } } @@ -111,16 +109,16 @@ private fun migrateAppInfoSet(key: String) { .map(AppInfo.Companion::legacyDeserialize) .map(AppInfo::serialize) .toSet() - .let { LauncherPreferences.getSharedPreferences().edit { putStringSet(key, it) } } + .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)) - .remove("$key.app") - .remove("$key.user") - } + LauncherPreferences.getSharedPreferences().edit() + .putString(key, Json.encodeToString(action)) + .remove("$key.app") + .remove("$key.user") + .apply() } } diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt index 2d1152d..a33670b 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt @@ -6,7 +6,7 @@ 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 -import androidx.core.content.edit + private fun migrateStringPreference( @@ -64,317 +64,318 @@ fun migratePreferencesFromVersionUnknown(context: Context) { return } - LauncherPreferences.getSharedPreferences().edit { + val newPrefs = LauncherPreferences.getSharedPreferences().edit() - migrateBooleanPreference( - oldPrefs, - this, - "startedBefore", - "internal.started_before", - false - ) + migrateBooleanPreference( + oldPrefs, + newPrefs, + "startedBefore", + "internal.started_before", + false + ) - migrateStringPreference( - oldPrefs, - this, - "action_volumeUpApp", - "action.volume_up.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_volumeUpApp_user", - "action.volume_up.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_volumeDownApp", - "action.volume_down.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_volumeDownApp_user", - "action.volume_down.user", - -1 - ) - migrateStringPreference(oldPrefs, this, "action_timeApp", "action.time.app", "") - migrateIntPreference(oldPrefs, this, "action_timeApp_user", "action.time.user", -1) - migrateStringPreference(oldPrefs, this, "action_dateApp", "action.date.app", "") - migrateIntPreference(oldPrefs, this, "action_dateApp_user", "action.date.user", -1) - migrateStringPreference( - oldPrefs, - this, - "action_longClickApp", - "action.long_click.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_longClickApp_user", - "action.long_click.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_doubleClickApp", - "action.double_click.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_doubleClickApp_user", - "action.double_click.user", - -1 - ) - migrateStringPreference(oldPrefs, this, "action_upApp", "action.up.app", "") - migrateIntPreference(oldPrefs, this, "action_upApp_user", "action.up.user", -1) - migrateStringPreference( - oldPrefs, - this, - "action_up_leftApp", - "action.up_left.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_up_leftApp_user", - "action.up_left.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_up_rightApp", - "action.up_right.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_up_rightApp_user", - "action.up_right.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_doubleUpApp", - "action.double_up.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_doubleUpApp_user", - "action.double_up.user", - -1 - ) - migrateStringPreference(oldPrefs, this, "action_downApp", "action.down.app", "") - migrateIntPreference(oldPrefs, this, "action_downApp_user", "action.down.user", -1) - migrateStringPreference( - oldPrefs, - this, - "action_down_leftApp", - "action.down_left.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_down_leftApp_user", - "action.down_left.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_down_rightApp", - "action.down_right.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_down_rightApp_user", - "action.down_right.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_doubleDownApp", - "action.double_down.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_doubleDownApp_user", - "action.double_down.user", - -1 - ) - migrateStringPreference(oldPrefs, this, "action_leftApp", "action.left.app", "") - migrateIntPreference(oldPrefs, this, "action_leftApp_user", "action.left.user", -1) - migrateStringPreference( - oldPrefs, - this, - "action_left_topApp", - "action.left_top.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_left_topApp_user", - "action.left_top.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_left_bottomApp", - "action.left_bottom.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_left_bottomApp_user", - "action.left_bottom.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_doubleLeftApp", - "action.double_left.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_doubleLeftApp_user", - "action.double_left.user", - -1 - ) - migrateStringPreference(oldPrefs, this, "action_rightApp", "action.right.app", "") - migrateIntPreference( - oldPrefs, - this, - "action_rightApp_user", - "action.right.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_right_topApp", - "action.right_top.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_right_topApp_user", - "action.right_top.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_right_bottomApp", - "action.right_bottom.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_right_bottomApp_user", - "action.right_bottom.user", - -1 - ) - migrateStringPreference( - oldPrefs, - this, - "action_doubleRightApp", - "action.double_right.app", - "" - ) - migrateIntPreference( - oldPrefs, - this, - "action_doubleRightApp_user", - "action.double_right.user", - -1 - ) - migrateBooleanPreference(oldPrefs, this, "timeVisible", "clock.time_visible", true) - migrateBooleanPreference(oldPrefs, this, "dateVisible", "clock.date_visible", true) - migrateBooleanPreference( - oldPrefs, - this, - "dateLocalized", - "clock.date_localized", - false - ) - migrateBooleanPreference( - oldPrefs, - this, - "dateTimeFlip", - "clock.date_time_flip", - false - ) - migrateBooleanPreference( - oldPrefs, - this, - "disableTimeout", - "display.disable_timeout", - false - ) - migrateBooleanPreference( - oldPrefs, - this, - "useFullScreen", - "display.use_full_screen", - true - ) - migrateBooleanPreference( - oldPrefs, - this, - "enableDoubleActions", - "enabled_gestures.double_actions", - true - ) - migrateBooleanPreference( - oldPrefs, - this, - "enableEdgeActions", - "enabled_gestures.edge_actions", - true - ) - migrateBooleanPreference( - oldPrefs, - this, - "searchAutoLaunch", - "functionality.search_auto_launch", - true - ) - migrateBooleanPreference( - oldPrefs, - this, - "searchAutoKeyboard", - "functionality.search_auto_keyboard", - true - ) - } + 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" -> { diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt index d3088f4..816d94f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/theme/ColorTheme.kt @@ -5,6 +5,7 @@ import android.content.res.Resources import com.google.android.material.color.DynamicColors import de.jrpie.android.launcher.R +@Suppress("unused") enum class ColorTheme( private val id: Int, private val labelResource: Int, diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt index a658cd1..14e04d5 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt @@ -57,8 +57,6 @@ class HomeActivity : UIObject, AppCompatActivity() { super.onCreate() val displayMetrics = DisplayMetrics() - - @Suppress("deprecation") // required to support API < 30 windowManager.defaultDisplay.getMetrics(displayMetrics) val width = displayMetrics.widthPixels @@ -80,7 +78,6 @@ class HomeActivity : UIObject, AppCompatActivity() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { binding.root.setOnApplyWindowInsetsListener { _, windowInsets -> - @Suppress("deprecation") // required to support API 29 val insets = windowInsets.systemGestureInsets touchGestureDetector.setSystemGestureInsets(insets) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt index 71908ba..4d5d700 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/PinShortcutActivity.kt @@ -24,7 +24,6 @@ import de.jrpie.android.launcher.actions.ShortcutAction import de.jrpie.android.launcher.apps.PinnedShortcutInfo import de.jrpie.android.launcher.databinding.ActivityPinShortcutBinding import de.jrpie.android.launcher.preferences.LauncherPreferences -import androidx.core.content.edit class PinShortcutActivity : AppCompatActivity(), UIObject { private lateinit var binding: ActivityPinShortcutBinding @@ -73,12 +72,9 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { isBound = true request.accept() } - LauncherPreferences.getSharedPreferences().edit { - ShortcutAction(PinnedShortcutInfo(request.shortcutInfo!!)).bindToGesture( - this, - gesture.id - ) - } + val editor = LauncherPreferences.getSharedPreferences().edit() + ShortcutAction(PinnedShortcutInfo(request.shortcutInfo!!)).bindToGesture(editor, gesture.id) + editor.apply() dialog.dismiss() } dialog.findViewById(R.id.dialog_select_gesture_recycler).apply { @@ -121,11 +117,11 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { } inner class GestureRecyclerAdapter(val context: Context, val onClick: (Gesture) -> Unit): RecyclerView.Adapter() { - private val gestures = Gesture.entries.filter { it.isEnabled() }.toList() + val gestures = Gesture.entries.filter { it.isEnabled() }.toList() inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val label: TextView = itemView.findViewById(R.id.dialog_select_gesture_row_name) - val description: TextView = itemView.findViewById(R.id.dialog_select_gesture_row_description) - val icon: ImageView = itemView.findViewById(R.id.dialog_select_gesture_row_icon) + val label = itemView.findViewById(R.id.dialog_select_gesture_row_name) + val description = itemView.findViewById(R.id.dialog_select_gesture_row_description) + val icon = itemView.findViewById(R.id.dialog_select_gesture_row_icon) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt b/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt index 51324f4..d97388f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/UIObject.kt @@ -15,10 +15,8 @@ import de.jrpie.android.launcher.preferences.LauncherPreferences * An interface implemented by every [Activity], Fragment etc. in Launcher. * It handles themes and window flags - a useful abstraction as it is the same everywhere. */ -@Suppress("deprecation") // FLAG_FULLSCREEN is required to support API level < 30 fun setWindowFlags(window: Window, homeScreen: Boolean) { window.setFlags(0, 0) // clear flags - // Display notification bar if (LauncherPreferences.display().hideStatusBar()) window.setFlags( diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt index 59d83e5..64bd850 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt @@ -1,18 +1,24 @@ package de.jrpie.android.launcher.ui.list +import android.app.Activity +import android.content.Intent import android.content.res.Resources import android.graphics.Rect import android.os.Build import android.os.Bundle import android.view.View +import android.widget.Toast import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources import androidx.fragment.app.Fragment -import androidx.viewpager2.adapter.FragmentStateAdapter -import com.google.android.material.tabs.TabLayoutMediator +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentPagerAdapter +import androidx.viewpager.widget.ViewPager +import com.google.android.material.tabs.TabLayout import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.REQUEST_UNINSTALL import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.apps.hidePrivateSpaceWhenLocked @@ -109,13 +115,10 @@ class ListActivity : AppCompatActivity(), UIObject { ?.let { ListActivityIntention.valueOf(it) } ?: ListActivityIntention.VIEW - @Suppress("deprecation") // required to support API level < 33 favoritesVisibility = bundle.getSerializable("favoritesVisibility") as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility - @Suppress("deprecation") // required to support API level < 33 privateSpaceVisibility = bundle.getSerializable("privateSpaceVisibility") as? AppFilter.Companion.AppSetVisibility ?: privateSpaceVisibility - @Suppress("deprecation") // required to support API level < 33 hiddenVisibility = bundle.getSerializable("hiddenVisibility") as? AppFilter.Companion.AppSetVisibility ?: hiddenVisibility @@ -182,6 +185,20 @@ class ListActivity : AppCompatActivity(), UIObject { finish() } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQUEST_UNINSTALL) { + if (resultCode == Activity.RESULT_OK) { + Toast.makeText(this, getString(R.string.list_removed), Toast.LENGTH_LONG).show() + finish() + } else if (resultCode == Activity.RESULT_FIRST_USER) { + Toast.makeText(this, getString(R.string.list_not_removed), Toast.LENGTH_LONG).show() + finish() + } + } + } + + fun updateTitle() { var titleResource = intention.titleResource if (intention == ListActivityIntention.VIEW) { @@ -224,14 +241,11 @@ class ListActivity : AppCompatActivity(), UIObject { updateTitle() - val sectionsPagerAdapter = ListSectionsPagerAdapter(this) - binding.listViewpager.apply { - adapter = sectionsPagerAdapter - currentItem = 0 - } - TabLayoutMediator(binding.listTabs, binding.listViewpager) { tab, position -> - tab.text = sectionsPagerAdapter.getPageTitle(position) - }.attach() + val sectionsPagerAdapter = ListSectionsPagerAdapter(this, supportFragmentManager) + val viewPager: ViewPager = findViewById(R.id.list_viewpager) + viewPager.adapter = sectionsPagerAdapter + val tabs: TabLayout = findViewById(R.id.list_tabs) + tabs.setupWithViewPager(viewPager) } } @@ -244,10 +258,10 @@ private val TAB_TITLES = arrayOf( * The [ListSectionsPagerAdapter] returns the fragment, * which corresponds to the selected tab in [ListActivity]. */ -class ListSectionsPagerAdapter(private val activity: ListActivity) : - FragmentStateAdapter(activity) { +class ListSectionsPagerAdapter(private val activity: ListActivity, fm: FragmentManager) : + FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - override fun createFragment(position: Int): Fragment { + override fun getItem(position: Int): Fragment { return when (position) { 0 -> ListFragmentApps() 1 -> ListFragmentOther() @@ -255,11 +269,11 @@ class ListSectionsPagerAdapter(private val activity: ListActivity) : } } - fun getPageTitle(position: Int): CharSequence { + override fun getPageTitle(position: Int): CharSequence { return activity.resources.getString(TAB_TITLES[position]) } - override fun getItemCount(): Int { + override fun getCount(): Int { return when (activity.intention) { ListActivity.ListActivityIntention.VIEW -> 1 else -> 2 diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt index 65278ce..c4428b7 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt @@ -2,6 +2,7 @@ package de.jrpie.android.launcher.ui.list.apps import android.annotation.SuppressLint import android.app.Activity +import android.content.Intent import android.graphics.Rect import android.view.LayoutInflater import android.view.View @@ -14,8 +15,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.actions.Action -import de.jrpie.android.launcher.actions.Gesture +import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.apps.AppInfo @@ -195,10 +195,11 @@ class AppsRecyclerAdapter( } ListActivity.ListActivityIntention.PICK -> { + val returnIntent = Intent() + appInfo.getAction().writeToIntent(returnIntent) + returnIntent.putExtra("forGesture", forGesture) + activity.setResult(REQUEST_CHOOSE_APP, returnIntent) activity.finish() - forGesture ?: return - val gesture = Gesture.byId(forGesture) ?: return - Action.setActionForGesture(gesture, appInfo.getAction()) } } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt index 22dff02..8b681b9 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt @@ -6,6 +6,7 @@ import android.content.Context import android.content.Intent import android.content.pm.LauncherApps import android.graphics.Rect +import android.net.Uri import android.os.Bundle import android.util.Log import android.view.View @@ -13,9 +14,11 @@ import android.widget.EditText import androidx.appcompat.app.AlertDialog import com.google.android.material.snackbar.Snackbar import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.REQUEST_UNINSTALL import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.AbstractAppInfo import de.jrpie.android.launcher.apps.AbstractDetailedAppInfo +import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.apps.PinnedShortcutInfo import de.jrpie.android.launcher.getUserFromId import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -41,13 +44,17 @@ fun AbstractAppInfo.uninstall(activity: Activity) { Log.i(LOG_TAG, "uninstalling $this") - val intent = Intent(Intent.ACTION_DELETE) + val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) intent.data = "package:$packageName".toUri() getUserFromId(userId, activity).let { user -> intent.putExtra(Intent.EXTRA_USER, user) } - activity.startActivity(intent) + intent.putExtra(Intent.EXTRA_RETURN_RESULT, true) + activity.startActivityForResult( + intent, + REQUEST_UNINSTALL + ) } else if(this is PinnedShortcutInfo) { val pinned = LauncherPreferences.apps().pinnedShortcuts() ?: mutableSetOf() pinned.remove(this) @@ -95,8 +102,8 @@ fun AbstractDetailedAppInfo.showRenameDialog(context: Context) { AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { setTitle(context.getString(R.string.dialog_rename_title, getLabel())) setView(R.layout.dialog_rename_app) - setNegativeButton(android.R.string.cancel) { d, _ -> d.cancel() } - setPositiveButton(android.R.string.ok) { d, _ -> + setNegativeButton(R.string.dialog_cancel) { d, _ -> d.cancel() } + setPositiveButton(R.string.dialog_rename_ok) { d, _ -> setCustomLabel( (d as? AlertDialog) ?.findViewById(R.id.dialog_rename_app_edit_text) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt index f176469..70d5376 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt @@ -1,6 +1,7 @@ package de.jrpie.android.launcher.ui.list.other import android.app.Activity +import android.content.Intent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -8,8 +9,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.actions.Action -import de.jrpie.android.launcher.actions.Gesture +import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.ui.list.ListActivity @@ -36,10 +36,7 @@ class OtherRecyclerAdapter(val activity: Activity) : val pos = bindingAdapterPosition val content = othersList[pos] - activity.finish() - val gestureId = (activity as? ListActivity)?.forGesture ?: return - val gesture = Gesture.byId(gestureId) ?: return - Action.setActionForGesture(gesture, content) + (activity as? ListActivity)?.forGesture?.let { returnChoiceIntent(it, content) } } init { @@ -64,4 +61,12 @@ class OtherRecyclerAdapter(val activity: Activity) : val view: View = inflater.inflate(R.layout.list_other_row, parent, false) return ViewHolder(view) } + + private fun returnChoiceIntent(forGesture: String, action: LauncherAction) { + val returnIntent = Intent() + returnIntent.putExtra("forGesture", forGesture) + action.writeToIntent(returnIntent) + activity.setResult(REQUEST_CHOOSE_APP, returnIntent) + activity.finish() + } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/SettingsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/SettingsActivity.kt index 4c464e5..fde61a7 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/SettingsActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/SettingsActivity.kt @@ -1,5 +1,6 @@ package de.jrpie.android.launcher.ui.settings +import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.content.res.Resources @@ -7,14 +8,17 @@ import android.os.Bundle import android.provider.Settings import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity -import androidx.viewpager2.adapter.FragmentStateAdapter -import com.google.android.material.tabs.TabLayoutMediator +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentPagerAdapter +import androidx.viewpager.widget.ViewPager +import com.google.android.material.tabs.TabLayout import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.databinding.SettingsBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.theme.Background import de.jrpie.android.launcher.preferences.theme.ColorTheme +import de.jrpie.android.launcher.saveListActivityChoice import de.jrpie.android.launcher.ui.UIObject import de.jrpie.android.launcher.ui.settings.actions.SettingsFragmentActions import de.jrpie.android.launcher.ui.settings.launcher.SettingsFragmentLauncher @@ -45,15 +49,15 @@ class SettingsActivity : AppCompatActivity(), UIObject { // This ugly workaround causes a jump to the top of the list, but at least // the text stays readable. val i = Intent(this, SettingsActivity::class.java) - .also { it.putExtra(EXTRA_TAB, 1) } + .also { it.putExtra("tab", 1) } finish() startActivity(i) } else - if (prefKey?.startsWith("theme.") == true || - prefKey?.startsWith("display.") == true - ) { - recreate() - } + if (prefKey?.startsWith("theme.") == true || + prefKey?.startsWith("display.") == true + ) { + recreate() + } } private lateinit var binding: SettingsBinding @@ -67,14 +71,15 @@ class SettingsActivity : AppCompatActivity(), UIObject { setContentView(binding.root) // set up tabs and swiping in settings - val sectionsPagerAdapter = SettingsSectionsPagerAdapter(this) - binding.settingsViewpager.apply { - adapter = sectionsPagerAdapter - setCurrentItem(intent.getIntExtra(EXTRA_TAB, 0), false) + val sectionsPagerAdapter = SettingsSectionsPagerAdapter(this, supportFragmentManager) + val viewPager: ViewPager = findViewById(R.id.settings_viewpager) + viewPager.adapter = sectionsPagerAdapter + + val tabs: TabLayout = findViewById(R.id.settings_tabs) + tabs.setupWithViewPager(viewPager) + if (intent.hasExtra("tab")) { + tabs.getTabAt(intent.getIntExtra("tab", 0))?.select() } - TabLayoutMediator(binding.settingsTabs, binding.settingsViewpager) { tab, position -> - tab.text = sectionsPagerAdapter.getPageTitle(position) - }.attach() } override fun onStart() { @@ -103,8 +108,11 @@ class SettingsActivity : AppCompatActivity(), UIObject { } } - companion object { - private const val EXTRA_TAB = "tab" + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQUEST_CHOOSE_APP -> saveListActivityChoice(data) + else -> super.onActivityResult(requestCode, resultCode, data) + } } } @@ -114,10 +122,10 @@ private val TAB_TITLES = arrayOf( R.string.settings_tab_meta ) -class SettingsSectionsPagerAdapter(private val activity: FragmentActivity) : - FragmentStateAdapter(activity) { +class SettingsSectionsPagerAdapter(private val context: Context, fm: FragmentManager) : + FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - override fun createFragment(position: Int): Fragment { + override fun getItem(position: Int): Fragment { return when (position) { 0 -> SettingsFragmentActions() 1 -> SettingsFragmentLauncher() @@ -126,11 +134,11 @@ class SettingsSectionsPagerAdapter(private val activity: FragmentActivity) : } } - fun getPageTitle(position: Int): CharSequence { - return activity.resources.getString(TAB_TITLES[position]) + override fun getPageTitle(position: Int): CharSequence { + return context.resources.getString(TAB_TITLES[position]) } - override fun getItemCount(): Int { + override fun getCount(): Int { return 3 } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt index ae47ce2..630b5b0 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt @@ -16,6 +16,7 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.apps.AppFilter @@ -178,6 +179,9 @@ class ActionsRecyclerAdapter(val activity: Activity) : intent.putExtra("intention", ListActivity.ListActivityIntention.PICK.toString()) intent.putExtra("hiddenVisibility", AppFilter.Companion.AppSetVisibility.VISIBLE) intent.putExtra("forGesture", gesture.id) // for which action we choose the app - activity.startActivity(intent) + activity.startActivityForResult( + intent, + REQUEST_CHOOSE_APP + ) } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt index dea0bcf..26f276a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt @@ -2,6 +2,7 @@ package de.jrpie.android.launcher.ui.settings.meta import android.app.AlertDialog import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -19,6 +20,7 @@ import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.resetPreferences import de.jrpie.android.launcher.ui.LegalInfoActivity import de.jrpie.android.launcher.ui.UIObject +import de.jrpie.android.launcher.ui.tutorial.TutorialActivity /** * The [SettingsFragmentMeta] is a used as a tab in the SettingsActivity. diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt index 847639c..12c6c8a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt @@ -1,5 +1,6 @@ package de.jrpie.android.launcher.ui.tutorial +import android.content.Intent import android.content.res.Resources import android.os.Build import android.os.Bundle @@ -11,8 +12,10 @@ import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator +import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.databinding.TutorialBinding import de.jrpie.android.launcher.preferences.LauncherPreferences +import de.jrpie.android.launcher.saveListActivityChoice import de.jrpie.android.launcher.ui.UIObject import de.jrpie.android.launcher.ui.blink import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment0Start @@ -33,7 +36,6 @@ class TutorialActivity : AppCompatActivity(), UIObject { private lateinit var binding: TutorialBinding - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) super.onCreate() @@ -111,9 +113,14 @@ class TutorialActivity : AppCompatActivity(), UIObject { super.onStart() } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQUEST_CHOOSE_APP -> saveListActivityChoice(data) + else -> super.onActivityResult(requestCode, resultCode, data) + } + } + // prevent going back when the tutorial is shown for the first time - @Deprecated("Deprecated in Java", ReplaceWith("use anyway")) - @Suppress("deprecation") // support API level < 33 override fun onBackPressed() { if (LauncherPreferences.internal().started()) super.onBackPressed() diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt index 5e38b9f..549f10f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/util/HtmlTextView.kt @@ -12,7 +12,6 @@ class HtmlTextView(context: Context, attr: AttributeSet?, int: Int) : constructor(context: Context) : this(context, null, 0) init { - @Suppress("deprecation") // required to support API level < 24 text = Html.fromHtml(text.toString()) movementMethod = LinkMovementMethod.getInstance() } diff --git a/app/src/main/res/drawable/baseline_more_horiz_24.xml b/app/src/main/res/drawable/baseline_more_horiz_24.xml new file mode 100644 index 0000000..061fae2 --- /dev/null +++ b/app/src/main/res/drawable/baseline_more_horiz_24.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..4f1c4ab --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/round_outline.xml b/app/src/main/res/drawable/round_outline.xml new file mode 100644 index 0000000..3650338 --- /dev/null +++ b/app/src/main/res/drawable/round_outline.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-mdpi/tutorial_app_list.png b/app/src/main/res/drawable/tutorial_app_list.png similarity index 100% rename from app/src/main/res/drawable-mdpi/tutorial_app_list.png rename to app/src/main/res/drawable/tutorial_app_list.png diff --git a/app/src/main/res/drawable-mdpi/tutorial_home_screen.png b/app/src/main/res/drawable/tutorial_home_screen.png similarity index 100% rename from app/src/main/res/drawable-mdpi/tutorial_home_screen.png rename to app/src/main/res/drawable/tutorial_home_screen.png diff --git a/app/src/main/res/layout/activity_pin_shortcut.xml b/app/src/main/res/layout/activity_pin_shortcut.xml index 2519374..5e10118 100644 --- a/app/src/main/res/layout/activity_pin_shortcut.xml +++ b/app/src/main/res/layout/activity_pin_shortcut.xml @@ -116,7 +116,7 @@ android:layout_margin="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@android:string/ok" + android:text="@string/pin_shortcut_button_ok" app:layout_constraintBottom_toBottomOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/list.xml b/app/src/main/res/layout/list.xml index 45bcb85..43c1f4c 100644 --- a/app/src/main/res/layout/list.xml +++ b/app/src/main/res/layout/list.xml @@ -95,7 +95,7 @@ - - - Uhr Auf die Uhrzeit klicken App wählen + Alle Anwendungen Apps installieren Store nicht gefunden Seleccionar Launcher Información de la aplicación + Su dispositivo no posee esta caracrerística. Desea cambiar los detalles de la aplicación? Ver tutorial de Launcher Configuración por defecto Todas sus preferencias se eliminarán. Desea continuar? @@ -92,6 +96,8 @@ Otros Desinstalar Información + Se eliminó la aplicación + No se pudo eliminar la aplicación Buscar Aplicaciones Configuración de Launcher Aplicaciones diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 0487823..388e089 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -37,6 +37,7 @@ Date Horloge Choisir une application + Voir toutes les applications Installer des applications Magasin d\'applications introuvable Choisir μLauncher comme application d\'écran d\'accueil par défaut Informations sur l\'application + Votre appareil ne prend pas en charge cette fonctionnalité. Souhaitez-vous plutôt accéder aux détails de l\'application ? Regarder le tutoriel Réinitialiser Vous allez réinitialiser tous vos paramètres. Souhaitez-vous poursuivre ? @@ -84,6 +88,8 @@ Autre Désinstaller Informations + Application supprimée + Impossible de désinstaller l\'application Chercher des applications Réglages d\'µLauncher Toutes les Applications diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5a4b16a..320bfc6 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -34,6 +34,7 @@



Puoi cambiare le tue scelte in seguito nelle impostazioni. ]]>
+ Il tuo dispositivo non supporta questa funzione. Vuoi aprire la pagina di dettaglio dell\'applicazione? Impossibile aprire l\'applicazione Desideri modificare le impostazioni? Apri le impostazioni per abbinare un\'azione a questo gesto @@ -82,6 +83,7 @@ Premi il pulsante di aumento del volume Riduci il volume Premi il pulsante per ridurre il volume + Vedi tutte le applicazioni Installa le applicazioni Icone monocromatiche Mostra l\'ora @@ -110,8 +112,10 @@ Font Inverti data e ora Scegli uno sfondo + Cambia immagine di sfondo Schermo Mantieni lo schermo acceso + Schermo intero Ruota lo schermo Funzionalità Apri automaticamente la tastiera per cercare @@ -177,6 +181,7 @@ Nascondi Mostra Rinomina + Le applicazioni selezionate sono state rimosse Cerca Impostazioni μLauncher Espandi il pannello notifiche @@ -192,6 +197,7 @@ Questa funzione richiede Android 6 o successivi. Ok Rinomina %1$s + Impossibile rimuovere l\'applicazione Dinamico Colore Due dita verso l\'alto diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9a0544f..6a6149c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -45,6 +45,7 @@ Data Hora Selecione um app + Ver todos os apps Instalar aplicativos Loja não encontrada Definir o μLauncher como tela inicial Informações do aplicativo + Seu dispositivo não é compatível com esse recurso. Gerenciar detalhes do app em vez disso? Ver tutorial do launcher Redefinir configuraçãos Você vai descartar todas as suas preferências. Continuar? @@ -96,6 +100,8 @@ Outros Desinstalar Informações do aplicativo + O app selecionado foi removido + Não foi possível remover o app Busque Configurações do µLauncher Todos os apps diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index e6fc115..bfd0cfe 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -105,6 +105,7 @@ Saat Saate tıklayın Uygulama Seçin + Tüm uygulamaları göster Uygulamaları yükle Mağaza bulunamadı Görünüş @@ -119,6 +120,8 @@ Hiçbir şey yapma Kaynak kodunu göster Hatayı bildirin + Seçilen uygulama kaldırıldı + Uygulama kaldırılamadı Uygulamaları Ara Tüm Uygulamalar Favori Uygulamalar @@ -131,8 +134,10 @@ Saniyeleri gösteri Tarih ile zamanı yer değiştir Duvar kağıdı seç + Duvar kağıdını değiştir Ekran Ekranı açık tut + Tam ekran kullan Ekranı döndür İşlevsellik Ekranın köşesinden kaydırın @@ -160,6 +165,7 @@ Metin Izgara Uygulama Detayı + Sizin cihazınız bu özelliği desteklemiyor. Onun yerine uygulama detaylarını düzenleyin? Ayarları Sıfırlayın Tüm tercihlerinizi bir kenara bırakacaksınız. Devam mı? Tek uzay diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 07b411d..793ef9d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -37,17 +37,21 @@ 日期 时间 选择应用 + 浏览全部应用 安装应用 没有找到应用市场 选择一个壁纸 + 换壁纸 保持屏幕常亮 + 使用全屏 功能 边缘滑动动作 零点击启动唯一搜索结果 搜索时呼出键盘 灵敏度 应用信息 + 您的设备不支持此功能。要不打开应用程序详细? 查看启动器教程 重置设置 你将放弃你所有的配置。继续吗? @@ -70,6 +74,8 @@ 应用 卸载 应用信息 + 无法移除应用 + 移除了选定的应用 搜索 启动器设置 全部应用 diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..beab31f --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #000000 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6205281..b94a92b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -101,6 +101,8 @@ Choose App + View all apps + Install apps Store not found @@ -146,6 +148,7 @@ Flip date and time Choose a wallpaper + Change wallpaper Display @@ -237,6 +240,9 @@ Show Rename + Removed the selected application + Unable to remove application + Search Search (no auto launch) @@ -259,6 +265,7 @@ Add Shortcut Bind to gesture + Ok Show in app list