Reorganize Searchable data types
This commit is contained in:
@@ -5,7 +5,8 @@ import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.customattrs.CustomAttributesRepository
|
||||
import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.data.Tag
|
||||
import de.mm20.launcher2.ui.utils.withCustomLabels
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
@@ -32,7 +33,7 @@ open class FavoritesVM : ViewModel(), KoinComponent {
|
||||
it.filterIsInstance<Tag>()
|
||||
}
|
||||
|
||||
val favorites: Flow<List<Searchable>> = selectedTag.flatMapLatest { tag ->
|
||||
val favorites: Flow<List<PinnableSearchable>> = selectedTag.flatMapLatest { tag ->
|
||||
if (tag == null) {
|
||||
val columns = dataStore.data.map { it.grid.columnCount }
|
||||
val excludeCalendar = widgetRepository.isCalendarWidgetEnabled()
|
||||
|
||||
@@ -71,7 +71,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.PathEffect
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.drawOutline
|
||||
@@ -90,7 +89,8 @@ import androidx.compose.ui.unit.toSize
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.badges.Badge
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.component.MissingPermissionBanner
|
||||
@@ -739,7 +739,7 @@ fun ShortcutPicker(viewModel: EditFavoritesSheetVM) {
|
||||
}
|
||||
|
||||
sealed interface FavoritesSheetGridItem {
|
||||
class Favorite(val item: Searchable) : FavoritesSheetGridItem
|
||||
class Favorite(val item: PinnableSearchable) : FavoritesSheetGridItem
|
||||
class Divider(val section: FavoritesSheetSection) : FavoritesSheetGridItem
|
||||
class Spacer(val span: Int = 1) : FavoritesSheetGridItem
|
||||
object EmptySection : FavoritesSheetGridItem
|
||||
|
||||
@@ -17,12 +17,12 @@ import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.ktx.normalize
|
||||
import de.mm20.launcher2.ktx.romanize
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.data.AppShortcut
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.data.Tag
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -48,9 +48,9 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent {
|
||||
|
||||
val createShortcutTarget = MutableLiveData<FavoritesSheetSection?>(null)
|
||||
|
||||
private var manuallySorted: MutableList<Searchable> = mutableListOf()
|
||||
private var automaticallySorted: MutableList<Searchable> = mutableListOf()
|
||||
private var frequentlyUsed: MutableList<Searchable> = mutableListOf()
|
||||
private var manuallySorted: MutableList<PinnableSearchable> = mutableListOf()
|
||||
private var automaticallySorted: MutableList<PinnableSearchable> = mutableListOf()
|
||||
private var frequentlyUsed: MutableList<PinnableSearchable> = mutableListOf()
|
||||
|
||||
val pinnedTags = MutableLiveData<List<Tag>>(emptyList())
|
||||
val availableTags = MutableLiveData<List<Tag>>(emptyList())
|
||||
@@ -179,7 +179,7 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent {
|
||||
)
|
||||
}
|
||||
|
||||
fun getIcon(searchable: Searchable, size: Int): Flow<LauncherIcon?> {
|
||||
fun getIcon(searchable: PinnableSearchable, size: Int): Flow<LauncherIcon?> {
|
||||
return iconRepository.getIcon(searchable, size)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,15 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||
|
||||
@Composable
|
||||
fun HiddenItemsSheet(
|
||||
items: List<Searchable>,
|
||||
items: List<PinnableSearchable>,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val viewModel: HiddenItemsSheetVM = viewModel()
|
||||
|
||||
@@ -43,7 +43,8 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.component.MissingPermissionBanner
|
||||
@@ -381,7 +382,7 @@ fun SearchColumn(
|
||||
}
|
||||
|
||||
fun LazyListScope.GridResults(
|
||||
items: ImmutableList<Searchable>,
|
||||
items: ImmutableList<PinnableSearchable>,
|
||||
columns: Int,
|
||||
reverse: Boolean,
|
||||
showLabels: Boolean,
|
||||
@@ -446,7 +447,7 @@ fun LazyListScope.GridResults(
|
||||
@Composable
|
||||
fun GridRow(
|
||||
modifier: Modifier = Modifier,
|
||||
items: ImmutableList<Searchable>,
|
||||
items: ImmutableList<PinnableSearchable>,
|
||||
columns: Int,
|
||||
showLabels: Boolean,
|
||||
) {
|
||||
@@ -470,7 +471,7 @@ fun GridRow(
|
||||
}
|
||||
|
||||
fun LazyListScope.ListResults(
|
||||
items: ImmutableList<Searchable>,
|
||||
items: ImmutableList<PinnableSearchable>,
|
||||
reverse: Boolean,
|
||||
key: String,
|
||||
before: (@Composable () -> Unit)? = null,
|
||||
@@ -523,7 +524,7 @@ fun LazyListScope.ListResults(
|
||||
@Composable
|
||||
fun ListRow(
|
||||
modifier: Modifier = Modifier,
|
||||
item: Searchable,
|
||||
item: PinnableSearchable,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier.padding(
|
||||
|
||||
@@ -16,12 +16,13 @@ import de.mm20.launcher2.files.FileRepository
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.WebsearchRepository
|
||||
import de.mm20.launcher2.search.data.*
|
||||
import de.mm20.launcher2.ui.utils.withCustomLabels
|
||||
import de.mm20.launcher2.unitconverter.UnitConverterRepository
|
||||
import de.mm20.launcher2.websites.WebsiteRepository
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import de.mm20.launcher2.wikipedia.WikipediaRepository
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
@@ -52,8 +53,8 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
|
||||
val showLabels = dataStore.data.map { it.grid.showLabels }.asLiveData()
|
||||
|
||||
val appResults = MutableLiveData<List<Application>>(emptyList())
|
||||
val workAppResults = MutableLiveData<List<Application>>(emptyList())
|
||||
val appResults = MutableLiveData<List<LauncherApp>>(emptyList())
|
||||
val workAppResults = MutableLiveData<List<LauncherApp>>(emptyList())
|
||||
val appShortcutResults = MutableLiveData<List<AppShortcut>>(emptyList())
|
||||
val fileResults = MutableLiveData<List<File>>(emptyList())
|
||||
val contactResults = MutableLiveData<List<Contact>>(emptyList())
|
||||
@@ -64,7 +65,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val unitConverterResult = MutableLiveData<UnitConverter?>(null)
|
||||
val websearchResults = MutableLiveData<List<Websearch>>(emptyList())
|
||||
|
||||
val hiddenResults = MutableLiveData<List<Searchable>>(emptyList())
|
||||
val hiddenResults = MutableLiveData<List<PinnableSearchable>>(emptyList())
|
||||
|
||||
val favoritesEnabled = dataStore.data.map { it.favorites.enabled }
|
||||
val hideFavorites = MutableLiveData(false)
|
||||
@@ -95,7 +96,7 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
val customAttrResults = customAttributesRepository.search(query)
|
||||
.combine(dataStore.data) { items, settings ->
|
||||
items.filter {
|
||||
it is Application
|
||||
it is LauncherApp
|
||||
|| it is Contact && settings.contactsSearch.enabled
|
||||
|| it is CalendarEvent && settings.calendarSearch.enabled
|
||||
|| it is AppShortcut && settings.appShortcutSearch.enabled
|
||||
@@ -285,15 +286,15 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
|
||||
|
||||
private inline fun <reified T : Searchable> Flow<List<T>>.withCustomAttributeResults(
|
||||
customAttributeResults: Flow<List<Searchable>>
|
||||
private inline fun <reified T : PinnableSearchable> Flow<List<T>>.withCustomAttributeResults(
|
||||
customAttributeResults: Flow<List<PinnableSearchable>>
|
||||
): Flow<List<T>> {
|
||||
return this.combine(customAttributeResults) { items, items2 ->
|
||||
(items + items2.filterIsInstance<T>()).distinctBy { it.key }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <T : Searchable> Flow<List<T>>.collectWithHiddenItems(
|
||||
private suspend fun <T : PinnableSearchable> Flow<List<T>>.collectWithHiddenItems(
|
||||
hiddenItemKeys: Flow<List<String>>,
|
||||
action: (items: List<T>, hidden: List<T>) -> Unit
|
||||
) {
|
||||
@@ -305,18 +306,18 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Searchable> Flow<List<T>>.sorted(): Flow<List<T>> = this.map { it.sorted() }
|
||||
private fun <T : PinnableSearchable> Flow<List<T>>.sorted(): Flow<List<T>> = this.map { it.sorted() }
|
||||
|
||||
}
|
||||
|
||||
private data class HiddenItemResults(
|
||||
val apps: List<Application> = emptyList(),
|
||||
val apps: List<LauncherApp> = emptyList(),
|
||||
val contacts: List<Contact> = emptyList(),
|
||||
val calendarEvents: List<CalendarEvent> = emptyList(),
|
||||
val files: List<File> = emptyList(),
|
||||
val appShortcuts: List<AppShortcut> = emptyList(),
|
||||
) {
|
||||
fun joinToList(): List<Searchable> {
|
||||
fun joinToList(): List<PinnableSearchable> {
|
||||
return apps + contacts + calendarEvents + files + appShortcuts
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.*
|
||||
import de.mm20.launcher2.ui.ktx.toDp
|
||||
@@ -40,7 +40,7 @@ import kotlin.math.roundToInt
|
||||
@Composable
|
||||
fun AppItem(
|
||||
modifier: Modifier = Modifier,
|
||||
app: Application,
|
||||
app: LauncherApp,
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
val viewModel = remember { AppItemVM(app) }
|
||||
@@ -336,7 +336,7 @@ fun AppItem(
|
||||
|
||||
@Composable
|
||||
fun AppItemGridPopup(
|
||||
app: Application,
|
||||
app: LauncherApp,
|
||||
show: Boolean,
|
||||
animationProgress: Float,
|
||||
origin: Rect,
|
||||
|
||||
@@ -8,16 +8,13 @@ import android.content.pm.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Process
|
||||
import android.provider.Settings
|
||||
import android.service.notification.StatusBarNotification
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.getSystemService
|
||||
import de.mm20.launcher2.appshortcuts.AppShortcutRepository
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.notifications.NotificationRepository
|
||||
import de.mm20.launcher2.search.data.AppShortcut
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -28,7 +25,7 @@ import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class AppItemVM(
|
||||
private val app: Application
|
||||
private val app: LauncherApp
|
||||
) : SearchableItemVM(app) {
|
||||
private val notificationRepository: NotificationRepository by inject()
|
||||
private val appShortcutRepository: AppShortcutRepository by inject()
|
||||
@@ -44,21 +41,12 @@ class AppItemVM(
|
||||
fun openAppInfo(context: Context) {
|
||||
val launcherApps = context.getSystemService<LauncherApps>()!!
|
||||
|
||||
if (app is LauncherApp) {
|
||||
launcherApps.startAppDetailsActivity(
|
||||
ComponentName(app.`package`, app.activity),
|
||||
app.getUser(),
|
||||
null,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
context.tryStartActivity(
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.parse("package:${app.`package`}")
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
)
|
||||
}
|
||||
launcherApps.startAppDetailsActivity(
|
||||
ComponentName(app.`package`, app.activity),
|
||||
app.getUser(),
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun shareApkFile(context: Context) {
|
||||
@@ -128,9 +116,7 @@ class AppItemVM(
|
||||
}
|
||||
|
||||
val shortcuts = flow {
|
||||
if (app is LauncherApp) {
|
||||
emit(appShortcutRepository.getShortcutsForActivity(app.launcherActivityInfo, 5))
|
||||
}
|
||||
emit(appShortcutRepository.getShortcutsForActivity(app.launcherActivityInfo, 5))
|
||||
}
|
||||
|
||||
fun isShortcutPinned(shortcut: AppShortcut): Flow<Boolean> {
|
||||
|
||||
@@ -10,15 +10,15 @@ import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.data.AppShortcut
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
abstract class SearchableItemVM(
|
||||
private val searchable: Searchable
|
||||
private val searchable: PinnableSearchable
|
||||
) : KoinComponent {
|
||||
protected val favoritesRepository: FavoritesRepository by inject()
|
||||
protected val badgeRepository: BadgeRepository by inject()
|
||||
@@ -74,7 +74,7 @@ abstract class SearchableItemVM(
|
||||
if (searchable.launch(context, bundle)) {
|
||||
favoritesRepository.incrementLaunchCounter(searchable)
|
||||
return true
|
||||
} else if (searchable is Application || searchable is AppShortcut) {
|
||||
} else if (searchable is LauncherApp || searchable is AppShortcut) {
|
||||
favoritesRepository.remove(searchable)
|
||||
}
|
||||
return false
|
||||
|
||||
+3
-2
@@ -23,7 +23,8 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.badges.Badge
|
||||
import de.mm20.launcher2.icons.CustomIconWithPreview
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||
@@ -35,7 +36,7 @@ import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun CustomizeSearchableSheet(
|
||||
searchable: Searchable,
|
||||
searchable: PinnableSearchable,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
val viewModel: CustomizeSearchableSheetVM =
|
||||
|
||||
+3
-3
@@ -4,11 +4,11 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.liveData
|
||||
import de.mm20.launcher2.customattrs.CustomAttributesRepository
|
||||
import de.mm20.launcher2.customattrs.CustomIcon
|
||||
import de.mm20.launcher2.customattrs.customAttrsModule
|
||||
import de.mm20.launcher2.icons.CustomIconWithPreview
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koin.core.component.KoinComponent
|
||||
@@ -16,7 +16,7 @@ import org.koin.core.component.inject
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class CustomizeSearchableSheetVM(
|
||||
private val searchable: Searchable
|
||||
private val searchable: PinnableSearchable
|
||||
) : KoinComponent {
|
||||
private val iconRepository: IconRepository by inject()
|
||||
private val customAttributesRepository: CustomAttributesRepository by inject()
|
||||
|
||||
@@ -2,19 +2,15 @@ package de.mm20.launcher2.ui.launcher.search.common.grid
|
||||
|
||||
import android.content.ComponentName
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
@@ -26,6 +22,8 @@ import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Popup
|
||||
import androidx.compose.ui.window.PopupProperties
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.data.*
|
||||
import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||
@@ -47,7 +45,7 @@ import kotlinx.coroutines.delay
|
||||
|
||||
|
||||
@Composable
|
||||
fun GridItem(modifier: Modifier = Modifier, item: Searchable, showLabels: Boolean = true) {
|
||||
fun GridItem(modifier: Modifier = Modifier, item: PinnableSearchable, showLabels: Boolean = true) {
|
||||
val viewModel = remember(item.key) { GridItemVM(item) }
|
||||
|
||||
val context = LocalContext.current
|
||||
@@ -59,13 +57,11 @@ fun GridItem(modifier: Modifier = Modifier, item: Searchable, showLabels: Boolea
|
||||
val iconSize = LocalGridIconSize.current.toPixels()
|
||||
val icon by remember(item.key) { viewModel.getIcon(iconSize.toInt()) }.collectAsState(null)
|
||||
|
||||
// If item is one of these types, try to launch them on click; show details otherwise
|
||||
val launchOnPress =
|
||||
item is File || item is Application || item is AppShortcut || item is Website || item is Wikipedia
|
||||
val launchOnPress = !item.preferDetailsOverLaunch
|
||||
|
||||
val windowSize = LocalWindowSize.current
|
||||
|
||||
if (item is Application) {
|
||||
if (item is LauncherApp) {
|
||||
HandleHomeTransition {
|
||||
val cn = ComponentName(item.`package`, item.activity)
|
||||
if (
|
||||
@@ -164,7 +160,7 @@ fun ItemPopup(origin: Rect, searchable: Searchable, onDismissRequest: () -> Unit
|
||||
.wrapContentSize()
|
||||
) {
|
||||
when (searchable) {
|
||||
is Application -> {
|
||||
is LauncherApp -> {
|
||||
AppItemGridPopup(
|
||||
app = searchable,
|
||||
show = show,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.common.grid
|
||||
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
|
||||
class GridItemVM(
|
||||
searchable: Searchable
|
||||
searchable: PinnableSearchable
|
||||
): SearchableItemVM(searchable)
|
||||
+3
-2
@@ -5,14 +5,15 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
import de.mm20.launcher2.ui.locals.LocalGridColumns
|
||||
import kotlin.math.ceil
|
||||
|
||||
@Composable
|
||||
fun SearchResultGrid(
|
||||
items: List<Searchable>,
|
||||
items: List<PinnableSearchable>,
|
||||
modifier: Modifier = Modifier,
|
||||
showLabels: Boolean = true,
|
||||
columns: Int = LocalGridColumns.current,
|
||||
|
||||
@@ -2,13 +2,14 @@ package de.mm20.launcher2.ui.launcher.search.common.list
|
||||
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.search.data.*
|
||||
import de.mm20.launcher2.ui.component.InnerCard
|
||||
import de.mm20.launcher2.ui.launcher.search.calendar.CalendarItem
|
||||
@@ -17,7 +18,7 @@ import de.mm20.launcher2.ui.launcher.search.files.FileItem
|
||||
import de.mm20.launcher2.ui.launcher.search.shortcut.AppShortcutItem
|
||||
|
||||
@Composable
|
||||
fun ListItem(modifier: Modifier = Modifier, item: Searchable) {
|
||||
fun ListItem(modifier: Modifier = Modifier, item: PinnableSearchable) {
|
||||
var showDetails by remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.common.list
|
||||
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||
|
||||
class ListItemVM(
|
||||
searchable: Searchable
|
||||
searchable: PinnableSearchable
|
||||
): SearchableItemVM(searchable)
|
||||
+3
-2
@@ -8,12 +8,13 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
|
||||
@Composable
|
||||
fun SearchResultList(
|
||||
items: List<Searchable>,
|
||||
items: List<PinnableSearchable>,
|
||||
modifier: Modifier = Modifier,
|
||||
reverse: Boolean = false
|
||||
) {
|
||||
|
||||
@@ -57,7 +57,7 @@ fun WebsiteItem(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = website.label,
|
||||
text = website.labelOverride ?: website.label,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
val tags by remember(viewModel) { viewModel.getTags() }.collectAsState(emptyList())
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
package de.mm20.launcher2.ui.launcher.widgets.favorites
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.common.FavoritesVM
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class FavoritesWidgetVM: FavoritesVM()
|
||||
-2
@@ -1,6 +1,5 @@
|
||||
package de.mm20.launcher2.ui.settings.hiddenitems
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
@@ -21,7 +20,6 @@ import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
|
||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||
|
||||
+15
-28
@@ -2,11 +2,8 @@ package de.mm20.launcher2.ui.settings.hiddenitems
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.LauncherApps
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -17,10 +14,9 @@ import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -37,18 +33,18 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
val allApps = appRepository.getAllInstalledApps().map {
|
||||
withContext(Dispatchers.Default) { it.sorted() }
|
||||
}.asLiveData()
|
||||
val hiddenItems: LiveData<List<Searchable>> = liveData {
|
||||
val hiddenItems: LiveData<List<PinnableSearchable>> = liveData {
|
||||
val hidden = withContext(Dispatchers.Default) {
|
||||
favoritesRepository.getHiddenItems().first().filter { it !is Application }.sorted()
|
||||
favoritesRepository.getHiddenItems().first().filter { it !is LauncherApp }.sorted()
|
||||
}
|
||||
emit(hidden)
|
||||
}
|
||||
|
||||
fun isHidden(searchable: Searchable): Flow<Boolean> {
|
||||
fun isHidden(searchable: PinnableSearchable): Flow<Boolean> {
|
||||
return favoritesRepository.isHidden(searchable)
|
||||
}
|
||||
|
||||
fun setHidden(searchable: Searchable, hidden: Boolean) {
|
||||
fun setHidden(searchable: PinnableSearchable, hidden: Boolean) {
|
||||
if(hidden) {
|
||||
favoritesRepository.hideItem(searchable)
|
||||
} else {
|
||||
@@ -56,11 +52,11 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
fun getIcon(searchable: Searchable, size: Int): Flow<LauncherIcon> {
|
||||
fun getIcon(searchable: PinnableSearchable, size: Int): Flow<LauncherIcon> {
|
||||
return iconRepository.getIcon(searchable, size)
|
||||
}
|
||||
|
||||
fun launch(context: Context, searchable: Searchable) {
|
||||
fun launch(context: Context, searchable: PinnableSearchable) {
|
||||
val bundle = Bundle()
|
||||
if (isAtLeastApiLevel(31)) {
|
||||
bundle.putInt("android.activity.splashScreenStyle", 1)
|
||||
@@ -68,23 +64,14 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
searchable.launch(context, bundle)
|
||||
}
|
||||
|
||||
fun openAppInfo(context: Context, app: Application) {
|
||||
fun openAppInfo(context: Context, app: LauncherApp) {
|
||||
val launcherApps = context.getSystemService<LauncherApps>()!!
|
||||
|
||||
if (app is LauncherApp) {
|
||||
launcherApps.startAppDetailsActivity(
|
||||
ComponentName(app.`package`, app.activity),
|
||||
app.getUser(),
|
||||
null,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
context.tryStartActivity(
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.parse("package:${app.`package`}")
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
)
|
||||
}
|
||||
launcherApps.startAppDetailsActivity(
|
||||
ComponentName(app.`package`, app.activity),
|
||||
app.getUser(),
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,26 @@
|
||||
package de.mm20.launcher2.ui.utils
|
||||
|
||||
import de.mm20.launcher2.customattrs.CustomAttributesRepository
|
||||
import de.mm20.launcher2.customattrs.CustomLabel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
||||
fun <T : Searchable> Flow<List<T>>.withCustomLabels(
|
||||
fun <T : PinnableSearchable> Flow<List<T>>.withCustomLabels(
|
||||
customAttributesRepository: CustomAttributesRepository,
|
||||
): Flow<List<T>> = channelFlow {
|
||||
this@withCustomLabels.collectLatest { items ->
|
||||
val customLabels = customAttributesRepository.getCustomLabels(items)
|
||||
customLabels.collectLatest { labels ->
|
||||
for (item in items) {
|
||||
send(items.map { item ->
|
||||
val customLabel = labels.find { it.key == item.key }
|
||||
item.labelOverride = customLabel?.label
|
||||
}
|
||||
send(items)
|
||||
if (customLabel != null) {
|
||||
item.overrideLabel(customLabel.label) as T
|
||||
} else {
|
||||
item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user