diff --git a/app/build.gradle b/app/build.gradle index eaf97f7..1a0a6fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -106,7 +106,6 @@ dependencies { 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 'androidx.activity:activity:1.10.1' annotationProcessor "eu.jonahbauer:android-preference-annotations:1.1.2" annotationProcessor "com.android.databinding:compiler:$android_plugin_version" testImplementation 'junit:junit:4.13.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a1d5a0..a5f8831 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,6 @@ tools:ignore="QueryAllPackagesPermission" /> - - - - - - \ No newline at end of file + 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 775621c..e6cce23 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -12,8 +12,6 @@ import android.os.Build.VERSION_CODES import android.os.UserHandle import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData -import android.appwidget.AppWidgetHost -import android.appwidget.AppWidgetManager import androidx.preference.PreferenceManager import de.jrpie.android.launcher.actions.TorchManager import de.jrpie.android.launcher.apps.AbstractAppInfo @@ -22,22 +20,13 @@ 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 de.jrpie.android.launcher.widgets.LauncherWidgetProvider -import de.jrpie.android.launcher.widgets.Widget import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch - -const val APP_WIDGET_HOST_ID = 42; - - class Application : android.app.Application() { val apps = MutableLiveData>() - val widgets = MutableLiveData>() val privateSpaceLocked = MutableLiveData() - lateinit var appWidgetHost: AppWidgetHost - lateinit var appWidgetManager: AppWidgetManager private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { @@ -101,8 +90,6 @@ class Application : android.app.Application() { customAppNames = LauncherPreferences.apps().customNames() } else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) { loadApps() - } else if (pref == LauncherPreferences.widgets().keys().widgets()) { - widgets.postValue(LauncherPreferences.widgets().widgets() ?: setOf()) } } @@ -116,15 +103,10 @@ class Application : android.app.Application() { torchManager = TorchManager(this) } - appWidgetHost = AppWidgetHost(this.applicationContext, APP_WIDGET_HOST_ID) - appWidgetManager = AppWidgetManager.getInstance(this.applicationContext) - - appWidgetHost.startListening() - - val preferences = PreferenceManager.getDefaultSharedPreferences(this) LauncherPreferences.init(preferences, this.resources) + // Try to restore old preferences migratePreferencesToNewVersion(this) @@ -175,10 +157,4 @@ class Application : android.app.Application() { apps.postValue(getApps(packageManager, applicationContext)) } } - - override fun onTerminate() { - appWidgetHost.stopListening() - super.onTerminate() - - } } 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 9679ae5..afc2c31 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -6,9 +6,6 @@ import android.app.role.RoleManager import android.content.ActivityNotFoundException import android.content.ClipData import android.content.ClipboardManager -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProvider -import android.appwidget.AppWidgetProviderInfo import android.content.Context import android.content.Intent import android.content.pm.LauncherApps @@ -226,4 +223,4 @@ fun copyToClipboard(context: Context, text: String) { val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipData = ClipData.newPlainText("Debug Info", text) clipboardManager.setPrimaryClip(clipData) -} +} \ No newline at end of file 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 a883922..9a2dc62 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 @@ -6,18 +6,14 @@ import android.content.SharedPreferences.Editor import android.graphics.Rect import android.graphics.drawable.Drawable import android.widget.Toast -import androidx.core.content.edit import de.jrpie.android.launcher.R 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 -/** - * Represents an action that can be bound to a [Gesture]. - * There are four types of actions: [AppAction], [ShortcutAction], [LauncherAction] and [WidgetPanelAction] - */ @Serializable sealed interface Action { fun invoke(context: Context, rect: Rect? = null): Boolean @@ -25,10 +21,6 @@ sealed interface Action { fun getIcon(context: Context): Drawable? fun isAvailable(context: Context): Boolean - fun showConfigurationDialog(context: Context, onSuccess: (Action) -> Unit) { - onSuccess(this) - } - // Can the action be used to reach µLauncher settings? fun canReachSettings(): Boolean diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/WidgetPanelAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/WidgetPanelAction.kt deleted file mode 100644 index d7829a6..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/actions/WidgetPanelAction.kt +++ /dev/null @@ -1,83 +0,0 @@ -package de.jrpie.android.launcher.actions - -import android.content.Context -import android.content.Intent -import android.graphics.Rect -import android.graphics.drawable.Drawable -import android.view.View -import android.widget.TextView -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.core.content.res.ResourcesCompat -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.ui.widgets.WidgetPanelActivity -import de.jrpie.android.launcher.ui.widgets.manage.EXTRA_PANEL_ID -import de.jrpie.android.launcher.ui.widgets.manage.WidgetPanelsRecyclerAdapter -import de.jrpie.android.launcher.widgets.WidgetPanel -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -@SerialName("action:panel") -class WidgetPanelAction(val widgetPanelId: Int) : Action { - - override fun invoke(context: Context, rect: Rect?): Boolean { - - if (WidgetPanel.byId(widgetPanelId) == null) { - Toast.makeText(context, R.string.alert_widget_panel_not_found, Toast.LENGTH_LONG).show() - } else { - context.startActivity(Intent(context, WidgetPanelActivity::class.java).also { - it.putExtra(EXTRA_PANEL_ID, widgetPanelId) - }) - } - return true - } - - override fun label(context: Context): String { - return WidgetPanel.byId(widgetPanelId)?.label - ?: context.getString(R.string.list_other_open_widget_panel) - } - - override fun isAvailable(context: Context): Boolean { - return true - } - - override fun canReachSettings(): Boolean { - return false - } - - override fun getIcon(context: Context): Drawable? { - return ResourcesCompat.getDrawable( - context.resources, - R.drawable.baseline_widgets_24, - context.theme - ) - } - - override fun showConfigurationDialog(context: Context, onSuccess: (Action) -> Unit) { - AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { - setTitle(R.string.dialog_select_widget_panel_title) - setNegativeButton(R.string.dialog_cancel) { _, _ -> } - setView(R.layout.dialog_select_widget_panel) - }.create().also { it.show() }.also { alertDialog -> - val infoTextView = - alertDialog.findViewById(R.id.dialog_select_widget_panel_info) - alertDialog.findViewById(R.id.dialog_select_widget_panel_recycler) - ?.apply { - setHasFixedSize(true) - layoutManager = LinearLayoutManager(alertDialog.context) - adapter = - WidgetPanelsRecyclerAdapter(alertDialog.context, false) { widgetPanel -> - onSuccess(WidgetPanelAction(widgetPanel.id)) - alertDialog.dismiss() - } - if (adapter?.itemCount == 0) { - infoTextView?.visibility = View.VISIBLE - } - } - } - true - } -} 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 d509ef2..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 @@ -8,8 +8,6 @@ import de.jrpie.android.launcher.actions.lock.LockMethod; import de.jrpie.android.launcher.preferences.serialization.MapAbstractAppInfoStringPreferenceSerializer; import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPreferenceSerializer; import de.jrpie.android.launcher.preferences.serialization.SetPinnedShortcutInfoPreferenceSerializer; -import de.jrpie.android.launcher.preferences.serialization.SetWidgetPanelSerializer; -import de.jrpie.android.launcher.preferences.serialization.SetWidgetSerializer; import de.jrpie.android.launcher.preferences.theme.Background; import de.jrpie.android.launcher.preferences.theme.ColorTheme; import de.jrpie.android.launcher.preferences.theme.Font; @@ -74,7 +72,6 @@ import eu.jonahbauer.android.preference.annotations.Preferences; @Preference(name = "search_auto_launch", type = boolean.class, defaultValue = "true"), @Preference(name = "search_web", type = boolean.class, description = "false"), @Preference(name = "search_auto_open_keyboard", type = boolean.class, defaultValue = "true"), - @Preference(name = "search_auto_close_keyboard", type = boolean.class, defaultValue = "false"), }), @PreferenceGroup(name = "enabled_gestures", prefix = "settings_enabled_gestures_", suffix = "_key", value = { @Preference(name = "double_swipe", type = boolean.class, defaultValue = "true"), @@ -84,9 +81,5 @@ import eu.jonahbauer.android.preference.annotations.Preferences; @PreferenceGroup(name = "actions", prefix = "settings_actions_", suffix = "_key", value = { @Preference(name = "lock_method", type = LockMethod.class, defaultValue = "DEVICE_ADMIN"), }), - @PreferenceGroup(name = "widgets", prefix = "settings_widgets_", suffix= "_key", value = { - @Preference(name = "widgets", type = Set.class, serializer = SetWidgetSerializer.class), - @Preference(name = "custom_panels", type = Set.class, serializer = SetWidgetPanelSerializer.class) - }), }) public final class LauncherPreferences$Config {} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt index e8e717e..59ecc7a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt @@ -2,29 +2,23 @@ package de.jrpie.android.launcher.preferences import android.content.Context import android.util.Log -import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.BuildConfig import de.jrpie.android.launcher.actions.Action +import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.AbstractAppInfo import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER -import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1 import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion2 import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion3 -import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion4 import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersionUnknown import de.jrpie.android.launcher.ui.HomeActivity -import de.jrpie.android.launcher.widgets.ClockWidget -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition -import de.jrpie.android.launcher.widgets.deleteAllWidgets /* Current version of the structure of preferences. * Increase when breaking changes are introduced and write an appropriate case in * `migratePreferencesToNewVersion` */ -const val PREFERENCE_VERSION = 5 +const val PREFERENCE_VERSION = 4 const val UNKNOWN_PREFERENCE_VERSION = -1 private const val TAG = "Launcher - Preferences" @@ -46,23 +40,18 @@ fun migratePreferencesToNewVersion(context: Context) { } 1 -> { - migratePreferencesFromVersion1(context) + migratePreferencesFromVersion1() Log.i(TAG, "migration of preferences complete (1 -> ${PREFERENCE_VERSION}).") } 2 -> { - migratePreferencesFromVersion2(context) + migratePreferencesFromVersion2() Log.i(TAG, "migration of preferences complete (2 -> ${PREFERENCE_VERSION}).") } 3 -> { - migratePreferencesFromVersion3(context) + migratePreferencesFromVersion3() Log.i(TAG, "migration of preferences complete (3 -> ${PREFERENCE_VERSION}).") } - 4 -> { - migratePreferencesFromVersion4(context) - Log.i(TAG, "migration of preferences complete (4 -> ${PREFERENCE_VERSION}).") - } - else -> { Log.w( TAG, @@ -82,17 +71,6 @@ fun resetPreferences(context: Context) { Log.i(TAG, "Resetting preferences") LauncherPreferences.clear() LauncherPreferences.internal().versionCode(PREFERENCE_VERSION) - deleteAllWidgets(context) - - LauncherPreferences.widgets().widgets( - setOf( - ClockWidget( - (context.applicationContext as Application).appWidgetHost.allocateAppWidgetId(), - WidgetPosition(1, 3, 10, 4), - WidgetPanel.HOME.id - ) - ) - ) val hidden: MutableSet = mutableSetOf() 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 6cd9819..a1cb022 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 @@ -1,13 +1,11 @@ package de.jrpie.android.launcher.preferences.legacy -import android.content.Context -import androidx.core.content.edit 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.AbstractAppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.apps.AppInfo +import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION import kotlinx.serialization.Serializable @@ -15,6 +13,7 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.json.JSONException import org.json.JSONObject +import androidx.core.content.edit @Serializable @@ -130,7 +129,7 @@ private fun migrateAction(key: String) { * Migrate preferences from version 1 (used until version j-0.0.18) to the current format * (see [PREFERENCE_VERSION]) */ -fun migratePreferencesFromVersion1(context: Context) { +fun migratePreferencesFromVersion1() { assert(LauncherPreferences.internal().versionCode() == 1) Gesture.entries.forEach { g -> migrateAction(g.id) } migrateAppInfoSet(LauncherPreferences.apps().keys().hidden()) @@ -138,5 +137,5 @@ fun migratePreferencesFromVersion1(context: Context) { migrateAppInfoStringMap(LauncherPreferences.apps().keys().customNames()) LauncherPreferences.internal().versionCode(2) - migratePreferencesFromVersion2(context) + migratePreferencesFromVersion2() } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt index 9714359..4e6eae1 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version2.kt @@ -1,6 +1,5 @@ package de.jrpie.android.launcher.preferences.legacy -import android.content.Context import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction @@ -12,10 +11,10 @@ import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION * Migrate preferences from version 2 (used until version 0.0.21) to the current format * (see [PREFERENCE_VERSION]) */ -fun migratePreferencesFromVersion2(context: Context) { +fun migratePreferencesFromVersion2() { assert(LauncherPreferences.internal().versionCode() == 2) // previously there was no setting for this Action.setActionForGesture(Gesture.BACK, LauncherAction.CHOOSE) LauncherPreferences.internal().versionCode(3) - migratePreferencesFromVersion3(context) + migratePreferencesFromVersion3() } \ No newline at end of file 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 e0a8447..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 @@ -1,17 +1,17 @@ package de.jrpie.android.launcher.preferences.legacy -import android.content.Context import android.content.SharedPreferences import android.content.SharedPreferences.Editor -import androidx.core.content.edit -import de.jrpie.android.launcher.apps.AbstractAppInfo import de.jrpie.android.launcher.apps.AppInfo +import de.jrpie.android.launcher.apps.AbstractAppInfo import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION import de.jrpie.android.launcher.preferences.serialization.MapAbstractAppInfoStringPreferenceSerializer import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPreferenceSerializer 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 @@ -70,7 +70,8 @@ private fun migrateMapAppInfoString(key: String, preferences: SharedPreferences, } } -fun migratePreferencesFromVersion3(context: Context) { +fun migratePreferencesFromVersion3() { + assert(PREFERENCE_VERSION == 4) assert(LauncherPreferences.internal().versionCode() == 3) val preferences = LauncherPreferences.getSharedPreferences() @@ -81,5 +82,4 @@ fun migratePreferencesFromVersion3(context: Context) { } LauncherPreferences.internal().versionCode(4) - migratePreferencesFromVersion4(context) } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt deleted file mode 100644 index d4c7441..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt +++ /dev/null @@ -1,27 +0,0 @@ -package de.jrpie.android.launcher.preferences.legacy - -import android.content.Context -import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.preferences.LauncherPreferences -import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION -import de.jrpie.android.launcher.widgets.ClockWidget -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition - -fun migratePreferencesFromVersion4(context: Context) { - assert(PREFERENCE_VERSION == 5) - assert(LauncherPreferences.internal().versionCode() == 4) - - LauncherPreferences.widgets().widgets( - setOf( - ClockWidget( - (context.applicationContext as Application).appWidgetHost.allocateAppWidgetId(), - WidgetPosition(1, 3, 10, 4), - WidgetPanel.HOME.id - ) - ) - ) - - - LauncherPreferences.internal().versionCode(5) -} \ No newline at end of file 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 f954b31..2d1152d 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 @@ -3,10 +3,10 @@ package de.jrpie.android.launcher.preferences.legacy import android.content.Context import android.content.SharedPreferences import android.util.Log -import androidx.core.content.edit 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( @@ -392,5 +392,5 @@ fun migratePreferencesFromVersionUnknown(context: Context) { LauncherPreferences.internal().versionCode(1) Log.i(TAG, "migrated preferences to version 1.") - migratePreferencesFromVersion1(context) + migratePreferencesFromVersion1() } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt index 7b5d794..3e19daf 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt @@ -4,8 +4,6 @@ package de.jrpie.android.launcher.preferences.serialization import de.jrpie.android.launcher.apps.AbstractAppInfo import de.jrpie.android.launcher.apps.PinnedShortcutInfo -import de.jrpie.android.launcher.widgets.Widget -import de.jrpie.android.launcher.widgets.WidgetPanel import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializationException import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSerializer import kotlinx.serialization.Serializable @@ -30,40 +28,6 @@ class SetAbstractAppInfoPreferenceSerializer : } } - -@Suppress("UNCHECKED_CAST") -class SetWidgetSerializer : - PreferenceSerializer?, java.util.Set?> { - @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.Set?): java.util.Set? { - return value?.map(Widget::serialize) - ?.toHashSet() as? java.util.Set - } - - @Throws(PreferenceSerializationException::class) - override fun deserialize(value: java.util.Set?): java.util.Set? { - return value?.map(java.lang.String::toString)?.map(Widget::deserialize) - ?.toHashSet() as? java.util.Set - } -} - -@Suppress("UNCHECKED_CAST") -class SetWidgetPanelSerializer : - PreferenceSerializer?, java.util.Set?> { - @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.Set?): java.util.Set? { - return value?.map(WidgetPanel::serialize) - ?.toHashSet() as? java.util.Set - } - - @Throws(PreferenceSerializationException::class) - override fun deserialize(value: java.util.Set?): java.util.Set? { - return value?.map(java.lang.String::toString)?.map(WidgetPanel::deserialize) - ?.toHashSet() as? java.util.Set - } -} - - @Suppress("UNCHECKED_CAST") class SetPinnedShortcutInfoPreferenceSerializer : PreferenceSerializer?, java.util.Set?> { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt b/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt index a863c67..1ca4d2b 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt @@ -1,6 +1,5 @@ package de.jrpie.android.launcher.ui -import android.app.Activity import android.content.Context import android.graphics.ColorMatrix import android.graphics.ColorMatrixColorFilter @@ -39,17 +38,10 @@ fun ImageView.transformGrayscale(grayscale: Boolean) { } -// Taken from https://stackoverflow.com/a/50743764 +// Taken from https://stackoverflow.com/a/50743764/12787264 fun View.openSoftKeyboard(context: Context) { this.requestFocus() - (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) - .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) + // open the soft keyboard + val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT) } - -// https://stackoverflow.com/a/17789187 -fun closeSoftKeyboard(activity: Activity) { - activity.currentFocus?.let { focus -> - (activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) - .hideSoftInputFromWindow( focus.windowToken, 0 ) - } -} \ 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 192a8e9..53a0876 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 @@ -1,7 +1,6 @@ package de.jrpie.android.launcher.ui import android.annotation.SuppressLint -import android.app.Activity import android.content.SharedPreferences import android.content.res.Configuration import android.content.res.Resources @@ -11,7 +10,8 @@ import android.view.KeyEvent import android.view.MotionEvent import android.view.View import android.window.OnBackInvokedDispatcher -import de.jrpie.android.launcher.Application +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.isVisible import de.jrpie.android.launcher.R import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture @@ -20,6 +20,7 @@ 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 /** * [HomeActivity] is the actual application Launcher, @@ -33,10 +34,10 @@ import de.jrpie.android.launcher.ui.tutorial.TutorialActivity * - Setting global variables (preferences etc.) * - Opening the [TutorialActivity] on new installations */ -class HomeActivity : UIObject, Activity() { +class HomeActivity : UIObject, AppCompatActivity() { private lateinit var binding: HomeBinding - private var touchGestureDetector: TouchGestureDetector? = null + private lateinit var touchGestureDetector: TouchGestureDetector private var sharedPreferencesListener = SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> @@ -44,26 +45,40 @@ class HomeActivity : UIObject, Activity() { prefKey?.startsWith("display.") == true ) { recreate() - } else if (prefKey?.startsWith("action.") == true) { - updateSettingsFallbackButtonVisibility() - } else if (prefKey == LauncherPreferences.widgets().keys().widgets()) { - binding.homeWidgetContainer.updateWidgets(this@HomeActivity, - LauncherPreferences.widgets().widgets() - ) } + if (prefKey?.startsWith("action.") == true) { + updateSettingsFallbackButtonVisibility() + } } override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + super.onCreate(savedInstanceState) super.onCreate() + touchGestureDetector = TouchGestureDetector( + this, 0, 0, + LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f + ) + touchGestureDetector.updateScreenSize(windowManager) // Initialise layout binding = HomeBinding.inflate(layoutInflater) setContentView(binding.root) + 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) + + windowInsets + } + } + + + // Handle back key / gesture on Android 13+, cf. onKeyDown() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { onBackInvokedDispatcher.registerOnBackInvokedCallback( @@ -79,11 +94,12 @@ class HomeActivity : UIObject, Activity() { override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - touchGestureDetector?.updateScreenSize(windowManager) + touchGestureDetector.updateScreenSize(windowManager) } override fun onStart() { - super.onStart() + super.onStart() + super.onStart() // If the tutorial was not finished, start it @@ -94,15 +110,6 @@ class HomeActivity : UIObject, Activity() { LauncherPreferences.getSharedPreferences() .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) - (application as Application).appWidgetHost.startListening() - - } - - - - override fun onStop() { - (application as Application).appWidgetHost.stopListening() - super.onStop() } override fun onWindowFocusChanged(hasFocus: Boolean) { @@ -128,6 +135,44 @@ class HomeActivity : UIObject, Activity() { } } + private fun initClock() { + val locale = Locale.getDefault() + val dateVisible = LauncherPreferences.clock().dateVisible() + val timeVisible = LauncherPreferences.clock().timeVisible() + + var dateFMT = "yyyy-MM-dd" + var timeFMT = "HH:mm" + if (LauncherPreferences.clock().showSeconds()) { + timeFMT += ":ss" + } + + if (LauncherPreferences.clock().localized()) { + dateFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, dateFMT) + timeFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, timeFMT) + } + + var upperFormat = dateFMT + var lowerFormat = timeFMT + var upperVisible = dateVisible + var lowerVisible = timeVisible + + if (LauncherPreferences.clock().flipDateTime()) { + upperFormat = lowerFormat.also { lowerFormat = upperFormat } + upperVisible = lowerVisible.also { lowerVisible = upperVisible } + } + + binding.homeUpperView.isVisible = upperVisible + binding.homeLowerView.isVisible = lowerVisible + + binding.homeUpperView.setTextColor(LauncherPreferences.clock().color()) + binding.homeLowerView.setTextColor(LauncherPreferences.clock().color()) + + binding.homeLowerView.format24Hour = lowerFormat + binding.homeUpperView.format24Hour = upperFormat + binding.homeLowerView.format12Hour = lowerFormat + binding.homeUpperView.format12Hour = upperFormat + } + override fun getTheme(): Resources.Theme { val mTheme = modifyTheme(super.getTheme()) mTheme.applyStyle(R.style.backgroundWallpaper, true) @@ -143,33 +188,11 @@ class HomeActivity : UIObject, Activity() { override fun onResume() { super.onResume() - /* This should be initialized in onCreate() - However on some devices there seems to be a bug where the touchGestureDetector - is not working properly after resuming the app. - Reinitializing the touchGestureDetector every time the app is resumed might help to fix that. - (see issue #138) - */ - touchGestureDetector = TouchGestureDetector( - this, 0, 0, + touchGestureDetector.edgeWidth = LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f - ).also { - it.updateScreenSize(windowManager) - } - 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) - - windowInsets - } - } + initClock() updateSettingsFallbackButtonVisibility() - - binding.homeWidgetContainer.updateWidgets(this@HomeActivity, - LauncherPreferences.widgets().widgets() - ) } override fun onDestroy() { @@ -207,10 +230,30 @@ class HomeActivity : UIObject, Activity() { } override fun onTouchEvent(event: MotionEvent): Boolean { - touchGestureDetector?.onTouchEvent(event) + touchGestureDetector.onTouchEvent(event) return true } + override fun setOnClicks() { + + binding.homeUpperView.setOnClickListener { + if (LauncherPreferences.clock().flipDateTime()) { + Gesture.TIME(this) + } else { + Gesture.DATE(this) + } + } + + binding.homeLowerView.setOnClickListener { + if (LauncherPreferences.clock().flipDateTime()) { + Gesture.DATE(this) + } else { + Gesture.TIME(this) + } + } + } + + private fun handleBack() { Gesture.BACK(this) } 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 3dbdda8..71908ba 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 @@ -49,21 +49,7 @@ class PinShortcutActivity : AppCompatActivity(), UIObject { val request = launcherApps.getPinItemRequest(intent) this.request = request - if (request == null) { - finish() - return - } - - if (request.requestType == PinItemRequest.REQUEST_TYPE_APPWIDGET) { - - // TODO - request.getAppWidgetProviderInfo(this) - // startActivity() - finish() - return - } - - if (request.requestType != PinItemRequest.REQUEST_TYPE_SHORTCUT) { + if (request == null || request.requestType != PinItemRequest.REQUEST_TYPE_SHORTCUT) { finish() return } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt index a8e59ba..1a55bbb 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt @@ -11,16 +11,13 @@ import android.widget.Toast import androidx.fragment.app.Fragment import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.R import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.databinding.ListAppsBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.ui.closeSoftKeyboard import de.jrpie.android.launcher.ui.list.ListActivity import de.jrpie.android.launcher.ui.openSoftKeyboard -import kotlin.math.absoluteValue /** @@ -93,20 +90,6 @@ class ListFragmentApps : Fragment(), UIObject { } } adapter = appsRecyclerAdapter - if (LauncherPreferences.functionality().searchAutoCloseKeyboard()) { - addOnScrollListener(object : RecyclerView.OnScrollListener() { - var totalDy: Int = 0 - var threshold = (resources.displayMetrics.density * 100).toInt() - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - totalDy += dy - - if (totalDy.absoluteValue > 100) { - totalDy = 0 - closeSoftKeyboard(requireActivity()) - } - } - }) - } } binding.listAppsSearchview.setOnQueryTextListener(object : 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 06be78a..f176469 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 @@ -11,7 +11,6 @@ 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.actions.LauncherAction -import de.jrpie.android.launcher.actions.WidgetPanelAction import de.jrpie.android.launcher.ui.list.ListActivity /** @@ -24,10 +23,8 @@ import de.jrpie.android.launcher.ui.list.ListActivity class OtherRecyclerAdapter(val activity: Activity) : RecyclerView.Adapter() { - private val othersList: Array = - LauncherAction.entries.filter { it.isAvailable(activity) } - .plus(WidgetPanelAction(-1)) - .toTypedArray() + private val othersList: Array = + LauncherAction.entries.filter { it.isAvailable(activity) }.toTypedArray() inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener { @@ -39,12 +36,10 @@ 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 - content.showConfigurationDialog(activity) { configuredAction -> - Action.setActionForGesture(gesture, configuredAction) - activity.finish() - } + Action.setActionForGesture(gesture, content) } init { @@ -53,11 +48,11 @@ class OtherRecyclerAdapter(val activity: Activity) : } override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { - val otherLabel = othersList[i].label(activity) - val icon = othersList[i].getIcon(activity) + val otherLabel = activity.getString(othersList[i].label) + val icon = othersList[i].icon viewHolder.textView.text = otherLabel - viewHolder.iconView.setImageDrawable(icon) + viewHolder.iconView.setImageResource(icon) } override fun getItemCount(): Int { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt index bb9df74..a8efb43 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/launcher/SettingsFragmentLauncher.kt @@ -11,8 +11,6 @@ import de.jrpie.android.launcher.actions.openAppsList import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.theme.ColorTheme import de.jrpie.android.launcher.setDefaultHomeScreen -import de.jrpie.android.launcher.ui.widgets.manage.ManageWidgetPanelsActivity -import de.jrpie.android.launcher.ui.widgets.manage.ManageWidgetsActivity /** @@ -83,22 +81,6 @@ class SettingsFragmentLauncher : PreferenceFragmentCompat() { true } - val manageWidgets = findPreference( - LauncherPreferences.widgets().keys().widgets() - ) - manageWidgets?.setOnPreferenceClickListener { - startActivity(Intent(requireActivity(), ManageWidgetsActivity::class.java)) - true - } - - val manageWidgetPanels = findPreference( - LauncherPreferences.widgets().keys().customPanels() - ) - manageWidgetPanels?.setOnPreferenceClickListener { - startActivity(Intent(requireActivity(), ManageWidgetPanelsActivity::class.java)) - true - } - val hiddenApps = findPreference( LauncherPreferences.apps().keys().hidden() ) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt deleted file mode 100644 index 33c4888..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/ClockView.kt +++ /dev/null @@ -1,80 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.isVisible -import de.jrpie.android.launcher.actions.Gesture -import de.jrpie.android.launcher.databinding.ClockBinding -import de.jrpie.android.launcher.preferences.LauncherPreferences -import java.util.Locale - -class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int): ConstraintLayout(context, attrs) { - - val binding: ClockBinding = ClockBinding.inflate(LayoutInflater.from(context), this, true) - init { - initClock() - setOnClicks() - } - - - private fun initClock() { - val locale = Locale.getDefault() - val dateVisible = LauncherPreferences.clock().dateVisible() - val timeVisible = LauncherPreferences.clock().timeVisible() - - var dateFMT = "yyyy-MM-dd" - var timeFMT = "HH:mm" - if (LauncherPreferences.clock().showSeconds()) { - timeFMT += ":ss" - } - - if (LauncherPreferences.clock().localized()) { - dateFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, dateFMT) - timeFMT = android.text.format.DateFormat.getBestDateTimePattern(locale, timeFMT) - } - - var upperFormat = dateFMT - var lowerFormat = timeFMT - var upperVisible = dateVisible - var lowerVisible = timeVisible - - if (LauncherPreferences.clock().flipDateTime()) { - upperFormat = lowerFormat.also { lowerFormat = upperFormat } - upperVisible = lowerVisible.also { lowerVisible = upperVisible } - } - - binding.clockUpperView.isVisible = upperVisible - binding.clockLowerView.isVisible = lowerVisible - - binding.clockUpperView.setTextColor(LauncherPreferences.clock().color()) - binding.clockLowerView.setTextColor(LauncherPreferences.clock().color()) - - binding.clockLowerView.format24Hour = lowerFormat - binding.clockUpperView.format24Hour = upperFormat - binding.clockLowerView.format12Hour = lowerFormat - binding.clockUpperView.format12Hour = upperFormat - } - - fun setOnClicks() { - binding.clockUpperView.setOnClickListener { - if (LauncherPreferences.clock().flipDateTime()) { - Gesture.TIME(context) - } else { - Gesture.DATE(context) - } - } - - binding.clockLowerView.setOnClickListener { - if (LauncherPreferences.clock().flipDateTime()) { - Gesture.DATE(context) - } else { - Gesture.TIME(context) - } - } - } - - - -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetContainerView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetContainerView.kt deleted file mode 100644 index d071771..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetContainerView.kt +++ /dev/null @@ -1,144 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets - -import android.app.Activity -import android.content.Context -import android.graphics.PointF -import android.graphics.RectF -import android.util.AttributeSet -import android.util.Log -import android.view.MotionEvent -import android.view.View -import android.view.View.MeasureSpec.makeMeasureSpec -import android.view.ViewGroup -import androidx.core.graphics.contains -import androidx.core.view.size -import de.jrpie.android.launcher.widgets.Widget -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition -import kotlin.math.max - - -/** - * This only works in an Activity, not AppCompatActivity - */ -open class WidgetContainerView( - var widgetPanelId: Int, - context: Context, - attrs: AttributeSet? = null -) : ViewGroup(context, attrs) { - constructor(context: Context, attrs: AttributeSet) : this(WidgetPanel.HOME.id, context, attrs) - - var widgetViewById = HashMap() - - open fun updateWidgets(activity: Activity, widgets: Collection?) { - synchronized(widgetViewById) { - if (widgets == null) { - return - } - Log.i("WidgetContainer", "updating ${activity.localClassName}") - widgetViewById.forEach { removeView(it.value) } - widgetViewById.clear() - widgets.filter { it.panelId == widgetPanelId }.forEach { widget -> - widget.createView(activity)?.let { - addView(it, LayoutParams(widget.position)) - widgetViewById.put(widget.id, it) - } - } - } - } - - override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { - if (ev == null) { - return false - } - val position = PointF(ev.x, ev.y) - - return widgetViewById.filter { - RectF( - it.value.x, - it.value.y, - it.value.x + it.value.width, - it.value.y + it.value.height - ).contains(position) == true - }.any { - Widget.byId(context, it.key)?.allowInteraction == false - } - } - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - - var maxHeight = suggestedMinimumHeight - var maxWidth = suggestedMinimumWidth - - val mWidth = MeasureSpec.getSize(widthMeasureSpec) - val mHeight = MeasureSpec.getSize(heightMeasureSpec) - - (0...onCreate(savedInstanceState) - super.onCreate() - widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.Companion.HOME.id) - val binding = ActivityWidgetPanelBinding.inflate(layoutInflater) - setContentView(binding.root) - binding.widgetPanelWidgetContainer.widgetPanelId = widgetPanelId - binding.widgetPanelWidgetContainer.updateWidgets( - this, - LauncherPreferences.widgets().widgets() - ) - } - - override fun getTheme(): Resources.Theme { - val mTheme = modifyTheme(super.getTheme()) - mTheme.applyStyle(R.style.backgroundWallpaper, true) - LauncherPreferences.clock().font().applyToTheme(mTheme) - LauncherPreferences.theme().colorTheme().applyToTheme( - mTheme, - LauncherPreferences.theme().textShadow() - ) - - return mTheme - } - - - override fun onStart() { - super.onStart() - super.onStart() - } - - override fun isHomeScreen(): Boolean { - return true - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt deleted file mode 100644 index b18852f..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetPanelsActivity.kt +++ /dev/null @@ -1,104 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.annotation.SuppressLint -import android.content.Intent -import android.content.SharedPreferences -import android.content.res.Resources -import android.os.Bundle -import android.widget.EditText -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.recyclerview.widget.LinearLayoutManager -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.databinding.ActivityManageWidgetPanelsBinding -import de.jrpie.android.launcher.preferences.LauncherPreferences -import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.updateWidgetPanel - -class ManageWidgetPanelsActivity : AppCompatActivity(), UIObject { - - private val sharedPreferencesListener = - SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> - if (prefKey == LauncherPreferences.widgets().keys().customPanels()) { - viewAdapter.widgetPanels = - (LauncherPreferences.widgets().customPanels() ?: setOf()).toTypedArray() - - @SuppressLint("NotifyDataSetChanged") - viewAdapter.notifyDataSetChanged() - } - } - private lateinit var binding: ActivityManageWidgetPanelsBinding - private lateinit var viewAdapter: WidgetPanelsRecyclerAdapter - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - super.onCreate() - - binding = ActivityManageWidgetPanelsBinding.inflate(layoutInflater) - setContentView(binding.main) - - val viewManager = LinearLayoutManager(this) - viewAdapter = WidgetPanelsRecyclerAdapter(this, true) { widgetPanel -> - startActivity( - Intent( - this@ManageWidgetPanelsActivity, - ManageWidgetsActivity::class.java - ).also { - it.putExtra(EXTRA_PANEL_ID, widgetPanel.id) - }) - } - binding.manageWidgetPanelsRecycler.apply { - // improve performance (since content changes don't change the layout size) - setHasFixedSize(true) - layoutManager = viewManager - adapter = viewAdapter - } - binding.manageWidgetPanelsClose.setOnClickListener { finish() } - binding.manageWidgetPanelsAddPanel.setOnClickListener { - AlertDialog.Builder(this@ManageWidgetPanelsActivity, R.style.AlertDialogCustom).apply { - setTitle(R.string.dialog_create_widget_panel_title) - setNegativeButton(R.string.dialog_cancel) { _, _ -> } - setPositiveButton(R.string.dialog_ok) { dialogInterface, _ -> - val panelId = WidgetPanel.allocateId() - val label = (dialogInterface as? AlertDialog) - ?.findViewById(R.id.dialog_create_widget_panel_edit_text)?.text?.toString() - ?: (getString(R.string.widget_panel_default_name, panelId)) - - updateWidgetPanel(WidgetPanel(panelId, label)) - } - setView(R.layout.dialog_create_widget_panel) - }.create().also { it.show() }.apply { - findViewById(R.id.dialog_create_widget_panel_edit_text) - ?.setText( - getString( - R.string.widget_panel_default_name, - WidgetPanel.allocateId() - ) - ) - } - true - } - } - - override fun onStart() { - super.onStart() - super.onStart() - LauncherPreferences.getSharedPreferences() - .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) - } - - override fun onPause() { - LauncherPreferences.getSharedPreferences() - .unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener) - super.onPause() - } - - override fun getTheme(): Resources.Theme { - return modifyTheme(super.getTheme()) - } - - override fun setOnClicks() { - binding.manageWidgetPanelsClose.setOnClickListener { finish() } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt deleted file mode 100644 index d191b70..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt +++ /dev/null @@ -1,185 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.app.Activity -import android.appwidget.AppWidgetManager -import android.content.Intent -import android.content.SharedPreferences -import android.content.res.Resources -import android.graphics.Rect -import android.os.Bundle -import android.util.Log -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.google.android.material.floatingactionbutton.FloatingActionButton -import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.preferences.LauncherPreferences -import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.ui.widgets.WidgetContainerView -import de.jrpie.android.launcher.widgets.AppWidget -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition -import kotlin.math.min - - -// http://coderender.blogspot.com/2012/01/hosting-android-widgets-my.html - -const val REQUEST_CREATE_APPWIDGET = 1 -const val REQUEST_PICK_APPWIDGET = 2 - -const val EXTRA_PANEL_ID = "widgetPanelId" - -// We can't use AppCompatActivity, since some AppWidgets don't work there. -class ManageWidgetsActivity : Activity(), UIObject { - - var panelId: Int = WidgetPanel.HOME.id - - private var sharedPreferencesListener = - SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey -> - if (prefKey == LauncherPreferences.widgets().keys().widgets()) { - // We can't observe the livedata because this is not an AppCompatActivity - findViewById(R.id.manage_widgets_container).updateWidgets(this, - LauncherPreferences.widgets().widgets() - ) - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - super.onCreate() - setContentView(R.layout.activity_manage_widgets) - - panelId = intent.extras?.getInt(EXTRA_PANEL_ID, WidgetPanel.HOME.id) ?: WidgetPanel.HOME.id - - findViewById(R.id.manage_widgets_button_add).setOnClickListener { - selectWidget() - } - - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - findViewById(R.id.manage_widgets_container).let { - it.widgetPanelId = panelId - it.updateWidgets(this, (application as Application).widgets.value) - } - } - - override fun onStart() { - super.onStart() - super.onStart() - - LauncherPreferences.getSharedPreferences() - .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) - - } - - override fun onResume() { - super.onResume() - findViewById(R.id.manage_widgets_container).updateWidgets(this, - LauncherPreferences.widgets().widgets() - ) - - } - override fun getTheme(): Resources.Theme { - val mTheme = modifyTheme(super.getTheme()) - mTheme.applyStyle(R.style.backgroundWallpaper, true) - LauncherPreferences.clock().font().applyToTheme(mTheme) - LauncherPreferences.theme().colorTheme().applyToTheme( - mTheme, - LauncherPreferences.theme().textShadow() - ) - return mTheme - } - - override fun onDestroy() { - LauncherPreferences.getSharedPreferences() - .unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener) - super.onDestroy() - } - - - fun selectWidget() { - val appWidgetHost = (application as Application).appWidgetHost - startActivityForResult( - Intent(this, SelectWidgetActivity::class.java).also { - it.putExtra( - AppWidgetManager.EXTRA_APPWIDGET_ID, - appWidgetHost.allocateAppWidgetId() - ) - it.putExtra( - EXTRA_PANEL_ID, - panelId - ) - }, REQUEST_PICK_APPWIDGET - ) - } - - - fun createWidget(data: Intent) { - Log.i("Launcher", "creating widget") - val appWidgetManager = (application as Application).appWidgetManager - val appWidgetId = data.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: return - - val provider = appWidgetManager.getAppWidgetInfo(appWidgetId) - - val display = windowManager.defaultDisplay - - val position = WidgetPosition.fromAbsoluteRect( - Rect(0,0, - min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minWidth), - min(400, appWidgetManager.getAppWidgetInfo(appWidgetId).minHeight) - ), - display.width, - display.height - ) - - val widget = AppWidget(appWidgetId, position, panelId, provider) - LauncherPreferences.widgets().widgets( - (LauncherPreferences.widgets().widgets() ?: HashSet()).also { - it.add(widget) - } - ) - } - - private fun configureWidget(data: Intent) { - val extras = data.extras - val appWidgetId = extras!!.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) - val widget = AppWidget(appWidgetId, panelId = panelId) - if (widget.isConfigurable(this)) { - widget.configure(this, REQUEST_CREATE_APPWIDGET) - } else { - createWidget(data) - } - } - - override fun onActivityResult( - requestCode: Int, resultCode: Int, - data: Intent? - ) { - super.onActivityResult(requestCode, resultCode, data) - if (resultCode == RESULT_OK) { - if (requestCode == REQUEST_PICK_APPWIDGET) { - configureWidget(data!!) - } else if (requestCode == REQUEST_CREATE_APPWIDGET) { - createWidget(data!!) - } - } else if (resultCode == RESULT_CANCELED && data != null) { - val appWidgetId = - data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) - if (appWidgetId != -1) { - AppWidget(appWidgetId).delete(this) - } - } - } - - - /** - * For a better preview, [ManageWidgetsActivity] should behave exactly like [HomeActivity] - */ - override fun isHomeScreen(): Boolean { - return true - } -} diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt deleted file mode 100644 index a1bd3b5..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt +++ /dev/null @@ -1,172 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProviderInfo -import android.content.Intent -import android.content.res.Resources -import android.os.Build -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.databinding.ActivitySelectWidgetBinding -import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.widgets.ClockWidget -import de.jrpie.android.launcher.widgets.LauncherAppWidgetProvider -import de.jrpie.android.launcher.widgets.LauncherClockWidgetProvider -import de.jrpie.android.launcher.widgets.LauncherWidgetProvider -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition -import de.jrpie.android.launcher.widgets.bindAppWidgetOrRequestPermission -import de.jrpie.android.launcher.widgets.getAppWidgetHost -import de.jrpie.android.launcher.widgets.getAppWidgetProviders -import de.jrpie.android.launcher.widgets.updateWidget - - -private const val REQUEST_WIDGET_PERMISSION = 29 - -/** - * This activity lets the user pick an app widget to add. - * It provides an interface similar to [android.appwidget.AppWidgetManager.ACTION_APPWIDGET_PICK], - * but shows more information and also shows widgets from other user profiles. - */ -class SelectWidgetActivity : AppCompatActivity(), UIObject { - lateinit var binding: ActivitySelectWidgetBinding - var widgetId: Int = -1 - var widgetPanelId: Int = WidgetPanel.HOME.id - - private fun tryBindWidget(info: LauncherWidgetProvider) { - when (info) { - is LauncherAppWidgetProvider -> { - if (bindAppWidgetOrRequestPermission( - this, - info.info, - widgetId, - REQUEST_WIDGET_PERMISSION - ) - ) { - setResult( - RESULT_OK, - Intent().also { - it.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId) - it.putExtra(EXTRA_PANEL_ID, widgetPanelId) - } - ) - finish() - } - } - is LauncherClockWidgetProvider -> { - updateWidget(ClockWidget(widgetId, WidgetPosition(0, 4, 12, 3), widgetPanelId)) - finish() - } - } - } - - override fun onStart() { - super.onStart() - super.onStart() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - super.onCreate() - - binding = ActivitySelectWidgetBinding.inflate(layoutInflater) - setContentView(binding.root) - - - widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) - widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id) - if (widgetId == -1) { - widgetId = getAppWidgetHost().allocateAppWidgetId() - } - - val viewManager = LinearLayoutManager(this) - val viewAdapter = SelectWidgetRecyclerAdapter() - - binding.selectWidgetRecycler.apply { - setHasFixedSize(false) - layoutManager = viewManager - adapter = viewAdapter - } - } - - override fun getTheme(): Resources.Theme { - return modifyTheme(super.getTheme()) - } - - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - - if (requestCode == REQUEST_WIDGET_PERMISSION && resultCode == RESULT_OK) { - data ?: return - val provider = (data.getSerializableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER) as? AppWidgetProviderInfo) ?: return - tryBindWidget(LauncherAppWidgetProvider(provider)) - } - } - - inner class SelectWidgetRecyclerAdapter() : - RecyclerView.Adapter() { - - private val widgets = getAppWidgetProviders(this@SelectWidgetActivity).toTypedArray() - - inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), - View.OnClickListener { - var textView: TextView = itemView.findViewById(R.id.list_widgets_row_name) - var descriptionView: TextView = itemView.findViewById(R.id.list_widgets_row_description) - var iconView: ImageView = itemView.findViewById(R.id.list_widgets_row_icon) - var previewView: ImageView = itemView.findViewById(R.id.list_widgets_row_preview) - - - override fun onClick(v: View) { - tryBindWidget(widgets[bindingAdapterPosition]) - } - - init { - itemView.setOnClickListener(this) - } - } - - override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { - val label = widgets[i].loadLabel(this@SelectWidgetActivity) - val description = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - widgets[i].loadDescription(this@SelectWidgetActivity) - } else { - "" - } - val preview = - widgets[i].loadPreviewImage(this@SelectWidgetActivity) - val icon = - widgets[i].loadIcon(this@SelectWidgetActivity) - - viewHolder.textView.text = label - viewHolder.descriptionView.text = description - viewHolder.descriptionView.visibility = - if (description?.isEmpty() == false) { View.VISIBLE } else { View.GONE } - viewHolder.iconView.setImageDrawable(icon) - - viewHolder.previewView.setImageDrawable(preview) - viewHolder.previewView.visibility = - if (preview != null) { View.VISIBLE } else { View.GONE } - - viewHolder.previewView.requestLayout() - } - - override fun getItemCount(): Int { - return widgets.size - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val inflater = LayoutInflater.from(parent.context) - val view: View = inflater.inflate(R.layout.list_widgets_row, parent, false) - return ViewHolder(view) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetManagerView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetManagerView.kt deleted file mode 100644 index 7a355f7..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetManagerView.kt +++ /dev/null @@ -1,175 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Context -import android.graphics.Point -import android.graphics.Rect -import android.graphics.RectF -import android.os.Build -import android.os.Handler -import android.os.Looper -import android.util.AttributeSet -import android.view.HapticFeedbackConstants -import android.view.MotionEvent -import android.view.View -import android.view.ViewConfiguration -import androidx.core.graphics.contains -import androidx.core.graphics.minus -import androidx.core.graphics.toRect -import androidx.core.view.children -import de.jrpie.android.launcher.ui.widgets.WidgetContainerView -import de.jrpie.android.launcher.widgets.Widget -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.WidgetPosition -import de.jrpie.android.launcher.widgets.updateWidget -import kotlin.math.max -import kotlin.math.min - -/** - * A variant of the [WidgetContainerView] which allows to manage widgets. - */ -class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSet? = null) : - WidgetContainerView(widgetPanelId, context, attrs) { - constructor(context: Context, attrs: AttributeSet?) : this(WidgetPanel.HOME.id, context, attrs) - - val TOUCH_SLOP: Int - val TOUCH_SLOP_SQUARE: Int - val LONG_PRESS_TIMEOUT: Long - - init { - val configuration = ViewConfiguration.get(context) - TOUCH_SLOP = configuration.scaledTouchSlop - TOUCH_SLOP_SQUARE = TOUCH_SLOP * TOUCH_SLOP - - LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout().toLong() - } - - - - enum class EditMode(val resize: (dx: Int, dy: Int, rect: Rect) -> Rect) { - MOVE({ dx, dy, rect -> - Rect(rect.left + dx, rect.top + dy, rect.right + dx, rect.bottom + dy) - }), - TOP({ dx, dy, rect -> - Rect(rect.left, min(rect.top + dy, rect.bottom - 200), rect.right, rect.bottom) - }), - BOTTOM({ dx, dy, rect -> - Rect(rect.left, rect.top, rect.right, max(rect.top + 200, rect.bottom + dy)) - }), - LEFT({ dx, dy, rect -> - Rect(min(rect.left + dx, rect.right - 200), rect.top, rect.right, rect.bottom) - }), - RIGHT({ dx, dy, rect -> - Rect(rect.left, rect.top, max(rect.left + 200, rect.right + dx), rect.bottom) - }), - } - - var selectedWidgetOverlayView: WidgetOverlayView? = null - var selectedWidgetView: View? = null - var currentGestureStart: Point? = null - var startWidgetPosition: Rect? = null - var lastPosition = Rect() - - private val longPressHandler = Handler(Looper.getMainLooper()) - - - override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { - return true - } - - @SuppressLint("ClickableViewAccessibility") - override fun onTouchEvent(event: MotionEvent?): Boolean { - if (event == null) { - return false - } - synchronized(this) { - if (event.actionMasked == MotionEvent.ACTION_DOWN) { - val start = Point(event.x.toInt(), event.y.toInt()) - currentGestureStart = start - val view = children.mapNotNull { it as? WidgetOverlayView }.firstOrNull { - RectF(it.x, it.y, it.x + it.width, it.y + it.height).toRect().contains(start) == true - } ?: return false - - val position = (view.layoutParams as Companion.LayoutParams).position.getAbsoluteRect(width, height) - selectedWidgetOverlayView = view - selectedWidgetView = widgetViewById.get(view.widgetId) ?: return true - startWidgetPosition = position - - val positionInView = start.minus(Point(position.left, position.top)) - view.mode = view.getHandles().firstOrNull { it.position.contains(positionInView) }?.mode ?: EditMode.MOVE - - longPressHandler.postDelayed({ - synchronized(this@WidgetManagerView) { - view.showPopupMenu() - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - endInteraction() - } - }, LONG_PRESS_TIMEOUT) - } - if (event.actionMasked == MotionEvent.ACTION_MOVE || - event.actionMasked == MotionEvent.ACTION_UP - ) { - val distanceX = event.x - (currentGestureStart?.x ?: return true) - val distanceY = event.y - (currentGestureStart?.y ?: return true) - if (distanceX * distanceX + distanceY * distanceY > TOUCH_SLOP_SQUARE) { - longPressHandler.removeCallbacksAndMessages(null) - } - val view = selectedWidgetOverlayView ?: return true - val start = startWidgetPosition ?: return true - val absoluteNewPosition = view.mode?.resize( - distanceX.toInt(), - distanceY.toInt(), - start - ) ?: return true - val newPosition = WidgetPosition.fromAbsoluteRect( - absoluteNewPosition, width, height - ) - if (newPosition != lastPosition) { - lastPosition = absoluteNewPosition - (view.layoutParams as Companion.LayoutParams).position = newPosition - (selectedWidgetView?.layoutParams as? Companion.LayoutParams)?.position = newPosition - requestLayout() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_PRESS) - } - } - - if (event.actionMasked == MotionEvent.ACTION_UP) { - longPressHandler.removeCallbacksAndMessages(null) - val id = selectedWidgetOverlayView?.widgetId ?: return true - val widget = Widget.byId(context, id) ?: return true - widget.position = newPosition - endInteraction() - updateWidget(widget) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - view.performHapticFeedback(HapticFeedbackConstants.GESTURE_END) - } - } - } - } - - - return true - } - private fun endInteraction() { - startWidgetPosition = null - selectedWidgetOverlayView?.mode = null - } - - override fun updateWidgets(activity: Activity, widgets: Collection?) { - super.updateWidgets(activity, widgets) - if (widgets == null) { - return - } - children.mapNotNull { it as? WidgetOverlayView }.forEach { removeView(it) } - - widgets.filter { it.panelId == widgetPanelId }.forEach { widget -> - WidgetOverlayView(activity).let { - addView(it) - it.widgetId = widget.id - (it.layoutParams as Companion.LayoutParams).position = widget.position - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt deleted file mode 100644 index 1b8a2d2..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetOverlayView.kt +++ /dev/null @@ -1,132 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Rect -import android.graphics.drawable.Drawable -import android.util.AttributeSet -import android.view.View -import android.widget.PopupMenu -import androidx.core.graphics.toRectF -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.widgets.Widget -import de.jrpie.android.launcher.widgets.updateWidget - - -private const val HANDLE_SIZE = 100 -private const val HANDLE_EDGE_SIZE = (1.2 * HANDLE_SIZE).toInt() - -/** - * An overlay to show configuration options for a widget in [WidgetManagerView] - */ -class WidgetOverlayView : View { - - - val paint = Paint() - val handlePaint = Paint() - val selectedHandlePaint = Paint() - var mode: WidgetManagerView.EditMode? = null - class Handle(val mode: WidgetManagerView.EditMode, val position: Rect) - init { - handlePaint.style = Paint.Style.STROKE - handlePaint.setARGB(255, 255, 255, 255) - - selectedHandlePaint.style = Paint.Style.FILL_AND_STROKE - selectedHandlePaint.setARGB(100, 255, 255, 255) - - paint.style = Paint.Style.STROKE - paint.setARGB(255, 255, 255, 255) - } - - private var preview: Drawable? = null - var widgetId: Int = -1 - set(newId) { - field = newId - preview = Widget.byId(context, widgetId)?.getPreview(context) - } - - constructor(context: Context) : super(context) { - init(null, 0) - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - init(attrs, 0) - } - - constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super( - context, - attrs, - defStyle - ) { - init(attrs, defStyle) - } - - private fun init(attrs: AttributeSet?, defStyle: Int) { } - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - - getHandles().forEach { - if (it.mode == mode) { - canvas.drawRoundRect(it.position.toRectF(), 5f, 5f, selectedHandlePaint) - } else { - canvas.drawRoundRect(it.position.toRectF(), 5f, 5f, handlePaint) - } - } - val bounds = getBounds() - canvas.drawRoundRect(bounds.toRectF(), 5f, 5f, paint) - - if (mode == null) { - return - } - - //preview?.bounds = bounds - //preview?.draw(canvas) - - - } - - fun showPopupMenu() { - val widget = Widget.byId(context, widgetId)?: return - val menu = PopupMenu(context, this) - menu.menu.let { - it.add( - context.getString(R.string.widget_menu_remove) - ).setOnMenuItemClickListener { _ -> - Widget.byId(context, widgetId)?.delete(context) - return@setOnMenuItemClickListener true - } - it.add( - if (widget.allowInteraction) { - context.getString(R.string.widget_menu_disable_interaction) - } else { - context.getString(R.string.widget_menu_enable_interaction) - } - ).setOnMenuItemClickListener { _ -> - widget.allowInteraction = !widget.allowInteraction - updateWidget(widget) - return@setOnMenuItemClickListener true - } - } - menu.show() - } - - fun getHandles(): List { - return listOf( - Handle(WidgetManagerView.EditMode.TOP, - Rect(HANDLE_EDGE_SIZE, 0, width - HANDLE_EDGE_SIZE, HANDLE_SIZE)), - Handle(WidgetManagerView.EditMode.BOTTOM, - Rect(HANDLE_EDGE_SIZE, height - HANDLE_SIZE, width - HANDLE_EDGE_SIZE, height)), - Handle(WidgetManagerView.EditMode.LEFT, - Rect(0, HANDLE_EDGE_SIZE, HANDLE_SIZE, height - HANDLE_EDGE_SIZE)), - Handle(WidgetManagerView.EditMode.RIGHT, - Rect(width - HANDLE_SIZE, HANDLE_EDGE_SIZE, width, height - HANDLE_EDGE_SIZE)) - ) - - } - - private fun getBounds(): Rect { - return Rect(0,0, width, height) - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt deleted file mode 100644 index 40c2c2f..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/WidgetPanelsRecyclerAdapter.kt +++ /dev/null @@ -1,98 +0,0 @@ -package de.jrpie.android.launcher.ui.widgets.manage - -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.EditText -import android.widget.PopupMenu -import android.widget.TextView -import androidx.appcompat.app.AlertDialog -import androidx.recyclerview.widget.RecyclerView -import de.jrpie.android.launcher.R -import de.jrpie.android.launcher.preferences.LauncherPreferences -import de.jrpie.android.launcher.widgets.WidgetPanel -import de.jrpie.android.launcher.widgets.updateWidgetPanel - - -class WidgetPanelsRecyclerAdapter( - val context: Context, - val showMenu: Boolean = false, - val onSelectWidgetPanel: (WidgetPanel) -> Unit -) : - RecyclerView.Adapter() { - - var widgetPanels = (LauncherPreferences.widgets().customPanels() ?: setOf()).toTypedArray() - - class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - var labelView: TextView = itemView.findViewById(R.id.list_widget_panels_label) - } - - override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { - viewHolder.labelView.text = widgetPanels[i].label - - viewHolder.itemView.setOnClickListener { - onSelectWidgetPanel(widgetPanels[i]) - } - - if (showMenu) { - viewHolder.itemView.setOnLongClickListener { - showOptionsPopup( - viewHolder, - widgetPanels[i] - ) - } - } - } - - @Suppress("SameReturnValue") - private fun showOptionsPopup( - viewHolder: ViewHolder, - widgetPanel: WidgetPanel - ): Boolean { - //create the popup menu - - val popup = PopupMenu(context, viewHolder.labelView) - popup.menu.add(R.string.manage_widget_panels_delete).setOnMenuItemClickListener { _ -> - widgetPanel.delete(context) - true - } - popup.menu.add(R.string.manage_widget_panels_rename).setOnMenuItemClickListener { _ -> - AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { - setNegativeButton(R.string.dialog_cancel) { _, _ -> } - setPositiveButton(R.string.dialog_ok) { dialogInterface, _ -> - var newLabel = (dialogInterface as? AlertDialog) - ?.findViewById(R.id.dialog_rename_widget_panel_edit_text) - ?.text?.toString() - if (newLabel == null || newLabel.isEmpty()) { - newLabel = - (context.getString(R.string.widget_panel_default_name, widgetPanel.id)) - } - widgetPanel.label = newLabel - updateWidgetPanel(widgetPanel) - } - setView(R.layout.dialog_rename_widget_panel) - }.create().also { it.show() }.apply { - findViewById(R.id.dialog_rename_widget_panel_edit_text)?.let { - it.setText(widgetPanel.label) - it.hint = context.getString(R.string.widget_panel_default_name, widgetPanel.id) - } - } - true - } - - popup.show() - return true - } - - override fun getItemCount(): Int { - return widgetPanels.size - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val view: View = - LayoutInflater.from(context).inflate(R.layout.list_widget_panels_row, parent, false) - val viewHolder = ViewHolder(view) - return viewHolder - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/AppWidget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/AppWidget.kt deleted file mode 100644 index 22a63eb..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/AppWidget.kt +++ /dev/null @@ -1,126 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.app.Activity -import android.appwidget.AppWidgetHostView -import android.appwidget.AppWidgetProviderInfo -import android.content.Context -import android.graphics.drawable.Drawable -import android.os.Build -import android.os.Bundle -import android.util.DisplayMetrics -import android.util.SizeF -import android.view.View -import de.jrpie.android.launcher.Application -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -@SerialName("widget:app") -class AppWidget( - override val id: Int, - override var position: WidgetPosition = WidgetPosition(0,0,1,1), - override var panelId: Int = WidgetPanel.HOME.id, - override var allowInteraction: Boolean = false, - - // We keep track of packageName, className and user to make it possible to restore the widget - // on a new device when restoring settings (currently not implemented) - // In normal operation only id and position are used. - val packageName: String? = null, - val className: String? = null, - val user: Int? = null -): Widget() { - - - constructor( - id: Int, - position: WidgetPosition, - panelId: Int, - widgetProviderInfo: AppWidgetProviderInfo - ) : - this( - id, - position, - panelId, - false, - widgetProviderInfo.provider.packageName, - widgetProviderInfo.provider.className, - widgetProviderInfo.profile.hashCode() - ) - - /** - * Get the [AppWidgetProviderInfo] by [id]. - * If the widget is not installed, use [restoreAppWidgetProviderInfo] instead. - */ - fun getAppWidgetProviderInfo(context: Context): AppWidgetProviderInfo? { - if (id < 0) { - return null - } - return (context.applicationContext as Application).appWidgetManager - .getAppWidgetInfo(id) - } - - /** - * Restore the AppWidgetProviderInfo from [user], [packageName] and [className]. - * Only use this when the widget is not installed, - * in normal operation use [getAppWidgetProviderInfo] instead. - */ - /*fun restoreAppWidgetProviderInfo(context: Context): AppWidgetProviderInfo? { - return getAppWidgetProviders(context).firstOrNull { - it.profile.hashCode() == user - && it.provider.packageName == packageName - && it.provider.className == className - } - }*/ - - override fun toString(): String { - return "WidgetInfo(id=$id, position=$position, packageName=$packageName, className=$className, user=$user)" - } - - override fun createView(activity: Activity): AppWidgetHostView? { - val providerInfo = activity.getAppWidgetManager().getAppWidgetInfo(id) ?: return null - val view = activity.getAppWidgetHost() - .createView(activity, this.id, providerInfo) - - val dp = activity.resources.displayMetrics.density - val screenWidth = activity.resources.displayMetrics.widthPixels - val screenHeight = activity.resources.displayMetrics.heightPixels - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val absolutePosition = position.getAbsoluteRect(screenWidth, screenHeight) - view.updateAppWidgetSize(Bundle.EMPTY, - listOf(SizeF( - absolutePosition.width() / dp, - absolutePosition.height() / dp - ))) - } - view.setPadding(0,0,0,0) - return view - } - - override fun findView(views: Sequence): AppWidgetHostView? { - return views.mapNotNull { it as? AppWidgetHostView }.firstOrNull { it.appWidgetId == id } - } - - override fun getIcon(context: Context): Drawable? { - return context.getAppWidgetManager().getAppWidgetInfo(id)?.loadIcon(context, DisplayMetrics.DENSITY_HIGH) - } - - override fun getPreview(context: Context): Drawable? { - return context.getAppWidgetManager().getAppWidgetInfo(id)?.loadPreviewImage(context, DisplayMetrics.DENSITY_HIGH) - } - - override fun isConfigurable(context: Context): Boolean { - return context.getAppWidgetManager().getAppWidgetInfo(id)?.configure != null - } - override fun configure(activity: Activity, requestCode: Int) { - if (!isConfigurable(activity)) { - return - } - activity.getAppWidgetHost().startAppWidgetConfigureActivityForResult( - activity, - id, - 0, - requestCode, - null - ) - } -} diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt deleted file mode 100644 index d0d1c0e..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt +++ /dev/null @@ -1,42 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.app.Activity -import android.content.Context -import android.graphics.drawable.Drawable -import android.view.View -import de.jrpie.android.launcher.ui.widgets.ClockView -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - - -@Serializable -@SerialName("widget:clock") -class ClockWidget( - override val id: Int, - override var position: WidgetPosition, - override val panelId: Int, - override var allowInteraction: Boolean = true -) : Widget() { - - override fun createView(activity: Activity): View? { - return ClockView(activity, null, id) - } - - override fun findView(views: Sequence): ClockView? { - return views.mapNotNull { it as? ClockView }.firstOrNull { it.appWidgetId == id } - } - - override fun getPreview(context: Context): Drawable? { - return null - } - - override fun getIcon(context: Context): Drawable? { - return null - } - - override fun isConfigurable(context: Context): Boolean { - return false - } - - override fun configure(activity: Activity, requestCode: Int) { } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt deleted file mode 100644 index 018b29b..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/LauncherWidgetProvider.kt +++ /dev/null @@ -1,58 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.appwidget.AppWidgetProviderInfo -import android.content.Context -import android.graphics.drawable.Drawable -import android.os.Build -import android.util.DisplayMetrics -import androidx.appcompat.content.res.AppCompatResources -import de.jrpie.android.launcher.R - -sealed class LauncherWidgetProvider { - abstract fun loadLabel(context: Context): CharSequence? - abstract fun loadPreviewImage(context: Context): Drawable? - abstract fun loadIcon(context: Context): Drawable? - abstract fun loadDescription(context: Context): CharSequence? -} - -class LauncherAppWidgetProvider(val info: AppWidgetProviderInfo) : LauncherWidgetProvider() { - - override fun loadLabel(context: Context): CharSequence? { - return info.loadLabel(context.packageManager) - } - override fun loadPreviewImage(context: Context): Drawable? { - return info.loadPreviewImage(context, DisplayMetrics.DENSITY_DEFAULT) - } - - override fun loadIcon(context: Context): Drawable? { - return info.loadIcon(context, DisplayMetrics.DENSITY_DEFAULT) - } - - override fun loadDescription(context: Context): CharSequence? { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - info.loadDescription(context) - } else { - null - } - } - -} -class LauncherClockWidgetProvider : LauncherWidgetProvider() { - - override fun loadLabel(context: Context): CharSequence? { - return context.getString(R.string.widget_clock_label) - } - - override fun loadDescription(context: Context): CharSequence? { - return context.getString(R.string.widget_clock_description) - } - - override fun loadPreviewImage(context: Context): Drawable? { - return null - } - - override fun loadIcon(context: Context): Drawable? { - return AppCompatResources.getDrawable(context, R.drawable.baseline_clock_24) - } -} - diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt deleted file mode 100644 index dbe667b..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt +++ /dev/null @@ -1,65 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.app.Activity -import android.content.Context -import android.graphics.drawable.Drawable -import android.view.View -import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.preferences.LauncherPreferences -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json - - -@Serializable -sealed class Widget { - abstract val id: Int - abstract var position: WidgetPosition - abstract val panelId: Int - abstract var allowInteraction: Boolean - - /** - * @param activity The activity where the view will be used. Must not be an AppCompatActivity. - */ - abstract fun createView(activity: Activity): View? - abstract fun findView(views: Sequence): View? - abstract fun getPreview(context: Context): Drawable? - abstract fun getIcon(context: Context): Drawable? - abstract fun isConfigurable(context: Context): Boolean - abstract fun configure(activity: Activity, requestCode: Int) - - fun delete(context: Context) { - context.getAppWidgetHost().deleteAppWidgetId(id) - - LauncherPreferences.widgets().widgets( - LauncherPreferences.widgets().widgets()?.also { - it.remove(this) - } - ) - } - - fun getPanel(): WidgetPanel? { - return WidgetPanel.byId(panelId) - } - - override fun hashCode(): Int { - return id - } - - override fun equals(other: Any?): Boolean { - return (other as? Widget)?.id == id - } - - fun serialize(): String { - return Json.encodeToString(serializer(), this) - } - companion object { - fun deserialize(serialized: String): Widget { - return Json.decodeFromString(serialized) - } - fun byId(context: Context, id: Int): Widget? { - return (context.applicationContext as Application).widgets.value?.firstOrNull { - it.id == id - } - } - } -} diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt deleted file mode 100644 index 93e588d..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPanel.kt +++ /dev/null @@ -1,58 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.content.Context -import de.jrpie.android.launcher.preferences.LauncherPreferences -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json - - -@Serializable -@SerialName("panel") -class WidgetPanel(val id: Int, var label: String) { - - override fun equals(other: Any?): Boolean { - return (other as? WidgetPanel)?.id == id - } - - override fun hashCode(): Int { - return id - } - - fun serialize(): String { - return Json.encodeToString(this) - } - - fun delete(context: Context) { - LauncherPreferences.widgets().customPanels( - (LauncherPreferences.widgets().customPanels() ?: setOf()).minus(this) - ) - (LauncherPreferences.widgets().widgets() ?: return) - .filter { it.panelId == this.id }.forEach { it.delete(context) } - } - - - companion object { - val HOME = WidgetPanel(0, "home") - fun byId(id: Int): WidgetPanel? { - if (id == 0) { - return HOME - } - return LauncherPreferences.widgets().customPanels()?.firstOrNull { it.id == id } - } - - fun allocateId(): Int { - return ( - (LauncherPreferences.widgets().customPanels() ?: setOf()) - .plus(HOME) - .maxOfOrNull { it.id } ?: 0 - ) + 1 - } - - fun deserialize(serialized: String): WidgetPanel { - return Json.decodeFromString(serialized) - } - - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt deleted file mode 100644 index b575665..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/WidgetPosition.kt +++ /dev/null @@ -1,58 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.graphics.Rect -import kotlinx.serialization.Serializable -import kotlin.math.ceil -import kotlin.math.roundToInt -import kotlin.math.max - -const val GRID_SIZE: Short = 12 - -@Serializable -data class WidgetPosition(var x: Short, var y: Short, var width: Short, var height: Short) { - - fun getAbsoluteRect(screenWidth: Int, screenHeight: Int): Rect { - val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() - - return Rect( - (x * gridWidth).toInt(), - (y * gridHeight).toInt(), - ((x + width) * gridWidth).toInt(), - ((y + height) * gridHeight).toInt() - ) - } - - companion object { - fun fromAbsoluteRect(absolute: Rect, screenWidth: Int, screenHeight: Int): WidgetPosition { - val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() - - val x = (absolute.left / gridWidth).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort()) - val y = (absolute.top / gridHeight).roundToInt().toShort().coerceIn(0, (GRID_SIZE-1).toShort()) - - - val w = max(2, ((absolute.right - absolute.left) / gridWidth).roundToInt()).toShort() - val h = max(2, ((absolute.bottom - absolute.top) / gridHeight).roundToInt()).toShort() - - return WidgetPosition(x,y,w,h) - - } - - fun center(minWidth: Int, minHeight: Int, screenWidth: Int, screenHeight: Int): WidgetPosition { - val gridWidth = screenWidth / GRID_SIZE.toFloat() - val gridHeight= screenHeight / GRID_SIZE.toFloat() - - val cellsWidth = ceil(minWidth / gridWidth).toInt().toShort() - val cellsHeight = ceil(minHeight / gridHeight).toInt().toShort() - - return WidgetPosition( - ((GRID_SIZE - cellsWidth) / 2).toShort(), - ((GRID_SIZE - cellsHeight) / 2).toShort(), - cellsWidth, - cellsHeight - ) - - } - } -} \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt deleted file mode 100644 index b7f140b..0000000 --- a/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt +++ /dev/null @@ -1,97 +0,0 @@ -package de.jrpie.android.launcher.widgets - -import android.app.Activity -import android.app.Service -import android.appwidget.AppWidgetHost -import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProviderInfo -import android.content.Context -import android.content.Intent -import android.content.pm.LauncherApps -import android.os.Build -import android.os.UserManager -import android.util.Log -import de.jrpie.android.launcher.Application -import de.jrpie.android.launcher.preferences.LauncherPreferences - -fun deleteAllWidgets(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.getAppWidgetHost().appWidgetIds.forEach { AppWidget(it).delete(context) } - } -} - -/** - * Tries to bind [providerInfo] to the id [id]. - * @param providerInfo The widget to be bound. - * @param id The id to bind the widget to. If -1 is provided, a new id is allocated. - * @param - * @param requestCode Used to start an activity to request permission to bind the widget. - * - * @return true iff the app widget was bound successfully. - */ -fun bindAppWidgetOrRequestPermission(activity: Activity, providerInfo: AppWidgetProviderInfo, id: Int, requestCode: Int? = null): Boolean { - val appWidgetId = if(id == -1) { - activity.getAppWidgetHost().allocateAppWidgetId() - } else { id } - - Log.i("Launcher", "Binding new widget ${appWidgetId}") - if (!activity.getAppWidgetManager().bindAppWidgetIdIfAllowed( - appWidgetId, - providerInfo.provider - ) - ) { - Log.i("Widgets", "requesting permission for widget") - val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply { - putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetId) - putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, providerInfo.provider) - } - activity.startActivityForResult(intent, requestCode ?: 0) - return false - } - return true -} - - -fun getAppWidgetProviders( context: Context ): List { - val list = mutableListOf(LauncherClockWidgetProvider()) - val appWidgetManager = context.getAppWidgetManager() - val profiles = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - (context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps).profiles - } else { - (context.getSystemService(Service.USER_SERVICE) as UserManager).userProfiles - } - list.addAll( - profiles.map { - appWidgetManager.getInstalledProvidersForProfile(it) - .map { LauncherAppWidgetProvider(it) } - }.flatten() - ) - - - return list -} - - -fun updateWidget(widget: Widget) { - LauncherPreferences.widgets().widgets( - (LauncherPreferences.widgets().widgets() ?: setOf()) - .minus(widget) - .plus(widget) - ) -} - -fun updateWidgetPanel(widgetPanel: WidgetPanel) { - LauncherPreferences.widgets().customPanels( - (LauncherPreferences.widgets().customPanels() ?: setOf()) - .minus(widgetPanel) - .plus(widgetPanel) - ) -} - -fun Context.getAppWidgetHost(): AppWidgetHost { - return (this.applicationContext as Application).appWidgetHost -} -fun Context.getAppWidgetManager(): AppWidgetManager { - return (this.applicationContext as Application).appWidgetManager -} diff --git a/app/src/main/res/drawable/baseline_add_24.xml b/app/src/main/res/drawable/baseline_add_24.xml deleted file mode 100644 index 13267ce..0000000 --- a/app/src/main/res/drawable/baseline_add_24.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/baseline_clock_24.xml b/app/src/main/res/drawable/baseline_clock_24.xml deleted file mode 100644 index 7968998..0000000 --- a/app/src/main/res/drawable/baseline_clock_24.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/drawable/baseline_widgets_24.xml b/app/src/main/res/drawable/baseline_widgets_24.xml deleted file mode 100644 index fd0f571..0000000 --- a/app/src/main/res/drawable/baseline_widgets_24.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/app/src/main/res/layout/activity_manage_widget_panels.xml b/app/src/main/res/layout/activity_manage_widget_panels.xml deleted file mode 100644 index 60413a3..0000000 --- a/app/src/main/res/layout/activity_manage_widget_panels.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_manage_widgets.xml b/app/src/main/res/layout/activity_manage_widgets.xml deleted file mode 100644 index c77f0e3..0000000 --- a/app/src/main/res/layout/activity_manage_widgets.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_select_widget.xml b/app/src/main/res/layout/activity_select_widget.xml deleted file mode 100644 index 82db94d..0000000 --- a/app/src/main/res/layout/activity_select_widget.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_widget_panel.xml b/app/src/main/res/layout/activity_widget_panel.xml deleted file mode 100644 index 6ef6b20..0000000 --- a/app/src/main/res/layout/activity_widget_panel.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/clock.xml b/app/src/main/res/layout/clock.xml deleted file mode 100644 index d81fc5f..0000000 --- a/app/src/main/res/layout/clock.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_create_widget_panel.xml b/app/src/main/res/layout/dialog_create_widget_panel.xml deleted file mode 100644 index 900823d..0000000 --- a/app/src/main/res/layout/dialog_create_widget_panel.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_rename_widget_panel.xml b/app/src/main/res/layout/dialog_rename_widget_panel.xml deleted file mode 100644 index effb783..0000000 --- a/app/src/main/res/layout/dialog_rename_widget_panel.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_select_widget_panel.xml b/app/src/main/res/layout/dialog_select_widget_panel.xml deleted file mode 100644 index 5f83d51..0000000 --- a/app/src/main/res/layout/dialog_select_widget_panel.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/home.xml b/app/src/main/res/layout/home.xml index 717151f..ecefdea 100644 --- a/app/src/main/res/layout/home.xml +++ b/app/src/main/res/layout/home.xml @@ -10,10 +10,29 @@ android:fitsSystemWindows="true" tools:context=".ui.HomeActivity"> - + + + - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/list_widgets_header.xml b/app/src/main/res/layout/list_widgets_header.xml deleted file mode 100644 index 7779f2b..0000000 --- a/app/src/main/res/layout/list_widgets_header.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/list_widgets_row.xml b/app/src/main/res/layout/list_widgets_row.xml deleted file mode 100644 index 878aaad..0000000 --- a/app/src/main/res/layout/list_widgets_row.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 2712036..1e4d12b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -11,9 +11,5 @@ #fff #9999ff #000 - #FF29B6F6 - #FF039BE5 - #FFBDBDBD - #FF757575 diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index f783d2a..89ec086 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -9,8 +9,6 @@ internal.started_before internal.first_startup internal.version_code - widgets.widgets - widgets.custom_panels apps.favorites apps.hidden apps.pinned_shortcuts @@ -149,7 +147,6 @@ functionality.search_auto_launch functionality.search_web functionality.search_auto_keyboard - functionality.search_auto_close_keyboard settings_action_lock_method diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d29128..a8bc9b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -98,9 +98,6 @@ Time Click on time - Manage widgets - Manage widget panels - Choose App @@ -170,7 +167,6 @@ Search the web Press return while searching the app list to launch a web search. Start keyboard for search - Close keyboard when scrolling Sensitivity @@ -255,12 +251,12 @@ Music: Next Music: Previous Music: Play / Pause - Expand Notifications Panel + Expand notifications panel Recent Apps - Do Nothing + Do nothing Lock Screen Toggle Torch - Launch Other Home Screen + Launch other Home Screen Add Shortcut @@ -391,33 +387,5 @@ Open Source Licenses No app found to handle search. Can\'t open URL: no browser found. - Choose Widget - - Remove - Configure - Enable Interaction - Disable Interaction - - - Clock - The default clock of μLauncher - Delete - Rename - - Widget Panel #%1$d - - Contains %d widget. - Contains %d widgets. - - - - Ok - Widget Panels - Select a Widget Panel - Create new widget panel - Launcher > Manage Widget Panels.]]> - Open Widget Panel - This widget panel no longer exists. - Widgets diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index c5b7252..20ccb67 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -66,12 +66,12 @@ 0 2 - + - + - - - - - diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 0ee7c17..6ef5d07 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -3,10 +3,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - + - - - - -