mirror of
https://github.com/jrpie/Launcher.git
synced 2025-04-27 06:11:02 +02:00
add option to enable / disable interaction with widgets
This commit is contained in:
parent
13c88122b2
commit
72f77c8294
20 changed files with 214 additions and 124 deletions
|
@ -22,6 +22,8 @@ import de.jrpie.android.launcher.apps.isPrivateSpaceLocked
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
|
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
|
||||||
import de.jrpie.android.launcher.preferences.resetPreferences
|
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.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -32,6 +34,7 @@ const val APP_WIDGET_HOST_ID = 42;
|
||||||
|
|
||||||
class Application : android.app.Application() {
|
class Application : android.app.Application() {
|
||||||
val apps = MutableLiveData<List<AbstractDetailedAppInfo>>()
|
val apps = MutableLiveData<List<AbstractDetailedAppInfo>>()
|
||||||
|
val widgets = MutableLiveData<Set<Widget>>()
|
||||||
val privateSpaceLocked = MutableLiveData<Boolean>()
|
val privateSpaceLocked = MutableLiveData<Boolean>()
|
||||||
lateinit var appWidgetHost: AppWidgetHost
|
lateinit var appWidgetHost: AppWidgetHost
|
||||||
lateinit var appWidgetManager: AppWidgetManager
|
lateinit var appWidgetManager: AppWidgetManager
|
||||||
|
@ -98,6 +101,8 @@ class Application : android.app.Application() {
|
||||||
customAppNames = LauncherPreferences.apps().customNames()
|
customAppNames = LauncherPreferences.apps().customNames()
|
||||||
} else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) {
|
} else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) {
|
||||||
loadApps()
|
loadApps()
|
||||||
|
} else if (pref == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
|
widgets.postValue(LauncherPreferences.widgets().widgets() ?: setOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,12 @@ import de.jrpie.android.launcher.BuildConfig
|
||||||
import de.jrpie.android.launcher.R
|
import de.jrpie.android.launcher.R
|
||||||
import de.jrpie.android.launcher.actions.lock.LauncherAccessibilityService
|
import de.jrpie.android.launcher.actions.lock.LauncherAccessibilityService
|
||||||
import de.jrpie.android.launcher.apps.AppFilter
|
import de.jrpie.android.launcher.apps.AppFilter
|
||||||
|
import de.jrpie.android.launcher.apps.hidePrivateSpaceWhenLocked
|
||||||
import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
|
import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
|
||||||
import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
|
import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
import de.jrpie.android.launcher.ui.list.ListActivity
|
import de.jrpie.android.launcher.ui.list.ListActivity
|
||||||
import de.jrpie.android.launcher.ui.settings.SettingsActivity
|
import de.jrpie.android.launcher.ui.settings.SettingsActivity
|
||||||
import de.jrpie.android.launcher.ui.widgets.manage.ManageWidgetsActivity
|
|
||||||
import de.jrpie.android.launcher.ui.widgets.manage.SelectWidgetActivity
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
@ -62,10 +61,7 @@ enum class LauncherAction(
|
||||||
"choose_from_favorites",
|
"choose_from_favorites",
|
||||||
R.string.list_other_list_favorites,
|
R.string.list_other_list_favorites,
|
||||||
R.drawable.baseline_favorite_24,
|
R.drawable.baseline_favorite_24,
|
||||||
{ context ->
|
{ context -> openAppsList(context, favorite = true) },
|
||||||
context.startActivity(Intent(context.applicationContext, ManageWidgetsActivity::class.java))
|
|
||||||
},
|
|
||||||
//openAppsList(context, favorite = true) },
|
|
||||||
true
|
true
|
||||||
),
|
),
|
||||||
CHOOSE_FROM_PRIVATE_SPACE(
|
CHOOSE_FROM_PRIVATE_SPACE(
|
||||||
|
@ -73,15 +69,12 @@ enum class LauncherAction(
|
||||||
R.string.list_other_list_private_space,
|
R.string.list_other_list_private_space,
|
||||||
R.drawable.baseline_security_24,
|
R.drawable.baseline_security_24,
|
||||||
{ context ->
|
{ context ->
|
||||||
context.startActivity(Intent(context.applicationContext, SelectWidgetActivity::class.java))
|
|
||||||
},
|
|
||||||
/*{ context ->
|
|
||||||
if ((context.applicationContext as Application).privateSpaceLocked.value != true
|
if ((context.applicationContext as Application).privateSpaceLocked.value != true
|
||||||
|| !hidePrivateSpaceWhenLocked(context)
|
|| !hidePrivateSpaceWhenLocked(context)
|
||||||
) {
|
) {
|
||||||
openAppsList(context, private = true)
|
openAppsList(context, private = true)
|
||||||
}
|
}
|
||||||
}, */
|
},
|
||||||
available = { _ ->
|
available = { _ ->
|
||||||
isPrivateSpaceSupported()
|
isPrivateSpaceSupported()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import eu.jonahbauer.android.preference.annotations.Preferences;
|
||||||
@Preference(name = "started_time", type = long.class),
|
@Preference(name = "started_time", type = long.class),
|
||||||
// see PREFERENCE_VERSION in de.jrpie.android.launcher.preferences.Preferences.kt
|
// see PREFERENCE_VERSION in de.jrpie.android.launcher.preferences.Preferences.kt
|
||||||
@Preference(name = "version_code", type = int.class, defaultValue = "-1"),
|
@Preference(name = "version_code", type = int.class, defaultValue = "-1"),
|
||||||
@Preference(name = "widgets", type = Set.class, serializer = SetWidgetSerializer.class)
|
|
||||||
}),
|
}),
|
||||||
@PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = {
|
@PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = {
|
||||||
@Preference(name = "favorites", type = Set.class, serializer = SetAbstractAppInfoPreferenceSerializer.class),
|
@Preference(name = "favorites", type = Set.class, serializer = SetAbstractAppInfoPreferenceSerializer.class),
|
||||||
|
@ -84,5 +83,8 @@ import eu.jonahbauer.android.preference.annotations.Preferences;
|
||||||
@PreferenceGroup(name = "actions", prefix = "settings_actions_", suffix = "_key", value = {
|
@PreferenceGroup(name = "actions", prefix = "settings_actions_", suffix = "_key", value = {
|
||||||
@Preference(name = "lock_method", type = LockMethod.class, defaultValue = "DEVICE_ADMIN"),
|
@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)
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
public final class LauncherPreferences$Config {}
|
public final class LauncherPreferences$Config {}
|
|
@ -76,7 +76,7 @@ fun resetPreferences(context: Context) {
|
||||||
LauncherPreferences.internal().versionCode(PREFERENCE_VERSION)
|
LauncherPreferences.internal().versionCode(PREFERENCE_VERSION)
|
||||||
deleteAllWidgets(context)
|
deleteAllWidgets(context)
|
||||||
|
|
||||||
LauncherPreferences.internal().widgets(
|
LauncherPreferences.widgets().widgets(
|
||||||
setOf(
|
setOf(
|
||||||
ClockWidget(-500, WidgetPosition(1,4,10,3))
|
ClockWidget(-500, WidgetPosition(1,4,10,3))
|
||||||
)
|
)
|
||||||
|
|
|
@ -44,16 +44,14 @@ class HomeActivity : UIObject, Activity() {
|
||||||
prefKey?.startsWith("display.") == true
|
prefKey?.startsWith("display.") == true
|
||||||
) {
|
) {
|
||||||
recreate()
|
recreate()
|
||||||
}
|
} else if (prefKey?.startsWith("action.") == true) {
|
||||||
|
|
||||||
if (prefKey?.startsWith("action.") == true) {
|
|
||||||
updateSettingsFallbackButtonVisibility()
|
updateSettingsFallbackButtonVisibility()
|
||||||
|
} else if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
|
binding.homeWidgetContainer.updateWidgets(this@HomeActivity,
|
||||||
|
LauncherPreferences.widgets().widgets()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefKey?.startsWith("internal.widgets") == true) {
|
|
||||||
binding.homeWidgetContainer.updateWidgets(this)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -77,7 +75,6 @@ class HomeActivity : UIObject, Activity() {
|
||||||
binding.buttonFallbackSettings.setOnClickListener {
|
binding.buttonFallbackSettings.setOnClickListener {
|
||||||
LauncherAction.SETTINGS.invoke(this)
|
LauncherAction.SETTINGS.invoke(this)
|
||||||
}
|
}
|
||||||
binding.homeWidgetContainer.updateWidgets(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
@ -98,7 +95,6 @@ class HomeActivity : UIObject, Activity() {
|
||||||
.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
|
.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
|
||||||
|
|
||||||
(application as Application).appWidgetHost.startListening()
|
(application as Application).appWidgetHost.startListening()
|
||||||
binding.homeWidgetContainer.updateWidgets(this)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +166,10 @@ class HomeActivity : UIObject, Activity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateSettingsFallbackButtonVisibility()
|
updateSettingsFallbackButtonVisibility()
|
||||||
|
|
||||||
|
binding.homeWidgetContainer.updateWidgets(this@HomeActivity,
|
||||||
|
LauncherPreferences.widgets().widgets()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -206,12 +206,6 @@ class HomeActivity : UIObject, Activity() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
|
||||||
// TODO: fix!
|
|
||||||
touchGestureDetector?.onTouchEvent(event)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
android.util.Log.e("Launcher", "on touch")
|
android.util.Log.e("Launcher", "on touch")
|
||||||
touchGestureDetector?.onTouchEvent(event)
|
touchGestureDetector?.onTouchEvent(event)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import de.jrpie.android.launcher.actions.openAppsList
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
import de.jrpie.android.launcher.preferences.theme.ColorTheme
|
||||||
import de.jrpie.android.launcher.setDefaultHomeScreen
|
import de.jrpie.android.launcher.setDefaultHomeScreen
|
||||||
|
import de.jrpie.android.launcher.ui.widgets.manage.ManageWidgetsActivity
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,6 +82,14 @@ class SettingsFragmentLauncher : PreferenceFragmentCompat() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val manageWidgets = findPreference<androidx.preference.Preference>(
|
||||||
|
LauncherPreferences.widgets().keys().widgets()
|
||||||
|
)
|
||||||
|
manageWidgets?.setOnPreferenceClickListener {
|
||||||
|
startActivity(Intent(requireActivity(), ManageWidgetsActivity::class.java))
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
val hiddenApps = findPreference<androidx.preference.Preference>(
|
val hiddenApps = findPreference<androidx.preference.Preference>(
|
||||||
LauncherPreferences.apps().keys().hidden()
|
LauncherPreferences.apps().keys().hidden()
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,34 +2,60 @@ package de.jrpie.android.launcher.ui.widgets
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.graphics.PointF
|
||||||
import android.os.Bundle
|
import android.graphics.RectF
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.SizeF
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
import android.view.View.MeasureSpec.makeMeasureSpec
|
import android.view.View.MeasureSpec.makeMeasureSpec
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.graphics.contains
|
||||||
import androidx.core.view.size
|
import androidx.core.view.size
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
|
|
||||||
// TODO: implement layout logic instead of linear layout
|
|
||||||
/**
|
/**
|
||||||
* This only works in an Activity, not AppCompatActivity
|
* This only works in an Activity, not AppCompatActivity
|
||||||
*/
|
*/
|
||||||
open class WidgetContainerView(context: Context, attrs: AttributeSet? = null) : ViewGroup(context, attrs) {
|
open class WidgetContainerView(context: Context, attrs: AttributeSet? = null) : ViewGroup(context, attrs) {
|
||||||
|
|
||||||
open fun updateWidgets(activity: Activity) {
|
var widgetViewById = HashMap<Int, View>()
|
||||||
|
|
||||||
|
open fun updateWidgets(activity: Activity, widgets: Set<Widget>?) {
|
||||||
|
if (widgets == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
Log.i("WidgetContainer", "updating ${activity.localClassName}")
|
Log.i("WidgetContainer", "updating ${activity.localClassName}")
|
||||||
|
widgetViewById.clear()
|
||||||
(0..<size).forEach { removeViewAt(0) }
|
(0..<size).forEach { removeViewAt(0) }
|
||||||
LauncherPreferences.internal().widgets()?.forEach { widget ->
|
widgets.forEach { widget ->
|
||||||
widget.createView(activity)?.let {
|
widget.createView(activity)?.let {
|
||||||
addView(it, WidgetContainerView.Companion.LayoutParams(widget.position))
|
addView(it, WidgetContainerView.Companion.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) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
|
|
||||||
var maxHeight = suggestedMinimumHeight
|
var maxHeight = suggestedMinimumHeight
|
||||||
|
@ -70,15 +96,11 @@ open class WidgetContainerView(context: Context, attrs: AttributeSet? = null) :
|
||||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||||
for (i in 0..<size) {
|
for (i in 0..<size) {
|
||||||
val child = getChildAt(i)
|
val child = getChildAt(i)
|
||||||
//if (child.visibility != GONE) {
|
val lp = child.layoutParams as LayoutParams
|
||||||
val lp = child.layoutParams as LayoutParams
|
val position = lp.position.getAbsoluteRect(r - l, b - t)
|
||||||
|
child.layout(position.left, position.top, position.right, position.bottom)
|
||||||
val position = lp.position.getAbsoluteRect(r - l, b - t)
|
|
||||||
Log.e("onLayout", "$l, $t, $r, $b, absolute rect: $position")
|
|
||||||
child.layout(position.left, position.top, position.right, position.bottom)
|
|
||||||
child.layoutParams.width = position.width()
|
child.layoutParams.width = position.width()
|
||||||
child.layoutParams.height = position.height()
|
child.layoutParams.height = position.height()
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,16 @@ import kotlin.math.min
|
||||||
const val REQUEST_CREATE_APPWIDGET = 1
|
const val REQUEST_CREATE_APPWIDGET = 1
|
||||||
const val REQUEST_PICK_APPWIDGET = 2
|
const val REQUEST_PICK_APPWIDGET = 2
|
||||||
|
|
||||||
|
// We can't use AppCompatActivity, since some AppWidgets don't work there.
|
||||||
class ManageWidgetsActivity : Activity(), UIObject {
|
class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
|
|
||||||
private var sharedPreferencesListener =
|
private var sharedPreferencesListener =
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
||||||
if (prefKey?.startsWith("internal.widgets") == true) {
|
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this)
|
// We can't observe the livedata because this is not an AppCompatActivity
|
||||||
|
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this,
|
||||||
|
LauncherPreferences.widgets().widgets()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +54,9 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this)
|
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this,
|
||||||
|
(application as Application).widgets.value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
@ -60,6 +66,14 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
LauncherPreferences.getSharedPreferences()
|
LauncherPreferences.getSharedPreferences()
|
||||||
.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
|
.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this,
|
||||||
|
LauncherPreferences.widgets().widgets()
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
override fun getTheme(): Resources.Theme {
|
override fun getTheme(): Resources.Theme {
|
||||||
val mTheme = modifyTheme(super.getTheme())
|
val mTheme = modifyTheme(super.getTheme())
|
||||||
|
@ -111,30 +125,19 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
)
|
)
|
||||||
|
|
||||||
val widget = AppWidget(appWidgetId, provider, position)
|
val widget = AppWidget(appWidgetId, provider, position)
|
||||||
LauncherPreferences.internal().widgets(
|
LauncherPreferences.widgets().widgets(
|
||||||
(LauncherPreferences.internal().widgets() ?: HashSet()).also {
|
(LauncherPreferences.widgets().widgets() ?: HashSet()).also {
|
||||||
it.add(widget)
|
it.add(widget)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configureWidget(data: Intent) {
|
private fun configureWidget(data: Intent) {
|
||||||
val extras = data.extras
|
val extras = data.extras
|
||||||
val appWidgetId = extras!!.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
|
val appWidgetId = extras!!.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
|
||||||
val appWidgetHost = (application as Application).appWidgetHost
|
val widget = AppWidget(appWidgetId)
|
||||||
val appWidgetInfo: AppWidgetProviderInfo =
|
if (widget.isConfigurable(this)) {
|
||||||
(application as Application).appWidgetManager.getAppWidgetInfo(appWidgetId) ?: return
|
widget.configure(this, REQUEST_CREATE_APPWIDGET)
|
||||||
if (appWidgetInfo.configure != null) {
|
|
||||||
appWidgetHost.startAppWidgetConfigureActivityForResult(
|
|
||||||
this,
|
|
||||||
appWidgetId,
|
|
||||||
0,
|
|
||||||
REQUEST_CREATE_APPWIDGET,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
createWidget(data)
|
createWidget(data)
|
||||||
}
|
}
|
||||||
|
@ -146,14 +149,12 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
) {
|
) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Log.i("Manage Widgets", "result ok")
|
|
||||||
if (requestCode == REQUEST_PICK_APPWIDGET) {
|
if (requestCode == REQUEST_PICK_APPWIDGET) {
|
||||||
configureWidget(data!!)
|
configureWidget(data!!)
|
||||||
} else if (requestCode == REQUEST_CREATE_APPWIDGET) {
|
} else if (requestCode == REQUEST_CREATE_APPWIDGET) {
|
||||||
createWidget(data!!)
|
createWidget(data!!)
|
||||||
}
|
}
|
||||||
} else if (resultCode == RESULT_CANCELED && data != null) {
|
} else if (resultCode == RESULT_CANCELED && data != null) {
|
||||||
Log.i("Manage Widgets", "result canceled")
|
|
||||||
val appWidgetId =
|
val appWidgetId =
|
||||||
data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
|
data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
|
||||||
if (appWidgetId != -1) {
|
if (appWidgetId != -1) {
|
||||||
|
|
|
@ -6,28 +6,21 @@ import android.content.Intent
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.enableEdgeToEdge
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import de.jrpie.android.launcher.R
|
import de.jrpie.android.launcher.R
|
||||||
import de.jrpie.android.launcher.databinding.ActivitySelectWidgetBinding
|
import de.jrpie.android.launcher.databinding.ActivitySelectWidgetBinding
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
|
||||||
import de.jrpie.android.launcher.ui.UIObject
|
import de.jrpie.android.launcher.ui.UIObject
|
||||||
import de.jrpie.android.launcher.widgets.ClockWidget
|
import de.jrpie.android.launcher.widgets.ClockWidget
|
||||||
import de.jrpie.android.launcher.widgets.LauncherAppWidgetProvider
|
import de.jrpie.android.launcher.widgets.LauncherAppWidgetProvider
|
||||||
import de.jrpie.android.launcher.widgets.LauncherClockWidgetProvider
|
import de.jrpie.android.launcher.widgets.LauncherClockWidgetProvider
|
||||||
import de.jrpie.android.launcher.widgets.LauncherWidgetProvider
|
import de.jrpie.android.launcher.widgets.LauncherWidgetProvider
|
||||||
import de.jrpie.android.launcher.widgets.Widget
|
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||||
import de.jrpie.android.launcher.widgets.bindAppWidgetOrRequestPermission
|
import de.jrpie.android.launcher.widgets.bindAppWidgetOrRequestPermission
|
||||||
import de.jrpie.android.launcher.widgets.getAppWidgetHost
|
import de.jrpie.android.launcher.widgets.getAppWidgetHost
|
||||||
|
@ -110,7 +103,6 @@ class SelectWidgetActivity : AppCompatActivity(), UIObject {
|
||||||
|
|
||||||
if (requestCode == REQUEST_WIDGET_PERMISSION && resultCode == RESULT_OK) {
|
if (requestCode == REQUEST_WIDGET_PERMISSION && resultCode == RESULT_OK) {
|
||||||
data ?: return
|
data ?: return
|
||||||
Log.i("SelectWidget", "permission granted")
|
|
||||||
val provider = (data.getSerializableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER) as? AppWidgetProviderInfo) ?: return
|
val provider = (data.getSerializableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER) as? AppWidgetProviderInfo) ?: return
|
||||||
tryBindWidget(LauncherAppWidgetProvider(provider))
|
tryBindWidget(LauncherAppWidgetProvider(provider))
|
||||||
}
|
}
|
||||||
|
@ -139,7 +131,7 @@ class SelectWidgetActivity : AppCompatActivity(), UIObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
|
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
|
||||||
val label = widgets[i].label
|
val label = widgets[i].loadLabel(this@SelectWidgetActivity)
|
||||||
val description = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
val description = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
widgets[i].loadDescription(this@SelectWidgetActivity)
|
widgets[i].loadDescription(this@SelectWidgetActivity)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package de.jrpie.android.launcher.ui.widgets.manage
|
package de.jrpie.android.launcher.ui.widgets.manage
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.appwidget.AppWidgetHostView
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
@ -18,7 +18,6 @@ import androidx.core.graphics.contains
|
||||||
import androidx.core.graphics.minus
|
import androidx.core.graphics.minus
|
||||||
import androidx.core.graphics.toRect
|
import androidx.core.graphics.toRect
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
|
||||||
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
||||||
import de.jrpie.android.launcher.widgets.Widget
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||||
|
@ -72,11 +71,12 @@ class WidgetManagerView(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
|
||||||
private val longPressHandler = Handler(Looper.getMainLooper())
|
private val longPressHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
|
||||||
onTouchEvent(ev)
|
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
override fun onTouchEvent(event: MotionEvent?): Boolean {
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
return false
|
return false
|
||||||
|
@ -91,7 +91,7 @@ class WidgetManagerView(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
|
||||||
val position = (view.layoutParams as Companion.LayoutParams).position.getAbsoluteRect(width, height)
|
val position = (view.layoutParams as Companion.LayoutParams).position.getAbsoluteRect(width, height)
|
||||||
selectedWidgetOverlayView = view
|
selectedWidgetOverlayView = view
|
||||||
selectedWidgetView = Widget.byId(view.widgetId)?.findView(children) ?: return true
|
selectedWidgetView = widgetViewById.get(view.widgetId) ?: return true
|
||||||
startWidgetPosition = position
|
startWidgetPosition = position
|
||||||
|
|
||||||
val positionInView = start.minus(Point(position.left, position.top))
|
val positionInView = start.minus(Point(position.left, position.top))
|
||||||
|
@ -136,7 +136,7 @@ class WidgetManagerView(context: Context, attrs: AttributeSet? = null) :
|
||||||
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
if (event.actionMasked == MotionEvent.ACTION_UP) {
|
||||||
longPressHandler.removeCallbacksAndMessages(null)
|
longPressHandler.removeCallbacksAndMessages(null)
|
||||||
val id = selectedWidgetOverlayView?.widgetId ?: return true
|
val id = selectedWidgetOverlayView?.widgetId ?: return true
|
||||||
val widget = Widget.byId(id) ?: return true
|
val widget = Widget.byId(context, id) ?: return true
|
||||||
widget.position = newPosition
|
widget.position = newPosition
|
||||||
endInteraction()
|
endInteraction()
|
||||||
updateWidget(widget)
|
updateWidget(widget)
|
||||||
|
@ -155,10 +155,13 @@ class WidgetManagerView(context: Context, attrs: AttributeSet? = null) :
|
||||||
selectedWidgetOverlayView?.mode = null
|
selectedWidgetOverlayView?.mode = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateWidgets(activity: Activity) {
|
override fun updateWidgets(activity: Activity, widgets: Set<Widget>?) {
|
||||||
super.updateWidgets(activity)
|
super.updateWidgets(activity, widgets)
|
||||||
|
if (widgets == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
LauncherPreferences.internal().widgets()?.forEach { widget ->
|
widgets.forEach { widget ->
|
||||||
WidgetOverlayView(activity).let {
|
WidgetOverlayView(activity).let {
|
||||||
addView(it)
|
addView(it)
|
||||||
it.widgetId = widget.id
|
it.widgetId = widget.id
|
||||||
|
|
|
@ -9,7 +9,9 @@ import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import androidx.core.graphics.toRectF
|
import androidx.core.graphics.toRectF
|
||||||
|
import de.jrpie.android.launcher.R
|
||||||
import de.jrpie.android.launcher.widgets.Widget
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
|
import de.jrpie.android.launcher.widgets.updateWidget
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An overlay to show configuration options for a widget.
|
* An overlay to show configuration options for a widget.
|
||||||
|
@ -29,11 +31,9 @@ class WidgetOverlayView : View {
|
||||||
handlePaint.style = Paint.Style.STROKE
|
handlePaint.style = Paint.Style.STROKE
|
||||||
handlePaint.setARGB(255, 255, 255, 255)
|
handlePaint.setARGB(255, 255, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
selectedHandlePaint.style = Paint.Style.FILL_AND_STROKE
|
selectedHandlePaint.style = Paint.Style.FILL_AND_STROKE
|
||||||
selectedHandlePaint.setARGB(100, 255, 255, 255)
|
selectedHandlePaint.setARGB(100, 255, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
paint.style = Paint.Style.STROKE
|
paint.style = Paint.Style.STROKE
|
||||||
paint.setARGB(255, 255, 255, 255)
|
paint.setARGB(255, 255, 255, 255)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class WidgetOverlayView : View {
|
||||||
var widgetId: Int = -1
|
var widgetId: Int = -1
|
||||||
set(newId) {
|
set(newId) {
|
||||||
field = newId
|
field = newId
|
||||||
preview = Widget.byId(widgetId)?.getPreview(context)
|
preview = Widget.byId(context, widgetId)?.getPreview(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(context: Context) : super(context) {
|
constructor(context: Context) : super(context) {
|
||||||
|
@ -74,7 +74,7 @@ class WidgetOverlayView : View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val bounds = getBounds()
|
val bounds = getBounds()
|
||||||
canvas.drawRect(bounds, paint)
|
canvas.drawRoundRect(bounds.toRectF(), 5f, 5f, paint)
|
||||||
|
|
||||||
if (mode == null) {
|
if (mode == null) {
|
||||||
return
|
return
|
||||||
|
@ -87,16 +87,26 @@ class WidgetOverlayView : View {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showPopupMenu() {
|
fun showPopupMenu() {
|
||||||
|
val widget = Widget.byId(context, widgetId)?: return
|
||||||
val menu = PopupMenu(context, this)
|
val menu = PopupMenu(context, this)
|
||||||
menu.menu.let {
|
menu.menu.let {
|
||||||
it.add("Remove").setOnMenuItemClickListener { _ ->
|
it.add(
|
||||||
Widget.byId(widgetId)?.delete(context)
|
context.getString(R.string.widget_menu_remove)
|
||||||
|
).setOnMenuItemClickListener { _ ->
|
||||||
|
Widget.byId(context, widgetId)?.delete(context)
|
||||||
return@setOnMenuItemClickListener true
|
return@setOnMenuItemClickListener true
|
||||||
}
|
}
|
||||||
it.add("Allow Interaction").setOnMenuItemClickListener { _ ->
|
it.add(
|
||||||
return@setOnMenuItemClickListener true
|
if (widget.allowInteraction) {
|
||||||
|
context.getString(R.string.widget_menu_disable_interaction)
|
||||||
|
} else {
|
||||||
|
context.getString(R.string.widget_menu_enable_interaction)
|
||||||
}
|
}
|
||||||
it.add("Add Padding")
|
).setOnMenuItemClickListener { _ ->
|
||||||
|
widget.allowInteraction = !widget.allowInteraction
|
||||||
|
updateWidget(widget)
|
||||||
|
return@setOnMenuItemClickListener true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
menu.show()
|
menu.show()
|
||||||
}
|
}
|
||||||
|
@ -118,5 +128,4 @@ class WidgetOverlayView : View {
|
||||||
private fun getBounds(): Rect {
|
private fun getBounds(): Rect {
|
||||||
return Rect(0,0, width, height)
|
return Rect(0,0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,32 +1,26 @@
|
||||||
package de.jrpie.android.launcher.widgets;
|
package de.jrpie.android.launcher.widgets;
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.appwidget.AppWidgetHost
|
|
||||||
import android.appwidget.AppWidgetHostView
|
import android.appwidget.AppWidgetHostView
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.appwidget.AppWidgetProviderInfo
|
import android.appwidget.AppWidgetProviderInfo
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
|
||||||
import android.util.SizeF
|
import android.util.SizeF
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import de.jrpie.android.launcher.Application
|
import de.jrpie.android.launcher.Application
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.ui.HomeActivity
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("widget:app")
|
@SerialName("widget:app")
|
||||||
class AppWidget(
|
class AppWidget(
|
||||||
override val id: Int,
|
override val id: Int,
|
||||||
override var position: WidgetPosition = WidgetPosition(0,0,1,1),
|
override var position: WidgetPosition = WidgetPosition(0,0,1,1),
|
||||||
|
override var allowInteraction: Boolean = false,
|
||||||
|
|
||||||
// We keep track of packageName, className and user to make it possible to restore the widget
|
// 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)
|
// on a new device when restoring settings (currently not implemented)
|
||||||
|
@ -39,7 +33,9 @@ class AppWidget(
|
||||||
|
|
||||||
constructor(id: Int, widgetProviderInfo: AppWidgetProviderInfo, position: WidgetPosition) :
|
constructor(id: Int, widgetProviderInfo: AppWidgetProviderInfo, position: WidgetPosition) :
|
||||||
this(
|
this(
|
||||||
id, position,
|
id,
|
||||||
|
position,
|
||||||
|
false,
|
||||||
widgetProviderInfo.provider.packageName,
|
widgetProviderInfo.provider.packageName,
|
||||||
widgetProviderInfo.provider.className,
|
widgetProviderInfo.provider.className,
|
||||||
widgetProviderInfo.profile.hashCode()
|
widgetProviderInfo.profile.hashCode()
|
||||||
|
@ -105,4 +101,20 @@ class AppWidget(
|
||||||
override fun getPreview(context: Context): Drawable? {
|
override fun getPreview(context: Context): Drawable? {
|
||||||
return context.getAppWidgetManager().getAppWidgetInfo(id)?.loadPreviewImage(context, DisplayMetrics.DENSITY_HIGH)
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,11 @@ import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("widget:clock")
|
@SerialName("widget:clock")
|
||||||
class ClockWidget(override val id: Int, override var position: WidgetPosition): Widget() {
|
class ClockWidget(
|
||||||
|
override val id: Int,
|
||||||
|
override var position: WidgetPosition,
|
||||||
|
override var allowInteraction: Boolean = true
|
||||||
|
) : Widget() {
|
||||||
|
|
||||||
override fun createView(activity: Activity): View? {
|
override fun createView(activity: Activity): View? {
|
||||||
return ClockView(activity, null, id)
|
return ClockView(activity, null, id)
|
||||||
|
@ -28,4 +32,10 @@ class ClockWidget(override val id: Int, override var position: WidgetPosition):
|
||||||
override fun getIcon(context: Context): Drawable? {
|
override fun getIcon(context: Context): Drawable? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isConfigurable(context: Context): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configure(activity: Activity, requestCode: Int) { }
|
||||||
}
|
}
|
|
@ -5,17 +5,21 @@ import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
|
import de.jrpie.android.launcher.R
|
||||||
|
|
||||||
sealed class LauncherWidgetProvider {
|
sealed class LauncherWidgetProvider {
|
||||||
abstract val label: String?
|
abstract fun loadLabel(context: Context): CharSequence?
|
||||||
|
|
||||||
abstract fun loadPreviewImage(context: Context): Drawable?
|
abstract fun loadPreviewImage(context: Context): Drawable?
|
||||||
abstract fun loadIcon(context: Context): Drawable?
|
abstract fun loadIcon(context: Context): Drawable?
|
||||||
abstract fun loadDescription(context: Context): CharSequence?
|
abstract fun loadDescription(context: Context): CharSequence?
|
||||||
}
|
}
|
||||||
|
|
||||||
class LauncherAppWidgetProvider(val info: AppWidgetProviderInfo) : LauncherWidgetProvider() {
|
class LauncherAppWidgetProvider(val info: AppWidgetProviderInfo) : LauncherWidgetProvider() {
|
||||||
override val label: String? = info.label
|
|
||||||
|
override fun loadLabel(context: Context): CharSequence? {
|
||||||
|
return info.loadLabel(context.packageManager)
|
||||||
|
}
|
||||||
override fun loadPreviewImage(context: Context): Drawable? {
|
override fun loadPreviewImage(context: Context): Drawable? {
|
||||||
return info.loadPreviewImage(context, DisplayMetrics.DENSITY_DEFAULT)
|
return info.loadPreviewImage(context, DisplayMetrics.DENSITY_DEFAULT)
|
||||||
}
|
}
|
||||||
|
@ -34,19 +38,21 @@ class LauncherAppWidgetProvider(val info: AppWidgetProviderInfo) : LauncherWidge
|
||||||
|
|
||||||
}
|
}
|
||||||
class LauncherClockWidgetProvider : LauncherWidgetProvider() {
|
class LauncherClockWidgetProvider : LauncherWidgetProvider() {
|
||||||
override val label: String?
|
|
||||||
get() = "Clock"
|
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? {
|
override fun loadPreviewImage(context: Context): Drawable? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadIcon(context: Context): Drawable? {
|
override fun loadIcon(context: Context): Drawable? {
|
||||||
return null
|
return AppCompatResources.getDrawable(context, R.drawable.baseline_clock_24)
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadDescription(context: Context): CharSequence? {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import de.jrpie.android.launcher.Application
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
@ -13,6 +14,7 @@ import kotlinx.serialization.json.Json
|
||||||
sealed class Widget {
|
sealed class Widget {
|
||||||
abstract val id: Int
|
abstract val id: Int
|
||||||
abstract var position: WidgetPosition
|
abstract var position: WidgetPosition
|
||||||
|
abstract var allowInteraction: Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param activity The activity where the view will be used. Must not be an AppCompatActivity.
|
* @param activity The activity where the view will be used. Must not be an AppCompatActivity.
|
||||||
|
@ -21,12 +23,14 @@ sealed class Widget {
|
||||||
abstract fun findView(views: Sequence<View>): View?
|
abstract fun findView(views: Sequence<View>): View?
|
||||||
abstract fun getPreview(context: Context): Drawable?
|
abstract fun getPreview(context: Context): Drawable?
|
||||||
abstract fun getIcon(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) {
|
fun delete(context: Context) {
|
||||||
context.getAppWidgetHost().deleteAppWidgetId(id)
|
context.getAppWidgetHost().deleteAppWidgetId(id)
|
||||||
|
|
||||||
LauncherPreferences.internal().widgets(
|
LauncherPreferences.widgets().widgets(
|
||||||
LauncherPreferences.internal().widgets()?.also {
|
LauncherPreferences.widgets().widgets()?.also {
|
||||||
it.remove(this)
|
it.remove(this)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -47,9 +51,10 @@ sealed class Widget {
|
||||||
fun deserialize(serialized: String): Widget {
|
fun deserialize(serialized: String): Widget {
|
||||||
return Json.decodeFromString(serialized)
|
return Json.decodeFromString(serialized)
|
||||||
}
|
}
|
||||||
fun byId(id: Int): Widget? {
|
fun byId(context: Context, id: Int): Widget? {
|
||||||
return (LauncherPreferences.internal().widgets() ?: setOf())
|
return (context.applicationContext as Application).widgets.value?.firstOrNull {
|
||||||
.firstOrNull { it.id == id }
|
it.id == id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,17 +3,14 @@ package de.jrpie.android.launcher.widgets
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.appwidget.AppWidgetHost
|
import android.appwidget.AppWidgetHost
|
||||||
import android.appwidget.AppWidgetHostView
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.appwidget.AppWidgetProviderInfo
|
import android.appwidget.AppWidgetProviderInfo
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.LauncherApps
|
import android.content.pm.LauncherApps
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.SizeF
|
|
||||||
import de.jrpie.android.launcher.Application
|
import de.jrpie.android.launcher.Application
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
|
|
||||||
|
@ -77,9 +74,9 @@ fun getAppWidgetProviders( context: Context ): List<LauncherWidgetProvider> {
|
||||||
|
|
||||||
|
|
||||||
fun updateWidget(widget: Widget) {
|
fun updateWidget(widget: Widget) {
|
||||||
var widgets = LauncherPreferences.internal().widgets() ?: setOf()
|
var widgets = LauncherPreferences.widgets().widgets() ?: setOf()
|
||||||
widgets = widgets.minus(widget).plus(widget)
|
widgets = widgets.minus(widget).plus(widget)
|
||||||
LauncherPreferences.internal().widgets(widgets)
|
LauncherPreferences.widgets().widgets(widgets)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getAppWidgetHost(): AppWidgetHost {
|
fun Context.getAppWidgetHost(): AppWidgetHost {
|
||||||
|
|
15
app/src/main/res/drawable/baseline_clock_24.xml
Normal file
15
app/src/main/res/drawable/baseline_clock_24.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="?android:textColor"
|
||||||
|
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z" />
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="?android:textColor"
|
||||||
|
android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z" />
|
||||||
|
|
||||||
|
</vector>
|
|
@ -9,7 +9,7 @@
|
||||||
<string name="settings_internal_started_key" translatable="false">internal.started_before</string>
|
<string name="settings_internal_started_key" translatable="false">internal.started_before</string>
|
||||||
<string name="settings_internal_started_time_key" translatable="false">internal.first_startup</string>
|
<string name="settings_internal_started_time_key" translatable="false">internal.first_startup</string>
|
||||||
<string name="settings_internal_version_code_key" translatable="false">internal.version_code</string>
|
<string name="settings_internal_version_code_key" translatable="false">internal.version_code</string>
|
||||||
<string name="settings_internal_widgets_key" translatable="false">internal.widgets</string>
|
<string name="settings_widgets_widgets_key" translatable="false">widgets.widgets</string>
|
||||||
<string name="settings_apps_favorites_key" translatable="false">apps.favorites</string>
|
<string name="settings_apps_favorites_key" translatable="false">apps.favorites</string>
|
||||||
<string name="settings_apps_hidden_key" translatable="false">apps.hidden</string>
|
<string name="settings_apps_hidden_key" translatable="false">apps.hidden</string>
|
||||||
<string name="settings_apps_pinned_shortcuts_key" translatable="false">apps.pinned_shortcuts</string>
|
<string name="settings_apps_pinned_shortcuts_key" translatable="false">apps.pinned_shortcuts</string>
|
||||||
|
|
|
@ -98,6 +98,8 @@
|
||||||
<string name="settings_gesture_time">Time</string>
|
<string name="settings_gesture_time">Time</string>
|
||||||
<string name="settings_gesture_description_time">Click on time</string>
|
<string name="settings_gesture_description_time">Click on time</string>
|
||||||
|
|
||||||
|
<string name="settings_widgets_widgets">Manage widgets</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="settings_apps_choose">Choose App</string>
|
<string name="settings_apps_choose">Choose App</string>
|
||||||
|
|
||||||
|
@ -390,4 +392,13 @@
|
||||||
<string name="toast_activity_not_found_browser">Can\'t open URL: no browser found.</string>
|
<string name="toast_activity_not_found_browser">Can\'t open URL: no browser found.</string>
|
||||||
<string name="select_widget_title">Choose Widget</string>
|
<string name="select_widget_title">Choose Widget</string>
|
||||||
|
|
||||||
|
<string name="widget_menu_remove">Remove</string>
|
||||||
|
<string name="widget_menu_configure">Configure</string>
|
||||||
|
<string name="widget_menu_enable_interaction">Enable Interaction</string>
|
||||||
|
<string name="widget_menu_disable_interaction">Disable Interaction</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="widget_clock_label">Clock</string>
|
||||||
|
<string name="widget_clock_description">The default clock of μLauncher</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<Preference
|
<Preference
|
||||||
android:key="@string/settings_general_choose_home_screen_key"
|
android:key="@string/settings_general_choose_home_screen_key"
|
||||||
android:title="@string/settings_general_choose_home_screen"/>
|
android:title="@string/settings_general_choose_home_screen"/>
|
||||||
|
<Preference
|
||||||
|
android:key="@string/settings_widgets_widgets_key"
|
||||||
|
android:title="@string/settings_widgets_widgets"/>
|
||||||
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue