Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ fun SearchColumn(
val favoritesVM: SearchFavoritesVM = viewModel()
val favorites by favoritesVM.favorites.collectAsState(emptyList())

val hidePrivateProfile by viewModel.hidePrivateProfile.collectAsState()
val showUnlockPrivateProfile by viewModel.showUnlockPrivateProfile
val isPrivateProfileLocked by viewModel.isPrivateProfileLocked.collectAsState(false)
val hideFavs by viewModel.hideFavorites
val favoritesEnabled by viewModel.favoritesEnabled.collectAsState(false)

Expand Down Expand Up @@ -204,19 +207,33 @@ fun SearchColumn(
showList = showList,
selectedIndex = selectedAppIndex,
onSelect = { selectedAppIndex = it },
hidePrivateProfile = hidePrivateProfile,
isPrivateProfileLocked = isPrivateProfileLocked,
showUnlockPrivateProfile = showUnlockPrivateProfile
)
} else {
val privateProfileIndex = profiles.indexOfFirst { it.type == Profile.Type.Private };
AppResults(
apps = apps,
highlightedItem = bestMatch as? Application,
profiles = profiles,
onProfileSelected = {
selectedAppProfileIndex = it
},
onProfileLockChange = { p, l ->
viewModel.setProfileLock(p, l)
viewModel.reset()
},
columns = columns,
reverse = reverse,
showProfileLockControls = hasProfilesPermission,
showList = showList,
selectedIndex = selectedAppIndex,
onSelect = { selectedAppIndex = it },
hidePrivateProfile = hidePrivateProfile,
isPrivateProfileLocked = isPrivateProfileLocked,
showUnlockPrivateProfile = showUnlockPrivateProfile,
privateProfileIndex = privateProfileIndex
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class SearchVM : ViewModel(), KoinComponent {
val launchOnEnter = searchUiSettings.launchOnEnter
.stateIn(viewModelScope, SharingStarted.Eagerly, false)

val hidePrivateProfile = searchUiSettings.hidePrivateProfile
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), false)
var showUnlockPrivateProfile = mutableStateOf(false)

private val searchService: SearchService by inject()

val searchQuery = mutableStateOf("")
Expand All @@ -92,6 +96,11 @@ class SearchVM : ViewModel(), KoinComponent {
it.toList()
}
}
val isPrivateProfileLocked = profileManager.isPrivateProfileLocked.shareIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
replay = 1
)

val hasProfilesPermission = permissionsManager.hasPermission(PermissionGroup.ManageProfiles)

Expand Down Expand Up @@ -257,6 +266,13 @@ class SearchVM : ViewModel(), KoinComponent {
}

} else {
if (hidePrivateProfile.value) {
val score = ResultScore(
query = query,
primaryFields = listOf("Private Space")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be translatable

)
showUnlockPrivateProfile.value = score.isPrefix && query.length >= 3
}
val hiddenItemKeys = if (!filters.hiddenItems) searchableRepository.getKeys(
maxVisibility = VisibilityLevel.Hidden,
) else flowOf(emptyList())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package de.mm20.launcher2.ui.launcher.search.apps
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -17,11 +19,13 @@ import androidx.compose.material.icons.rounded.Work
import androidx.compose.material.icons.rounded.WorkOff
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LeadingIconTab
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.PrimaryScrollableTabRow
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -55,8 +59,12 @@ fun LazyListScope.AppResults(
columns: Int,
reverse: Boolean,
showList: Boolean,
hidePrivateProfile: Boolean = false,
isPrivateProfileLocked: Boolean = false,
showUnlockPrivateProfile: Boolean = false,
privateProfileIndex: Int = -1
) {
val before = if (profiles.size > 1) {
val before = if (profiles.size > 1 && privateProfileIndex == -1) {
@Composable {
Column(
verticalArrangement = if (reverse) Arrangement.BottomReversed else Arrangement.Top,
Expand All @@ -68,6 +76,9 @@ fun LazyListScope.AppResults(
divider = {}
) {
for ((i, profile) in profiles.withIndex()) {
if (hidePrivateProfile && profile.type == Profile.Type.Private && isPrivateProfileLocked) {
continue
}
LeadingIconTab(
selected = selectedProfileIndex == profiles.indexOf(profile),
text = {
Expand Down Expand Up @@ -201,7 +212,77 @@ fun LazyListScope.AppResults(
}
}
}
} else null
} else {
if (hidePrivateProfile && isPrivateProfileLocked && showUnlockPrivateProfile) {
@Composable {
OutlinedCard(
modifier = Modifier.padding(8.dp),
colors = CardDefaults.outlinedCardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainer,
contentColor = MaterialTheme.colorScheme.secondary,
),
shape = MaterialTheme.shapes.small,
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier.padding(end = 16.dp),
imageVector = Icons.Rounded.Lock,
contentDescription = null
)
Text(
text = stringResource(R.string.profile_private_profile_state_locked),
modifier = Modifier.padding(top = 8.dp),
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.titleSmall,
)
}
FlowRow(
Modifier
.align(Alignment.End)
.padding(start = 12.dp, end = 12.dp, bottom = 12.dp),
horizontalArrangement = Arrangement.End,
verticalArrangement = Arrangement.Bottom,
itemVerticalAlignment = Alignment.CenterVertically,
) {
Box(modifier = Modifier.padding(start = 8.dp)) {
if (showProfileLockControls) {
Button(
// modifier = Modifier.padding(top = 32.dp),
onClick = {
onProfileLockChange?.invoke(
profiles[privateProfileIndex],
false
)
},
contentPadding = ButtonDefaults.TextButtonWithIconContentPadding,
) {
Icon(
Icons.Rounded.LockOpen,
contentDescription = null,
modifier = Modifier
.padding(end = ButtonDefaults.IconSpacing)
.size(ButtonDefaults.IconSize)
)
Text(
stringResource(
R.string.profile_private_profile_action_unlock
)
)
}
}
}
}
}
}
}
} else null
}
if (showList) {
ListResults(
key = "apps",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ fun SearchSettingsScreen() {
val websites by viewModel.websites.collectAsStateWithLifecycle(null)


val hidePrivateProfile by viewModel.hidePrivateProfile.collectAsStateWithLifecycle(null)
val autoFocus by viewModel.autoFocus.collectAsStateWithLifecycle(null)
val launchOnEnter by viewModel.launchOnEnter.collectAsStateWithLifecycle(null)
val reverseSearchResults by viewModel.reverseSearchResults.collectAsStateWithLifecycle(null)
Expand Down Expand Up @@ -300,6 +301,15 @@ fun SearchSettingsScreen() {
navController?.navigate("settings/search/hiddenitems")
}
)
SwitchPreference(
title = stringResource(R.string.preference_hide_private_profile),
iconPadding = true,
summary = stringResource(R.string.preference_hide_private_profile_summary),
value = hidePrivateProfile == true,
onValueChanged = {
viewModel.setHidePrivateProfile(it)
}
)
Preference(
title = stringResource(R.string.preference_screen_tags),
summary = stringResource(R.string.preference_screen_tags_summary),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,11 @@ class SearchSettingsScreenVM : ViewModel(), KoinComponent {
val isTasksAppInstalled = appRepository.findOne("org.tasks", Process.myUserHandle())
.map { it != null }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)

val hidePrivateProfile = searchUiSettings.hidePrivateProfile
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)

fun setHidePrivateProfile(hidePrivateProfile: Boolean) {
searchUiSettings.setHidePrivateProfile(hidePrivateProfile)
}
}
2 changes: 2 additions & 0 deletions core/i18n/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,8 @@
<string name="preference_search_bar_auto_focus_summary">Automatically show the keyboard when opening the app drawer</string>
<string name="preference_search_bar_launch_on_enter">Launch on enter</string>
<string name="preference_search_bar_launch_on_enter_summary">Launch highlighted match or quick action upon tapping go</string>
<string name="preference_hide_private_profile">Hide private space</string>
<string name="preference_hide_private_profile_summary">Hides private space in the app drawer (search "Private Space" to show)</string>
<string name="preference_hidden_items">Hidden search results</string>
<string name="preference_hidden_items_summary">Manage hidden apps and search results</string>
<string name="preference_hidden_items_reveal_button">Show reveal button</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ data class LauncherSettingsData internal constructor(

val searchResultsReversed: Boolean = false,
val separateWorkProfile: Boolean = true,
val hidePrivateProfile: Boolean = false,

val rankingWeightFactor: WeightFactor = WeightFactor.Default,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,12 @@ class SearchUiSettings internal constructor(
}
}

val hidePrivateProfile
get() = launcherDataStore.data.map { it.hidePrivateProfile }

fun setHidePrivateProfile(hidePrivateProfile: Boolean) {
launcherDataStore.update {
it.copy(hidePrivateProfile = hidePrivateProfile)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ class ProfileManager(
it.mapNotNull { it?.profile }
}.shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)

val isPrivateProfileLocked: Flow<Boolean> = profileStates.map {
it.any {
it?.state?.locked == true && it.profile.type == Profile.Type.Private
}
}

init {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Expand Down