Simplify ActivityStarter and remove app start animation preference

This commit is contained in:
MM20 2022-01-29 19:15:05 +01:00
parent f5b21e4fe6
commit 189ea7dbb5
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
29 changed files with 50 additions and 374 deletions

View File

@ -1,99 +0,0 @@
package de.mm20.launcher2.ui.preferences
import android.animation.Animator
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.postDelayed
import androidx.preference.Preference
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.airbnb.lottie.LottieAnimationView
import de.mm20.launcher2.R
import de.mm20.launcher2.preferences.AppStartAnimation
import de.mm20.launcher2.preferences.LauncherPreferences
class AppStartAnimPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.preferenceStyle) : Preference(context, attrs, defStyleAttr) {
init {
summary = getNameForAnimation(LauncherPreferences.instance.appStartAnim)
setOnPreferenceClickListener {
val anims = mutableListOf(
AppStartAnimation.M to R.raw.app_start_anim_m,
AppStartAnimation.SLIDE_BOTTOM to R.raw.app_start_anim_slide_bottom,
AppStartAnimation.FADE to R.raw.app_start_anim_fade
)
val dialog = MaterialDialog(context)
val layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val list = LinearLayout(context)
list.orientation = LinearLayout.VERTICAL
anims.forEachIndexed { _, anim ->
val view = View.inflate(context, R.layout.preference_start_anim_item, null)
view.findViewById<LottieAnimationView>(R.id.icon).also { iconView ->
iconView.setAnimation(anim.second)
iconView.addAnimatorListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator) {
iconView.postDelayed(500) {
iconView.frame = 0
}
iconView.postDelayed(1300) {
iconView.playAnimation()
}
}
override fun onAnimationCancel(animation: Animator?) {
}
override fun onAnimationStart(animation: Animator?) {
}
})
iconView.postDelayed(300) {
iconView.playAnimation()
}
}
view.findViewById<TextView>(R.id.label).also { labelView ->
labelView.setText(getNameForAnimation(anim.first))
}
view.layoutParams = layoutParams
list.addView(view)
view.setOnClickListener {
LauncherPreferences.instance.appStartAnim = anim.first
summary = getNameForAnimation(anim.first)
dialog.dismiss()
}
}
dialog.customView(view = list, scrollable = true)
.title(R.string.preference_app_start_animation)
.negativeButton(android.R.string.cancel) {
dialog.cancel()
}
.show()
true
}
}
private fun getNameForAnimation(anim: AppStartAnimation): String {
return when (anim) {
AppStartAnimation.FADE -> context.getString(R.string.preference_app_start_animation_fade)
AppStartAnimation.SLIDE_BOTTOM -> context.getString(R.string.preference_app_start_animation_slide_bottom)
AppStartAnimation.M -> context.getString(R.string.preference_app_start_animation_m)
else -> context.getString(R.string.preference_app_start_animation_default)
}
}
}

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:foreground="?selectableItemBackground"
android:orientation="horizontal">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/icon"
android:background="@color/blue"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_vertical"
tools:rawRes="@raw/app_start_anim_fade"/>
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:layout_gravity="center_vertical"
tools:text="Fade"/>
</LinearLayout>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -56,7 +56,6 @@
app:title="@string/preference_icon_shape" /> app:title="@string/preference_icon_shape" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/preference_category_animations"> <PreferenceCategory app:title="@string/preference_category_animations">
<de.mm20.launcher2.ui.preferences.AppStartAnimPreference app:title="@string/preference_app_start_animation" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/preference_category_searchbar"> <PreferenceCategory app:title="@string/preference_category_searchbar">
<ListPreference <ListPreference

View File

@ -164,5 +164,4 @@ message Settings {
bool lightNavBar = 2; bool lightNavBar = 2;
} }
SystemBarsSettings system_bars = 23; SystemBarsSettings system_bars = 23;
} }

View File

@ -262,10 +262,13 @@ dependencyResolutionManagement {
.to("com.google.android.material", "compose-theme-adapter") .to("com.google.android.material", "compose-theme-adapter")
.version("1.1.1") .version("1.1.1")
version("lottie", "4.1.0") version("lottie", "4.2.2")
alias("lottie.core") alias("lottie.core")
.to("com.airbnb.android", "lottie") .to("com.airbnb.android", "lottie")
.versionRef("lottie") .versionRef("lottie")
alias("lottie.compose")
.to("com.airbnb.android", "lottie-compose")
.versionRef("lottie")
alias("okhttp") alias("okhttp")
.to("com.squareup.okhttp3", "okhttp") .to("com.squareup.okhttp3", "okhttp")

View File

@ -67,6 +67,8 @@ dependencies {
implementation(libs.composecolorpicker) implementation(libs.composecolorpicker)
implementation(libs.lottie.compose)
// Legacy dependencies // Legacy dependencies
implementation(libs.androidx.transition) implementation(libs.androidx.transition)
@ -76,7 +78,6 @@ dependencies {
implementation(libs.viewpropertyobjectanimator) implementation(libs.viewpropertyobjectanimator)
implementation(libs.draglinearlayout) implementation(libs.draglinearlayout)
implementation(libs.lottie.core)
implementation(libs.accompanist.insets) implementation(libs.accompanist.insets)
implementation(libs.accompanist.systemuicontroller) implementation(libs.accompanist.systemuicontroller)

View File

@ -1,6 +1,7 @@
package de.mm20.launcher2.ui.base package de.mm20.launcher2.ui.base
import android.os.Bundle import android.os.Bundle
import android.view.Window
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate

View File

@ -14,18 +14,13 @@ import com.afollestad.materialdialogs.callbacks.onDismiss
import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.customView
import de.mm20.launcher2.icons.DynamicIconController import de.mm20.launcher2.icons.DynamicIconController
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.base.BaseActivity import de.mm20.launcher2.ui.base.BaseActivity
import de.mm20.launcher2.ui.databinding.ActivityLauncherBinding import de.mm20.launcher2.ui.databinding.ActivityLauncherBinding
import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView
import de.mm20.launcher2.ui.launcher.modals.HiddenItemsView import de.mm20.launcher2.ui.launcher.modals.HiddenItemsView
import kotlinx.coroutines.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.core.component.inject
import java.util.*
class LauncherActivity : BaseActivity() { class LauncherActivity : BaseActivity() {
@ -114,7 +109,6 @@ class LauncherActivity : BaseActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
ActivityStarter.resume()
ActivityStarter.create(binding.rootView) ActivityStarter.create(binding.rootView)
binding.activityStartOverlay.visibility = View.INVISIBLE binding.activityStartOverlay.visibility = View.INVISIBLE
@ -123,18 +117,8 @@ class LauncherActivity : BaseActivity() {
} }
} }
override fun onPause() {
super.onPause()
ActivityStarter.pause()
}
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)
onBackPressed() onBackPressed()
} }
override fun onDestroy() {
super.onDestroy()
ActivityStarter.destroy()
}
} }

View File

@ -17,7 +17,7 @@ import coil.size.Scale
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Websearch import de.mm20.launcher2.search.data.Websearch
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.databinding.ViewWebsearchBinding import de.mm20.launcher2.ui.databinding.ViewWebsearchBinding

View File

@ -9,7 +9,7 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Website import de.mm20.launcher2.search.data.Website
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchVM import de.mm20.launcher2.ui.launcher.search.SearchVM

View File

@ -8,7 +8,7 @@ import android.widget.FrameLayout
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Wikipedia import de.mm20.launcher2.search.data.Wikipedia
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchVM import de.mm20.launcher2.ui.launcher.search.SearchVM

View File

@ -1,6 +1,5 @@
package de.mm20.launcher2.legacy.helper package de.mm20.launcher2.ui.legacy.helper
import android.animation.AnimatorSet
import android.app.PendingIntent import android.app.PendingIntent
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
@ -9,13 +8,9 @@ import android.graphics.Rect
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewGroupOverlay import android.view.ViewGroupOverlay
import android.view.animation.AccelerateInterpolator
import android.widget.Toast import android.widget.Toast
import androidx.core.app.ActivityOptionsCompat import androidx.core.app.ActivityOptionsCompat
import com.bartoszlipinski.viewpropertyobjectanimator.ViewPropertyObjectAnimator
import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.favorites.FavoritesRepository
import de.mm20.launcher2.preferences.AppStartAnimation
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
@ -24,26 +19,13 @@ import java.lang.ref.WeakReference
object ActivityStarter : KoinComponent { object ActivityStarter : KoinComponent {
val favoritesRepository: FavoritesRepository by inject() private val favoritesRepository: FavoritesRepository by inject()
private var initialized = false
private lateinit var overlayView: WeakReference<ViewGroupOverlay> private lateinit var overlayView: WeakReference<ViewGroupOverlay>
private lateinit var rootView: WeakReference<ViewGroup> private lateinit var rootView: WeakReference<ViewGroup>
const val ANIM_SPLASH1 = 0
const val ANIM_SPLASH2 = 1
const val ANIM_M = 2
const val ANIM_FADE = 3
const val ANIM_SLIDE_BOTTOM = 4
private lateinit var animationStyle: AppStartAnimation
fun create(rootView: ViewGroup) { fun create(rootView: ViewGroup) {
this.rootView = WeakReference(rootView) ActivityStarter.rootView = WeakReference(rootView)
this.overlayView = WeakReference(rootView.overlay) overlayView = WeakReference(rootView.overlay)
onResumeCallback = null
animationStyle = LauncherPreferences.instance.appStartAnim
initialized = true
} }
fun start( fun start(
@ -53,87 +35,11 @@ object ActivityStarter : KoinComponent {
intent: Intent? = null, intent: Intent? = null,
pendingIntent: PendingIntent? = null pendingIntent: PendingIntent? = null
): Boolean { ): Boolean {
if (!initialized) throw IllegalStateException("Item starter has not been initialized properly.")
if (!startActivity(context, item, intent, pendingIntent, transitionView)) return false if (!startActivity(context, item, intent, pendingIntent, transitionView)) return false
if (animationStyle == AppStartAnimation.SLIDE_BOTTOM || animationStyle == AppStartAnimation.FADE ||
animationStyle == AppStartAnimation.M
) {
return true
}
val rootView = rootView.get() ?: return true
val background = rootView.findViewById<View>(R.id.activityStartOverlay)
background.pivotX = background.width * 0.5f
background.pivotY = background.height * 0.5f
val searchView = rootView.findViewById<View>(R.id.container)
val parent = transitionView.parent as ViewGroup
val index = parent.indexOfChild(transitionView)
overlayView.get()?.add(transitionView)
val bounds = Rect()
transitionView.getGlobalVisibleRect(bounds)
val scale = (rootView.width).toFloat() / transitionView.width
//val x = bounds.left.toFloat()
//val y = bounds.top.toFloat()
val x = (rootView.width - transitionView.width) * 0.5f - transitionView.x
val y = (rootView.height - transitionView.height) * 0.5f - transitionView.y
background.visibility = View.VISIBLE
background.scaleX = transitionView.width.toFloat() / background.width
background.scaleY = transitionView.height.toFloat() / background.height
background.translationX = bounds.exactCenterX() - background.width * 0.5f
background.translationY = bounds.exactCenterY() - background.height * 0.5f
AnimatorSet().apply {
playTogether(
ViewPropertyObjectAnimator.animate(background)
.scaleX(1f)
.scaleY(1f)
.translationX(0f)
.translationY(0f)
.setDuration(200)
.setInterpolator(AccelerateInterpolator(0.8f))
.get(),
ViewPropertyObjectAnimator.animate(transitionView)
.scaleX(scale)
.scaleY(scale)
.alpha(0f)
.translationX(x)
.translationY(y)
.setDuration(200)
.setInterpolator(AccelerateInterpolator(0.8f))
.get(),
ViewPropertyObjectAnimator.animate(searchView)
.scaleX(0.8f)
.scaleY(0.8f)
.alpha(0f)
.get()
)
}.start()
onResumeCallback = {
transitionView.translationX = 0f
transitionView.translationY = 0f
transitionView.scaleX = 1f
transitionView.scaleY = 1f
transitionView.alpha = 1f
searchView.scaleX = 1f
searchView.scaleY = 1f
searchView.alpha = 1f
background.scaleX = 1f
background.scaleY = 1f
background.translationX = 0f
background.translationY = 0f
overlayView.get()?.remove(transitionView)
background.visibility = View.INVISIBLE
parent.addView(transitionView, index)
}
return true return true
} }
private var onResumeCallback: (() -> Unit)? = null
private fun startActivity( private fun startActivity(
context: Context, context: Context,
item: Searchable? = null, item: Searchable? = null,
@ -146,7 +52,7 @@ object ActivityStarter : KoinComponent {
val sourceBounds = val sourceBounds =
Rect(pos[0], pos[1], pos[0] + sourceView.width, pos[1] + sourceView.height) Rect(pos[0], pos[1], pos[0] + sourceView.width, pos[1] + sourceView.height)
val bundle = getActivityOptions(context, sourceView, sourceBounds)?.toBundle() val bundle = getActivityOptions(sourceView, sourceBounds).toBundle()
if (pendingIntent != null) { if (pendingIntent != null) {
return try { return try {
@ -177,72 +83,19 @@ object ActivityStarter : KoinComponent {
} }
private fun getActivityOptions( private fun getActivityOptions(
context: Context,
sourceView: View, sourceView: View,
sourceBounds: Rect? sourceBounds: Rect?
): ActivityOptionsCompat? { ): ActivityOptionsCompat {
return when (animationStyle) { return ActivityOptionsCompat.makeClipRevealAnimation(
AppStartAnimation.FADE -> ActivityOptionsCompat.makeCustomAnimation( sourceView,
context, 0,
R.anim.activity_start_fade_enter, 0,
R.anim.activity_start_fade_exit sourceView.width,
) sourceView.height
AppStartAnimation.SLIDE_BOTTOM -> ActivityOptionsCompat.makeCustomAnimation( )
context,
R.anim.activity_start_slide_bottom_enter,
R.anim.activity_start_slide_bottom_exit
)
AppStartAnimation.M -> sourceBounds?.let {
ActivityOptionsCompat.makeClipRevealAnimation(
sourceView,
0,
0,
sourceView.width,
sourceView.height
)
}
else -> ActivityOptionsCompat.makeCustomAnimation(
context,
R.anim.activity_start_splash2_enter,
R.anim.activity_start_splash2_exit
)
}
} }
fun pause() {
}
fun resume() {
onResumeCallback?.invoke()
onResumeCallback = null
val it = callbacks.iterator()
while (it.hasNext()) {
val callbackRef = it.next()
val callback = callbackRef.get()
if (callback == null) {
it.remove()
continue
}
callback.onResume()
}
}
fun destroy() {
onResumeCallback = null
}
/**
* Returns true when an animation is running
*/
fun isStarting(): Boolean {
return onResumeCallback != null
}
private val callbacks = mutableSetOf<WeakReference<ActivityStarterCallback>>()
fun registerCallback(callback: ActivityStarterCallback) {
callbacks.add(WeakReference(callback))
}
} }

View File

@ -38,7 +38,7 @@ import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.favorites.FavoritesRepository
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.* import de.mm20.launcher2.ktx.*
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.notifications.NotificationRepository import de.mm20.launcher2.notifications.NotificationRepository
import de.mm20.launcher2.search.data.AppInstallation import de.mm20.launcher2.search.data.AppInstallation
import de.mm20.launcher2.search.data.Application import de.mm20.launcher2.search.data.Application

View File

@ -9,7 +9,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView

View File

@ -13,7 +13,7 @@ import androidx.core.text.HtmlCompat
import androidx.transition.Scene import androidx.transition.Scene
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ktx.setStartCompoundDrawable import de.mm20.launcher2.ktx.setStartCompoundDrawable
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.CalendarEvent import de.mm20.launcher2.search.data.CalendarEvent
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView

View File

@ -21,7 +21,7 @@ import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.ktx.setStartCompoundDrawable import de.mm20.launcher2.ktx.setStartCompoundDrawable
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Contact import de.mm20.launcher2.search.data.Contact
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R

View File

@ -9,7 +9,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.File import de.mm20.launcher2.search.data.File
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R

View File

@ -13,10 +13,9 @@ import androidx.recyclerview.widget.ListUpdateCallback
import de.mm20.launcher2.ktx.ceilToInt import de.mm20.launcher2.ktx.ceilToInt
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback import de.mm20.launcher2.ui.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.preferences.LauncherDataStore import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@ -32,12 +31,7 @@ import org.koin.core.component.inject
import java.util.* import java.util.*
import kotlin.math.min import kotlin.math.min
class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent { class SearchGridView : ViewGroup, KoinComponent {
override fun onResume() {
while (postponedDiffs.isNotEmpty()) {
postponedDiffs.poll()?.let { applyDiff(it, true) }
}
}
val dataStore: LauncherDataStore by inject() val dataStore: LauncherDataStore by inject()
@ -96,9 +90,6 @@ class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
private var currentItems = listOf<Searchable>() private var currentItems = listOf<Searchable>()
private val postponedDiffs = ArrayDeque<Queue<DiffAction>>()
/** /**
* The height of each row. An absolute pixel size or [ROW_HEIGHT_AUTO] * The height of each row. An absolute pixel size or [ROW_HEIGHT_AUTO]
*/ */
@ -121,7 +112,6 @@ class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
it.enableTransitionType(LayoutTransition.CHANGING) it.enableTransitionType(LayoutTransition.CHANGING)
} }
clipChildren = false clipChildren = false
ActivityStarter.registerCallback(this)
} }
init { init {
@ -228,11 +218,7 @@ class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
* Applies a diff queue. Enqueues to postponedDiffs if an activity is starting (leaving this view * Applies a diff queue. Enqueues to postponedDiffs if an activity is starting (leaving this view
* in an unstable state) or if postponedDiffs is not empty and [force] is not set. * in an unstable state) or if postponedDiffs is not empty and [force] is not set.
*/ */
private fun applyDiff(diff: Queue<DiffAction>, force: Boolean = false) { private fun applyDiff(diff: Queue<DiffAction>) {
if (ActivityStarter.isStarting() || (postponedDiffs.isNotEmpty() && !force)) {
postponedDiffs.push(diff)
return
}
val representation = val representation =
if (columnCount == 1) SearchableView.REPRESENTATION_LIST else SearchableView.REPRESENTATION_GRID if (columnCount == 1) SearchableView.REPRESENTATION_LIST else SearchableView.REPRESENTATION_GRID
while (diff.isNotEmpty()) { while (diff.isNotEmpty()) {

View File

@ -4,8 +4,8 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.LinearLayout import android.widget.LinearLayout
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback import de.mm20.launcher2.ui.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.transition.ChangingLayoutTransition import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@ -17,12 +17,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.* import java.util.*
class SearchListView : LinearLayout, ActivityStarterCallback { class SearchListView : LinearLayout {
override fun onResume() {
while (postponedDiffs.isNotEmpty()) {
postponedDiffs.poll()?.let { applyDiff(it, true) }
}
}
@ObsoleteCoroutinesApi @ObsoleteCoroutinesApi
private val updateActor = lifecycleScope private val updateActor = lifecycleScope
@ -55,27 +50,19 @@ class SearchListView : LinearLayout, ActivityStarterCallback {
private var currentItems = listOf<Searchable>() private var currentItems = listOf<Searchable>()
private val postponedDiffs = ArrayDeque<Queue<DiffAction>>()
constructor(context: Context) : this(context, null) constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) { constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) {
layoutTransition = ChangingLayoutTransition() layoutTransition = ChangingLayoutTransition()
clipChildren = false clipChildren = false
orientation = VERTICAL orientation = VERTICAL
ActivityStarter.registerCallback(this)
} }
/** /**
* Applies a diff queue. Enqueues to postponedDiffs if an activity is starting (leaving this view * Applies a diff queue. Enqueues to postponedDiffs if an activity is starting (leaving this view
* in an unstable state) or if postponedDiffs is not empty and [force] is not set. * in an unstable state) or if postponedDiffs is not empty and [force] is not set.
*/ */
private fun applyDiff(diff: Queue<DiffAction>, force: Boolean = false) { private fun applyDiff(diff: Queue<DiffAction>) {
if (ActivityStarter.isStarting() || (postponedDiffs.isNotEmpty() && !force)) {
postponedDiffs.push(diff)
return
}
val representation = SearchableView.REPRESENTATION_LIST val representation = SearchableView.REPRESENTATION_LIST
while (diff.isNotEmpty()) { while (diff.isNotEmpty()) {
val action = diff.poll() ?: continue val action = diff.poll() ?: continue

View File

@ -14,7 +14,7 @@ import coil.load
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.search.data.Website import de.mm20.launcher2.search.data.Website
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R

View File

@ -15,7 +15,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.search.data.Website import de.mm20.launcher2.search.data.Website
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R

View File

@ -6,10 +6,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.GridCells import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
@ -32,10 +29,9 @@ import com.google.accompanist.pager.HorizontalPagerIndicator
import com.google.accompanist.pager.rememberPagerState import com.google.accompanist.pager.rememberPagerState
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.preferences.Settings.*
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme
import de.mm20.launcher2.preferences.Settings.IconSettings
import de.mm20.launcher2.preferences.Settings.SearchBarSettings
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.* import de.mm20.launcher2.ui.component.preferences.*
import de.mm20.launcher2.ui.launcher.search.SearchBar import de.mm20.launcher2.ui.launcher.search.SearchBar

View File

@ -127,12 +127,14 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
val installedIconPacks: LiveData<List<IconPack>> = liveData { val installedIconPacks: LiveData<List<IconPack>> = liveData {
emit( emit(
listOf(IconPack( listOf(
name = "System", IconPack(
packageName = "", name = "System",
version = "", packageName = "",
)) + version = "",
iconRepository.getInstalledIconPacks() )
) +
iconRepository.getInstalledIconPacks()
) )
} }
val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData() val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData()