Adds setting to not separate work profile and main profile apps (#678)

* Adds setting to not separate work profile and main profile apps

* Only show work profile related preference when there is a work profile

---------

Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
chaptergy 2024-03-28 21:00:06 +01:00 committed by GitHub
parent 0e1f3f9be8
commit 3646745a36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 93 additions and 9 deletions

View File

@ -98,6 +98,7 @@ fun SearchColumn(
val locations by viewModel.locationResults val locations by viewModel.locationResults
val website by viewModel.websiteResults val website by viewModel.websiteResults
val hiddenResults by viewModel.hiddenResults val hiddenResults by viewModel.hiddenResults
val separateWorkProfile by viewModel.separateWorkProfile.collectAsState(true)
val bestMatch by viewModel.bestMatch val bestMatch by viewModel.bestMatch
@ -160,11 +161,11 @@ fun SearchColumn(
} }
GridResults( GridResults(
items = if ((showWorkProfileApps || apps.isEmpty()) && workApps.isNotEmpty()) workApps.toImmutableList() else apps.toImmutableList(), items = if (separateWorkProfile) if ((showWorkProfileApps || apps.isEmpty()) && workApps.isNotEmpty()) workApps.toImmutableList() else apps.toImmutableList() else listOf(apps, workApps).flatten().sorted().toImmutableList(),
columns = columns, columns = columns,
reverse = reverse, reverse = reverse,
key = "apps", key = "apps",
before = if (workApps.isNotEmpty() && apps.isNotEmpty()) { before = if (separateWorkProfile && workApps.isNotEmpty() && apps.isNotEmpty()) {
{ {
Row( Row(
modifier = Modifier modifier = Modifier

View File

@ -90,6 +90,8 @@ class SearchVM : ViewModel(), KoinComponent {
val favoritesEnabled = searchUiSettings.favorites val favoritesEnabled = searchUiSettings.favorites
val hideFavorites = mutableStateOf(false) val hideFavorites = mutableStateOf(false)
val separateWorkProfile = searchUiSettings.separateWorkProfile
private val hiddenItemKeys = searchableRepository private val hiddenItemKeys = searchableRepository
.getKeys( .getKeys(
hidden = true, hidden = true,

View File

@ -1,17 +1,26 @@
package de.mm20.launcher2.ui.settings.search package de.mm20.launcher2.ui.settings.search
import android.content.Context
import android.content.pm.LauncherApps
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.* import androidx.compose.material.icons.rounded.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.getSystemService
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.preferences.LegacySettings import de.mm20.launcher2.preferences.LegacySettings
import de.mm20.launcher2.preferences.SearchResultOrder import de.mm20.launcher2.preferences.SearchResultOrder
@ -20,15 +29,28 @@ import de.mm20.launcher2.ui.component.MissingPermissionBanner
import de.mm20.launcher2.ui.component.preferences.* import de.mm20.launcher2.ui.component.preferences.*
import de.mm20.launcher2.ui.icons.Wikipedia import de.mm20.launcher2.ui.icons.Wikipedia
import de.mm20.launcher2.ui.locals.LocalNavController import de.mm20.launcher2.ui.locals.LocalNavController
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@Composable @Composable
fun SearchSettingsScreen() { fun SearchSettingsScreen() {
val viewModel: SearchSettingsScreenVM = viewModel() val viewModel: SearchSettingsScreenVM = viewModel()
val context = LocalContext.current val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val navController = LocalNavController.current val navController = LocalNavController.current
val hasWorkProfile by viewModel.hasWorkProfile
LaunchedEffect(Unit) {
lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewModel.onResume(context)
}
}
PreferenceScreen(title = stringResource(R.string.preference_screen_search)) { PreferenceScreen(title = stringResource(R.string.preference_screen_search)) {
item { item {
PreferenceCategory { PreferenceCategory {
@ -55,7 +77,9 @@ fun SearchSettingsScreen() {
} }
) )
val hasContactsPermission by viewModel.hasContactsPermission.collectAsStateWithLifecycle(null) val hasContactsPermission by viewModel.hasContactsPermission.collectAsStateWithLifecycle(
null
)
AnimatedVisibility(hasContactsPermission == false) { AnimatedVisibility(hasContactsPermission == false) {
MissingPermissionBanner( MissingPermissionBanner(
text = stringResource(R.string.missing_permission_contact_search_settings), text = stringResource(R.string.missing_permission_contact_search_settings),
@ -77,7 +101,9 @@ fun SearchSettingsScreen() {
enabled = hasContactsPermission == true enabled = hasContactsPermission == true
) )
val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsStateWithLifecycle(null) val hasCalendarPermission by viewModel.hasCalendarPermission.collectAsStateWithLifecycle(
null
)
AnimatedVisibility(hasCalendarPermission == false) { AnimatedVisibility(hasCalendarPermission == false) {
MissingPermissionBanner( MissingPermissionBanner(
text = stringResource(R.string.missing_permission_calendar_search_settings), text = stringResource(R.string.missing_permission_calendar_search_settings),
@ -99,7 +125,9 @@ fun SearchSettingsScreen() {
enabled = hasCalendarPermission == true enabled = hasCalendarPermission == true
) )
val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle(null) val hasAppShortcutsPermission by viewModel.hasAppShortcutPermission.collectAsStateWithLifecycle(
null
)
AnimatedVisibility(hasAppShortcutsPermission == false) { AnimatedVisibility(hasAppShortcutsPermission == false) {
MissingPermissionBanner( MissingPermissionBanner(
text = stringResource( text = stringResource(
@ -218,6 +246,24 @@ fun SearchSettingsScreen() {
) )
} }
} }
if (hasWorkProfile) {
item {
PreferenceCategory {
val separateWorkProfile by viewModel.separateWorkProfile.collectAsStateWithLifecycle(
null
)
SwitchPreference(
title = stringResource(R.string.preference_search_bar_separate_work_profile),
summary = stringResource(R.string.preference_search_bar_separate_work_profile_summary),
icon = Icons.Rounded.Work,
value = separateWorkProfile == true,
onValueChanged = {
viewModel.setSeparateWorkProfile(it)
}
)
}
}
}
item { item {
PreferenceCategory { PreferenceCategory {
val autoFocus by viewModel.autoFocus.collectAsStateWithLifecycle(null) val autoFocus by viewModel.autoFocus.collectAsStateWithLifecycle(null)
@ -243,7 +289,9 @@ fun SearchSettingsScreen() {
} }
item { item {
PreferenceCategory { PreferenceCategory {
val searchResultOrdering by viewModel.searchResultOrdering.collectAsStateWithLifecycle(null) val searchResultOrdering by viewModel.searchResultOrdering.collectAsStateWithLifecycle(
null
)
ListPreference( ListPreference(
title = stringResource(R.string.preference_search_result_ordering), title = stringResource(R.string.preference_search_result_ordering),
items = listOf( items = listOf(
@ -257,8 +305,11 @@ fun SearchSettingsScreen() {
icon = Icons.Rounded.Sort icon = Icons.Rounded.Sort
) )
val reverseSearchResults by viewModel.reverseSearchResults.collectAsStateWithLifecycle(null) val reverseSearchResults by viewModel.reverseSearchResults.collectAsStateWithLifecycle(
ListPreference(title = stringResource(R.string.preference_layout_search_results), null
)
ListPreference(
title = stringResource(R.string.preference_layout_search_results),
items = listOf( items = listOf(
stringResource(R.string.search_results_order_top_down) to false, stringResource(R.string.search_results_order_top_down) to false,
stringResource(R.string.search_results_order_bottom_up) to true, stringResource(R.string.search_results_order_bottom_up) to true,

View File

@ -1,6 +1,10 @@
package de.mm20.launcher2.ui.settings.search package de.mm20.launcher2.ui.settings.search
import android.content.Context
import android.content.pm.LauncherApps
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.mutableStateOf
import androidx.core.content.getSystemService
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionGroup
@ -16,6 +20,7 @@ import de.mm20.launcher2.preferences.search.WebsiteSearchSettings
import de.mm20.launcher2.preferences.search.WikipediaSearchSettings import de.mm20.launcher2.preferences.search.WikipediaSearchSettings
import de.mm20.launcher2.preferences.ui.SearchUiSettings import de.mm20.launcher2.preferences.ui.SearchUiSettings
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
@ -33,6 +38,12 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
private val permissionsManager: PermissionsManager by inject() private val permissionsManager: PermissionsManager by inject()
private val locationSearchSettings: LocationSearchSettings by inject() private val locationSearchSettings: LocationSearchSettings by inject()
val hasWorkProfile = mutableStateOf(false)
fun onResume(context: Context) {
hasWorkProfile.value = context.getSystemService<LauncherApps>()!!.profiles.size > 1
}
val favorites = searchUiSettings.favorites val favorites = searchUiSettings.favorites
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
@ -139,6 +150,13 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
searchUiSettings.setReversedResults(reverseSearchResults) searchUiSettings.setReversedResults(reverseSearchResults)
} }
val separateWorkProfile = searchUiSettings.separateWorkProfile
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
fun setSeparateWorkProfile(separateWorkProfile: Boolean) {
searchUiSettings.setSeparateWorkProfile(separateWorkProfile)
}
fun requestAppShortcutsPermission(activity: AppCompatActivity) { fun requestAppShortcutsPermission(activity: AppCompatActivity) {
permissionsManager.requestPermission(activity, PermissionGroup.AppShortcuts) permissionsManager.requestPermission(activity, PermissionGroup.AppShortcuts)
} }

View File

@ -898,4 +898,6 @@
<string name="plugin_weather_provider_enabled">Currently set as weather provider</string> <string name="plugin_weather_provider_enabled">Currently set as weather provider</string>
<string name="cached_searchable">Showing a cached version, information might be outdated.</string> <string name="cached_searchable">Showing a cached version, information might be outdated.</string>
<string name="unavailable_searchable">This item does not exist anymore.</string> <string name="unavailable_searchable">This item does not exist anymore.</string>
<string name="preference_search_bar_separate_work_profile">Separate work profile apps</string>
<string name="preference_search_bar_separate_work_profile_summary">Shows work profile apps in a separate list</string>
</resources> </resources>

View File

@ -79,6 +79,7 @@ data class LauncherSettingsData(
val searchResultsReversed: Boolean = false, val searchResultsReversed: Boolean = false,
val searchResultOrder: SearchResultOrder = SearchResultOrder.Weighted, val searchResultOrder: SearchResultOrder = SearchResultOrder.Weighted,
val separateWorkProfile: Boolean = true,
val rankingWeightFactor: WeightFactor = WeightFactor.Default, val rankingWeightFactor: WeightFactor = WeightFactor.Default,

View File

@ -62,4 +62,13 @@ class SearchUiSettings internal constructor(
} }
} }
val separateWorkProfile
get() = launcherDataStore.data.map { it.separateWorkProfile }.distinctUntilChanged()
fun setSeparateWorkProfile(separateWorkProfile: Boolean) {
launcherDataStore.update {
it.copy(separateWorkProfile = separateWorkProfile)
}
}
} }