From 5e18d2533546335d6812a9ca868faa5d8eb456fd Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Fri, 18 Feb 2022 23:35:41 +0100 Subject: [PATCH] Migrate hidden items panel to Jetpack Compose --- .../launcher2/ui/launcher/LauncherActivity.kt | 24 ++-- .../ui/launcher/modals/HiddenItemsVM.kt | 10 +- .../ui/launcher/modals/HiddenItemsView.kt | 128 ++++++++++++------ 3 files changed, 101 insertions(+), 61 deletions(-) diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt index 4b4f0913..32b3ec40 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/LauncherActivity.kt @@ -9,8 +9,10 @@ import android.view.View import androidx.activity.viewModels import androidx.core.view.* import androidx.lifecycle.Lifecycle +import androidx.lifecycle.ViewTreeLifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import androidx.savedstate.ViewTreeSavedStateRegistryOwner import com.afollestad.materialdialogs.LayoutMode import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.bottomsheets.BottomSheet @@ -107,22 +109,20 @@ class LauncherActivity : BaseActivity() { } } - var hiddenItemsDialog: MaterialDialog? = null + var hiddenItemsView: HiddenItemsView? = null viewModel.isHiddenItemsShown.observe(this) { if (it) { - val view = HiddenItemsView(this) - hiddenItemsDialog = MaterialDialog(this, BottomSheet(LayoutMode.MATCH_PARENT)) - .show { - title(R.string.menu_hidden_items) - customView(view = view) - negativeButton(R.string.close) { dismiss() } - onDismiss { - viewModel.hideHiddenItems() - } + if (hiddenItemsView != null) return@observe + hiddenItemsView = HiddenItemsView(this).apply { + onDismiss = { + viewModel.hideHiddenItems() } + } + binding.rootView.addView(hiddenItemsView) } else { - hiddenItemsDialog?.dismiss() - hiddenItemsDialog = null + if (hiddenItemsView == null) return@observe + binding.rootView.removeView(hiddenItemsView) + hiddenItemsView = null } } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsVM.kt index e0e05742..24869a43 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsVM.kt @@ -13,13 +13,5 @@ import org.koin.core.component.inject class HiddenItemsVM: ViewModel(), KoinComponent { private val repository: FavoritesRepository by inject() - val hiddenItems = MutableLiveData>(emptyList()) - - suspend fun onActive() { - withContext(Dispatchers.IO) { - repository.getHiddenItems().collectLatest { - hiddenItems.postValue(it) - } - } - } + val hiddenItems = repository.getHiddenItems() } \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsView.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsView.kt index d08057e3..5adefb86 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsView.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsView.kt @@ -2,56 +2,104 @@ package de.mm20.launcher2.ui.launcher.modals import android.content.Context import android.util.AttributeSet -import android.view.ViewGroup import android.widget.FrameLayout import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.setMargins -import androidx.core.widget.NestedScrollView -import de.mm20.launcher2.ktx.dp -import de.mm20.launcher2.ktx.lifecycleScope -import de.mm20.launcher2.ui.legacy.search.SearchGridView -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.slideIn +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import de.mm20.launcher2.ui.MdcLauncherTheme +import de.mm20.launcher2.ui.R +import de.mm20.launcher2.ui.base.ProvideSettings +import de.mm20.launcher2.ui.launcher.search.common.SearchResultGrid +@OptIn(ExperimentalComposeUiApi::class) class HiddenItemsView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null -) : NestedScrollView(context, attrs) { +) : FrameLayout(context, attrs) { private val viewModel: HiddenItemsVM by (context as AppCompatActivity).viewModels() init { - clipChildren = false - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - val hiddenItemsGrid = SearchGridView(context) - hiddenItemsGrid.layoutParams = FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - setMargins((8 * dp).toInt()) + val composeView = ComposeView(context) + + composeView.setContent { + MdcLauncherTheme { + ProvideSettings { + Dialog( + properties = DialogProperties(usePlatformDefaultWidth = false), + onDismissRequest = { onDismiss() }) { + val animationState = remember { + MutableTransitionState(false).apply { + targetState = true + } + } + + AnimatedVisibility( + animationState, + enter = slideIn { IntOffset(0, it.height) } + ) { + Surface(modifier = Modifier.fillMaxSize()) { + Column( + modifier = Modifier + .fillMaxSize() + ) { + Text( + stringResource(R.string.menu_hidden_items), + style = MaterialTheme.typography.titleLarge, + modifier = Modifier.padding(24.dp) + + ) + val items by viewModel.hiddenItems.collectAsState(emptyList()) + SearchResultGrid( + items, + modifier = Modifier + .weight(1f) + .padding(8.dp) + .verticalScroll(rememberScrollState()) + ) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + contentAlignment = Alignment.CenterEnd + ) { + TextButton(onClick = { onDismiss() }) { + Text( + stringResource(id = R.string.close), + style = MaterialTheme.typography.labelLarge + ) + } + } + } + } + } + + } + } + } } - val hiddenItems = viewModel.hiddenItems - hiddenItems.observe(context as AppCompatActivity) { - hiddenItemsGrid.submitItems(it) - } - addView(hiddenItemsGrid) + + addView(composeView) } - private var job: Job? = null - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - val job = Job() - this.job = job - lifecycleScope.launch(job) { - viewModel.onActive() - } - } - - override fun onDetachedFromWindow() { - super.onDetachedFromWindow() - job?.cancel() - } + var onDismiss: () -> Unit = {} } \ No newline at end of file