From 077ee4381a7783ff1d044b9cb6cce437eae2f942 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 15:27:26 +0100 Subject: [PATCH] lint --- .../de/jrpie/android/launcher/Application.kt | 11 +++--- .../de/jrpie/android/launcher/Functions.kt | 4 +-- .../LauncherPreferences$Config.java | 2 ++ .../launcher/preferences/legacy/Version1.kt | 2 +- .../launcher/preferences/legacy/Version3.kt | 16 ++++----- .../jrpie/android/launcher/ui/HomeActivity.kt | 15 ++++---- .../launcher/ui/TouchGestureDetector.kt | 34 +++++++++++++++---- .../ui/list/apps/AppsRecyclerAdapter.kt | 2 +- .../ui/list/apps/ContextMenuActions.kt | 3 +- .../ui/list/other/OtherRecyclerAdapter.kt | 2 +- .../ui/settings/meta/SettingsFragmentMeta.kt | 3 +- .../launcher/ui/tutorial/TutorialActivity.kt | 17 +++++++++- 12 files changed, 75 insertions(+), 36 deletions(-) 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 09229ab..e674e4e 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -10,6 +10,8 @@ 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 @@ -108,12 +110,10 @@ class Application : android.app.Application() { // Try to restore old preferences migratePreferencesToNewVersion(this) - // First time opening the app: set defaults and start tutorial + // First time opening the app: set defaults + // The tutorial is started from HomeActivity#onStart, as starting it here is blocked by android if (!LauncherPreferences.internal().started()) { resetPreferences(this) - - LauncherPreferences.internal().started(true) - openTutorial(this) } @@ -134,7 +134,8 @@ class Application : android.app.Application() { it.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) } } - ContextCompat.registerReceiver(this, profileAvailabilityBroadcastReceiver, filter, + ContextCompat.registerReceiver( + this, profileAvailabilityBroadcastReceiver, filter, ContextCompat.RECEIVER_EXPORTED ) } 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 7c2abbf..57f13a5 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -135,9 +135,7 @@ fun openInBrowser(url: String, context: Context) { } fun openTutorial(context: Context) { - context.startActivity(Intent(context, TutorialActivity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - }) + context.startActivity(Intent(context, TutorialActivity::class.java)) } diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java index ca60591..85979fe 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java @@ -21,8 +21,10 @@ import eu.jonahbauer.android.preference.annotations.Preferences; r = R.class, value = { @PreferenceGroup(name = "internal", prefix = "settings_internal_", suffix = "_key", value = { + // set after the user finished the tutorial @Preference(name = "started", type = boolean.class, defaultValue = "false"), @Preference(name = "started_time", type = long.class), + // see PREFERENCE_VERSION in de.jrpie.android.launcher.preferences.Preferences.kt @Preference(name = "version_code", type = int.class, defaultValue = "-1"), }), @PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = { 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 6408b70..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 @@ -100,7 +100,7 @@ private fun migrateAppInfoStringMap(key: String) { } }?.toMap(HashMap()) )?.let { - preferences.edit().putStringSet(key, it as Set).apply() + preferences.edit().putStringSet(key, it).apply() } } diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt index 7698e62..4a9241f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt @@ -11,6 +11,7 @@ import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPre import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import java.util.HashSet +import androidx.core.content.edit /** * Migrate preferences from version 3 (used until version 0.0.23) to the current format @@ -42,6 +43,7 @@ private fun migrateSetAppInfo(key: String, preferences: SharedPreferences, edito deserializeSet(preferences.getStringSet(key, null))?.let { set.addAll(it) } + @Suppress("UNCHECKED_CAST") editor.putStringSet( key, serializer.serialize(set as java.util.Set) as Set? @@ -60,6 +62,7 @@ private fun migrateMapAppInfoString(key: String, preferences: SharedPreferences, deserializeMap(preferences.getStringSet(key, null))?.let { map.putAll(it) } + @Suppress("UNCHECKED_CAST") editor.putStringSet(key, serializer.serialize(map) as Set?) } catch (e: Exception) { e.printStackTrace() @@ -72,14 +75,11 @@ fun migratePreferencesFromVersion3() { assert(LauncherPreferences.internal().versionCode() == 3) val preferences = LauncherPreferences.getSharedPreferences() - val editor = preferences.edit() - migrateSetAppInfo(LauncherPreferences.apps().keys().favorites(), preferences, editor) - migrateSetAppInfo(LauncherPreferences.apps().keys().hidden(), preferences, editor) - migrateMapAppInfoString(LauncherPreferences.apps().keys().customNames(), preferences, editor) - - editor.apply() - - + preferences.edit { + migrateSetAppInfo(LauncherPreferences.apps().keys().favorites(), preferences, this) + migrateSetAppInfo(LauncherPreferences.apps().keys().hidden(), preferences, this) + migrateMapAppInfoString(LauncherPreferences.apps().keys().customNames(), preferences, this) + } LauncherPreferences.internal().versionCode(4) } \ No newline at end of file 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 61a4250..7875473 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 @@ -9,9 +9,6 @@ import android.util.DisplayMetrics import android.view.KeyEvent import android.view.MotionEvent import android.view.View -import android.view.Window -import android.view.WindowInsets -import android.view.WindowInsetsController import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible @@ -20,6 +17,7 @@ import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.databinding.HomeBinding +import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity import java.util.Locale @@ -58,7 +56,6 @@ class HomeActivity : UIObject, AppCompatActivity() { super.onCreate(savedInstanceState) super.onCreate() - val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) @@ -88,8 +85,6 @@ class HomeActivity : UIObject, AppCompatActivity() { binding.buttonFallbackSettings.setOnClickListener { LauncherAction.SETTINGS.invoke(this) } - - } override fun onStart() { @@ -97,6 +92,11 @@ class HomeActivity : UIObject, AppCompatActivity() { super.onStart() + // If the tutorial was not finished, start it + if (!LauncherPreferences.internal().started()) { + openTutorial(this) + } + LauncherPreferences.getSharedPreferences() .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) @@ -220,7 +220,8 @@ class HomeActivity : UIObject, AppCompatActivity() { } override fun onTouchEvent(event: MotionEvent): Boolean { - return touchGestureDetector.onTouchEvent(event) || super.onTouchEvent(event) + touchGestureDetector.onTouchEvent(event) + return true } override fun setOnClicks() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt b/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt index 00629a5..1c05d54 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt @@ -1,6 +1,8 @@ package de.jrpie.android.launcher.ui import android.content.Context +import android.os.Handler +import android.os.Looper import android.view.MotionEvent import android.view.ViewConfiguration import de.jrpie.android.launcher.actions.Gesture @@ -27,6 +29,8 @@ class TouchGestureDetector( private val MIN_TRIANGLE_HEIGHT = 250 + private val longPressHandler = Handler(Looper.getMainLooper()) + data class Vector(val x: Float, val y: Float) { fun absSquared(): Float { @@ -83,16 +87,28 @@ class TouchGestureDetector( } private var paths = HashMap() + private var gestureIsLongClick = false private var lastTappedTime = 0L private var lastTappedLocation: Vector? = null - fun onTouchEvent(event: MotionEvent): Boolean { + fun onTouchEvent(event: MotionEvent) { val pointerIdToIndex = (0.. LONG_PRESS_TIMEOUT) { - // TODO: Don't wait until the finger is lifted. - // Instead set a timer to start long click as soon as LONG_PRESS_TIMEOUT is reached - Gesture.LONG_CLICK.invoke(context) } } else { // detect swipes 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 0c0407e..1f275e4 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 @@ -67,7 +67,7 @@ class AppsRecyclerAdapter( override fun onClick(v: View) { val rect = Rect() img.getGlobalVisibleRect(rect) - selectItem(adapterPosition, rect) + selectItem(bindingAdapterPosition, rect) } init { 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 c1f3406..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 @@ -22,6 +22,7 @@ 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 +import androidx.core.net.toUri private const val LOG_TAG = "AppContextMenu" @@ -44,7 +45,7 @@ fun AbstractAppInfo.uninstall(activity: Activity) { Log.i(LOG_TAG, "uninstalling $this") val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) - intent.data = Uri.parse("package:$packageName") + intent.data = "package:$packageName".toUri() getUserFromId(userId, activity).let { user -> intent.putExtra(Intent.EXTRA_USER, user) } 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 97d1c84..dfba334 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 @@ -33,7 +33,7 @@ class OtherRecyclerAdapter(val activity: Activity) : override fun onClick(v: View) { - val pos = adapterPosition + val pos = bindingAdapterPosition val content = othersList[pos] forGesture?.let { returnChoiceIntent(it, content) } 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 70a225d..4cce930 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 @@ -16,6 +16,7 @@ import de.jrpie.android.launcher.copyToClipboard import de.jrpie.android.launcher.databinding.SettingsMetaBinding import de.jrpie.android.launcher.getDeviceInfo import de.jrpie.android.launcher.openInBrowser +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 @@ -48,7 +49,7 @@ class SettingsFragmentMeta : Fragment(), UIObject { override fun setOnClicks() { binding.settingsMetaButtonViewTutorial.setOnClickListener { - startActivity(Intent(this.context, TutorialActivity::class.java)) + openTutorial(requireContext()) } // prompting for settings-reset confirmation 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 28e2e02..fd60d19 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 @@ -2,7 +2,9 @@ package de.jrpie.android.launcher.ui.tutorial import android.content.Intent import android.content.res.Resources +import android.os.Build import android.os.Bundle +import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager @@ -33,6 +35,19 @@ class TutorialActivity : AppCompatActivity(), UIObject { super.onCreate(savedInstanceState) super.onCreate() + // Handle back key / gesture on Android 13+ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + onBackInvokedDispatcher.registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_OVERLAY + ) { + // prevent going back when the tutorial is shown for the first time + if (!LauncherPreferences.internal().started()) { + return@registerOnBackInvokedCallback + } + finish() + } + } + // Initialise layout setContentView(R.layout.tutorial) @@ -60,7 +75,7 @@ class TutorialActivity : AppCompatActivity(), UIObject { } } - // Default: prevent going back, allow if viewed again later + // prevent going back when the tutorial is shown for the first time override fun onBackPressed() { if (LauncherPreferences.internal().started()) super.onBackPressed()