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
29 changed files with 50 additions and 374 deletions
@@ -1,6 +1,7 @@
package de.mm20.launcher2.ui.base
import android.os.Bundle
import android.view.Window
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
@@ -14,18 +14,13 @@ import com.afollestad.materialdialogs.callbacks.onDismiss
import com.afollestad.materialdialogs.customview.customView
import de.mm20.launcher2.icons.DynamicIconController
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.base.BaseActivity
import de.mm20.launcher2.ui.databinding.ActivityLauncherBinding
import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView
import de.mm20.launcher2.ui.launcher.modals.HiddenItemsView
import kotlinx.coroutines.*
import org.koin.android.ext.android.inject
import org.koin.core.component.inject
import java.util.*
class LauncherActivity : BaseActivity() {
@@ -114,7 +109,6 @@ class LauncherActivity : BaseActivity() {
override fun onResume() {
super.onResume()
ActivityStarter.resume()
ActivityStarter.create(binding.rootView)
binding.activityStartOverlay.visibility = View.INVISIBLE
@@ -123,18 +117,8 @@ class LauncherActivity : BaseActivity() {
}
}
override fun onPause() {
super.onPause()
ActivityStarter.pause()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
onBackPressed()
}
override fun onDestroy() {
super.onDestroy()
ActivityStarter.destroy()
}
}
@@ -17,7 +17,7 @@ import coil.size.Scale
import com.google.android.material.chip.Chip
import de.mm20.launcher2.ktx.dp
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.ui.R
import de.mm20.launcher2.ui.databinding.ViewWebsearchBinding
@@ -9,7 +9,7 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData
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.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchVM
@@ -8,7 +8,7 @@ import android.widget.FrameLayout
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
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.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchVM
@@ -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.content.ActivityNotFoundException
import android.content.Context
@@ -9,13 +8,9 @@ import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroupOverlay
import android.view.animation.AccelerateInterpolator
import android.widget.Toast
import androidx.core.app.ActivityOptionsCompat
import com.bartoszlipinski.viewpropertyobjectanimator.ViewPropertyObjectAnimator
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.ui.R
import org.koin.core.component.KoinComponent
@@ -24,26 +19,13 @@ import java.lang.ref.WeakReference
object ActivityStarter : KoinComponent {
val favoritesRepository: FavoritesRepository by inject()
private var initialized = false
private val favoritesRepository: FavoritesRepository by inject()
private lateinit var overlayView: WeakReference<ViewGroupOverlay>
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) {
this.rootView = WeakReference(rootView)
this.overlayView = WeakReference(rootView.overlay)
onResumeCallback = null
animationStyle = LauncherPreferences.instance.appStartAnim
initialized = true
ActivityStarter.rootView = WeakReference(rootView)
overlayView = WeakReference(rootView.overlay)
}
fun start(
@@ -53,87 +35,11 @@ object ActivityStarter : KoinComponent {
intent: Intent? = null,
pendingIntent: PendingIntent? = null
): Boolean {
if (!initialized) throw IllegalStateException("Item starter has not been initialized properly.")
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
}
private var onResumeCallback: (() -> Unit)? = null
private fun startActivity(
context: Context,
item: Searchable? = null,
@@ -146,7 +52,7 @@ object ActivityStarter : KoinComponent {
val sourceBounds =
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) {
return try {
@@ -177,72 +83,19 @@ object ActivityStarter : KoinComponent {
}
private fun getActivityOptions(
context: Context,
sourceView: View,
sourceBounds: Rect?
): ActivityOptionsCompat? {
return when (animationStyle) {
AppStartAnimation.FADE -> ActivityOptionsCompat.makeCustomAnimation(
context,
R.anim.activity_start_fade_enter,
R.anim.activity_start_fade_exit
)
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
)
}
): ActivityOptionsCompat {
return ActivityOptionsCompat.makeClipRevealAnimation(
sourceView,
0,
0,
sourceView.width,
sourceView.height
)
}
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))
}
}
@@ -38,7 +38,7 @@ import de.mm20.launcher2.crashreporter.CrashReporter
import de.mm20.launcher2.favorites.FavoritesRepository
import de.mm20.launcher2.icons.IconRepository
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.search.data.AppInstallation
import de.mm20.launcher2.search.data.Application
@@ -9,7 +9,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
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.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@@ -13,7 +13,7 @@ import androidx.core.text.HtmlCompat
import androidx.transition.Scene
import de.mm20.launcher2.ui.R
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.Searchable
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@@ -21,7 +21,7 @@ import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.ktx.lifecycleOwner
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.Searchable
import de.mm20.launcher2.ui.R
@@ -9,7 +9,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
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.Searchable
import de.mm20.launcher2.ui.R
@@ -13,10 +13,9 @@ import androidx.recyclerview.widget.ListUpdateCallback
import de.mm20.launcher2.ktx.ceilToInt
import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.ui.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@@ -32,12 +31,7 @@ import org.koin.core.component.inject
import java.util.*
import kotlin.math.min
class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
override fun onResume() {
while (postponedDiffs.isNotEmpty()) {
postponedDiffs.poll()?.let { applyDiff(it, true) }
}
}
class SearchGridView : ViewGroup, KoinComponent {
val dataStore: LauncherDataStore by inject()
@@ -96,9 +90,6 @@ class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
private var currentItems = listOf<Searchable>()
private val postponedDiffs = ArrayDeque<Queue<DiffAction>>()
/**
* 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)
}
clipChildren = false
ActivityStarter.registerCallback(this)
}
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
* in an unstable state) or if postponedDiffs is not empty and [force] is not set.
*/
private fun applyDiff(diff: Queue<DiffAction>, force: Boolean = false) {
if (ActivityStarter.isStarting() || (postponedDiffs.isNotEmpty() && !force)) {
postponedDiffs.push(diff)
return
}
private fun applyDiff(diff: Queue<DiffAction>) {
val representation =
if (columnCount == 1) SearchableView.REPRESENTATION_LIST else SearchableView.REPRESENTATION_GRID
while (diff.isNotEmpty()) {
@@ -4,8 +4,8 @@ import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.ui.legacy.helper.ActivityStarter
import de.mm20.launcher2.ui.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.transition.ChangingLayoutTransition
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
@@ -17,12 +17,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.*
class SearchListView : LinearLayout, ActivityStarterCallback {
override fun onResume() {
while (postponedDiffs.isNotEmpty()) {
postponedDiffs.poll()?.let { applyDiff(it, true) }
}
}
class SearchListView : LinearLayout {
@ObsoleteCoroutinesApi
private val updateActor = lifecycleScope
@@ -55,27 +50,19 @@ class SearchListView : LinearLayout, ActivityStarterCallback {
private var currentItems = listOf<Searchable>()
private val postponedDiffs = ArrayDeque<Queue<DiffAction>>()
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes) {
layoutTransition = ChangingLayoutTransition()
clipChildren = false
orientation = VERTICAL
ActivityStarter.registerCallback(this)
}
/**
* 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.
*/
private fun applyDiff(diff: Queue<DiffAction>, force: Boolean = false) {
if (ActivityStarter.isStarting() || (postponedDiffs.isNotEmpty() && !force)) {
postponedDiffs.push(diff)
return
}
private fun applyDiff(diff: Queue<DiffAction>) {
val representation = SearchableView.REPRESENTATION_LIST
while (diff.isNotEmpty()) {
val action = diff.poll() ?: continue
@@ -14,7 +14,7 @@ import coil.load
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
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.Website
import de.mm20.launcher2.ui.R
@@ -15,7 +15,7 @@ import de.mm20.launcher2.badges.BadgeRepository
import de.mm20.launcher2.icons.IconRepository
import de.mm20.launcher2.ktx.dp
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.Website
import de.mm20.launcher2.ui.R
@@ -6,10 +6,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.items
@@ -32,10 +29,9 @@ import com.google.accompanist.pager.HorizontalPagerIndicator
import com.google.accompanist.pager.rememberPagerState
import de.mm20.launcher2.icons.LauncherIcon
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.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.component.preferences.*
import de.mm20.launcher2.ui.launcher.search.SearchBar
@@ -127,12 +127,14 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
val installedIconPacks: LiveData<List<IconPack>> = liveData {
emit(
listOf(IconPack(
name = "System",
packageName = "",
version = "",
)) +
iconRepository.getInstalledIconPacks()
listOf(
IconPack(
name = "System",
packageName = "",
version = "",
)
) +
iconRepository.getInstalledIconPacks()
)
}
val iconPack = dataStore.data.map { it.icons.iconPack }.asLiveData()