Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Verified Commit dbe7c5ff authored by Abhishek Aggarwal's avatar Abhishek Aggarwal Committed by Yash Garg
Browse files

(feat) widgets: properly migrate widget host

parent f9935601
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID
import com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME
import com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME_ALL
import com.android.launcher3.shortcuts.ShortcutKey
import foundation.e.bliss.widgets.DefaultWidgets
import java.net.URISyntaxException

object BlissDbUtils {
@@ -260,11 +259,6 @@ object BlissDbUtils {
                        if (widgetInfo != null) {
                            var provider: ComponentName = widgetInfo.provider

                            // Weather app component name has changed.
                            if (provider == DefaultWidgets.oldWeatherWidget) {
                                provider = DefaultWidgets.weatherWidget
                            }

                            widgetsInfoList.add(
                                WidgetItems(
                                    id,
+11 −0
Original line number Diff line number Diff line
@@ -10,10 +10,12 @@ package foundation.e.bliss.utils
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.os.Handler
import android.os.Looper
import android.os.UserHandle
@@ -94,3 +96,12 @@ fun getUninstallTarget(launcher: Launcher, item: ItemInfo?): ComponentName? {
    }
    return null
}

fun disableComponent(context: Context, componentName: ComponentName) {
    val packageManager = context.packageManager
    packageManager.setComponentEnabledSetting(
        componentName,
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP
    )
}
+2 −2
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ class BlissAppWidgetHost(val context: Context) : AppWidgetHost(context, WIDGET_H
        appWidgetId: Int,
        appWidget: AppWidgetProviderInfo?
    ): AppWidgetHostView {
        val blur = DefaultWidgets.getWidgetsList(context).contains(appWidget?.provider)
        val blur = DefaultWidgets.defaultWidgets.contains(appWidget?.provider)
        return RoundedWidgetView(context, blur)
    }

@@ -37,7 +37,7 @@ class BlissAppWidgetHost(val context: Context) : AppWidgetHost(context, WIDGET_H

    companion object {
        const val TAG = "BlissAppWidgetHost"
        const val WIDGET_HOST_ID = 1040
        const val WIDGET_HOST_ID = 0x7f090001
        const val REQUEST_CONFIGURE_APPWIDGET = 1041
    }
}
+1 −29
Original line number Diff line number Diff line
@@ -8,9 +8,6 @@
package foundation.e.bliss.widgets

import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import foundation.e.bliss.utils.BlissDbUtils

object DefaultWidgets {
    private val ecloudWidget =
@@ -28,30 +25,5 @@ object DefaultWidgets {
            "foundation.e.blissweather.widget.WeatherAppWidgetProvider"
        )

    private val widgets = listOf(ecloudWidget, privacyWidget, weatherWidget)

    @JvmStatic
    fun getWidgetsList(context: Context): List<ComponentName> {
        val providerList: MutableList<ComponentName> = mutableListOf()

        // Get widget details from old database
        val widgetItemsList: MutableList<BlissDbUtils.WidgetItems> =
            BlissDbUtils.getWidgetDetails(context)

        for (widgetItem in widgetItemsList) {
            val provider = widgetItem.componentName
            provider.let(providerList::add)
        }

        // Disable dummy widget provider component after widgets listed.
        val packageManager = context.packageManager
        packageManager.setComponentEnabledSetting(
            oldWeatherWidget,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
        )

        // Return default widgets if the providerList is empty
        return providerList.ifEmpty { widgets }
    }
    val defaultWidgets = listOf(ecloudWidget, privacyWidget, weatherWidget)
}
+77 −15
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.Toast
import com.android.internal.appwidget.IAppWidgetService
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.Launcher
import com.android.launcher3.PendingAddItemInfo
import com.android.launcher3.R
@@ -44,8 +45,10 @@ import com.android.launcher3.widget.WidgetCell
import com.android.launcher3.widget.picker.WidgetsFullSheet
import foundation.e.bliss.LauncherAppMonitor
import foundation.e.bliss.LauncherAppMonitorCallback
import foundation.e.bliss.utils.BlissDbUtils
import foundation.e.bliss.utils.Logger
import foundation.e.bliss.utils.ObservableList
import foundation.e.bliss.utils.disableComponent
import foundation.e.bliss.widgets.BlissAppWidgetHost.Companion.REQUEST_CONFIGURE_APPWIDGET
import io.reactivex.rxjava3.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
@@ -126,10 +129,11 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
    class WidgetFragment : FragmentWithPreview() {
        private lateinit var mWrapper: LinearLayout
        private lateinit var widgetObserver: Disposable
        private lateinit var widgetsDbHelper: WidgetsDbHelper

        private val mOldWidgets by lazy { BlissDbUtils.getWidgetDetails(context) }
        private val mWidgetManager by lazy { AppWidgetManager.getInstance(context) }
        private val mWidgetHost by lazy { BlissAppWidgetHost(context) }
        private val widgetsDbHelper by lazy { WidgetsDbHelper.getInstance(context) }
        private val launcher by lazy { Launcher.getLauncher(context) }

        private val mAppMonitorCallback: LauncherAppMonitorCallback =
@@ -161,6 +165,8 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View {
            widgetsDbHelper = WidgetsDbHelper.getInstance(context)

            mWrapper =
                LinearLayout(context, null).apply {
                    tag = "wrapper_children"
@@ -168,8 +174,8 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
                }

            if (isQsbEnabled) {
                loadWidgets()
                mWidgetHost.startListening()
                loadWidgets()
            }

            return mWrapper
@@ -179,19 +185,28 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
            super.onViewCreated(view, savedInstanceState)
        }

        override fun onDestroyView() {
            mWidgetHost.stopListening()
            super.onDestroyView()
        }

        private fun loadWidgets() {
            if (!initialWidgetsAdded) {
                val oldWidgets = mWidgetHost.appWidgetIds
                if (oldWidgets.isEmpty()) {
                    mWidgetHost.deleteHost()
                Logger.e(TAG, "default not added ${mWidgetHost.appWidgetIds.size}")

                DefaultWidgets.getWidgetsList(context).forEach {
                    DefaultWidgets.defaultWidgets.forEach {
                        try {
                            bindWidget(it)
                        } catch (e: Exception) {
                            Logger.e(TAG, "Could not add widget ${it.flattenToString()}")
                        }
                    }
                } else {
                    rebindWidgets(true)
                }

                disableComponent(context, DefaultWidgets.oldWeatherWidget)
                initialWidgetsAdded = true
            } else {
                rebindWidgets()
@@ -207,9 +222,21 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
            CoroutineScope(Dispatchers.Main).launch { eventFlow.collect { rebindWidgets() } }
        }

        private fun rebindWidgets() {
        private fun rebindWidgets(backup: Boolean = false) {
            mWrapper.removeAllViews()
            mWidgetHost.appWidgetIds.sorted().forEach(::addView)
            if (!backup) {
                widgetsDbHelper
                    .getWidgets()
                    .sortedBy { it.position }
                    .forEach { addView(it.widgetId, false) }
            } else {
                mOldWidgets
                    .filter { mWidgetHost.appWidgetIds.contains(it.id) }
                    .sortedWith(
                        compareBy(BlissDbUtils.WidgetItems::order, BlissDbUtils.WidgetItems::id)
                    )
                    .forEach { addView(it.id, true) }
            }
        }

        private fun bindWidget(provider: ComponentName) {
@@ -242,7 +269,7 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
            }
        }

        private fun addView(widgetId: Int) {
        private fun addView(widgetId: Int, backup: Boolean = false) {
            val info =
                LauncherAppWidgetProviderInfo.fromProviderInfo(
                    launcher,
@@ -274,7 +301,42 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
                                opts.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
                            )

                        Logger.d(TAG, "Widget height: ${params.height} | opts: $opts")
                        if (backup) {
                            if (it.appWidgetInfo.provider.equals(DefaultWidgets.oldWeatherWidget)) {
                                mWidgetHost.deleteAppWidgetId(it.id)

                                // Swap with new widget
                                bindWidget(DefaultWidgets.weatherWidget)
                                return
                            }
                            val oldHeight =
                                if (mOldWidgets.isNotEmpty()) {
                                    mOldWidgets
                                        .find { widgetItems -> widgetItems.id == widgetId }
                                        ?.height
                                } else {
                                    0
                                }
                            val minHeight: Int = info.minResizeHeight
                            val maxHeight: Int =
                                InvariantDeviceProfile.INSTANCE.get(context)
                                    .getDeviceProfile(context)
                                    .heightPx * 3 / 4
                            val normalisedDifference = (maxHeight - minHeight) / 100

                            if (oldHeight != null && oldHeight > 0) {
                                params.height = minHeight + normalisedDifference * oldHeight
                            } else {
                                params.height = 0
                            }
                            opts.remove(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
                            opts.remove(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
                            opts.remove(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
                            opts.remove(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
                            it.updateAppWidgetOptions(opts)
                        } else {
                            params.height = widgetsDbHelper.getWidgetHeight(it.id) ?: 0
                        }

                        if (params.height > 0) {
                            mWrapper.addView(it, params)
@@ -287,7 +349,7 @@ class WidgetContainer(context: Context, attrs: AttributeSet?) : FrameLayout(cont
                                mWrapper.indexOfChild(it),
                                it.appWidgetInfo.provider,
                                it.appWidgetId,
                                it.height
                                params.height
                            )
                        )
                    }
Loading