Add a preference to hide the edit favorites button
This commit is contained in:
parent
a2aca9bded
commit
9309cd4891
@ -620,6 +620,8 @@
|
||||
<string name="preference_edit_favorites_summary">Change the order of pinned items</string>
|
||||
<string name="preference_category_favorites_frequently_used">Frequently used</string>
|
||||
<string name="preference_favorites_frequently_used_summary">Show frequently used items in favorites</string>
|
||||
<string name="preference_edit_button">Edit button</string>
|
||||
<string name="preference_favorites_edit_button_summary">Show a button to rearrange the favorites</string>
|
||||
<!-- Used in an info banner if a specific feature requires a Nextcloud account -->
|
||||
<string name="no_account_nextcloud">You haven\'t connected a Nextcloud account yet</string>
|
||||
<!-- Used in an info banner if a specific feature requires an Owncloud account -->
|
||||
|
||||
@ -59,6 +59,7 @@ fun createFactorySettings(context: Context): Settings {
|
||||
.setEnabled(true)
|
||||
.setFrequentlyUsed(true)
|
||||
.setFrequentlyUsedRows(1)
|
||||
.setEditButton(true)
|
||||
)
|
||||
.setFileSearch(
|
||||
Settings.FilesSearchSettings
|
||||
|
||||
@ -8,6 +8,7 @@ class Migration_9_10: VersionedMigration(9, 10) {
|
||||
builder.favorites.toBuilder()
|
||||
.setFrequentlyUsed(true)
|
||||
.setFrequentlyUsedRows(1)
|
||||
.setEditButton(true)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -128,6 +128,7 @@ message Settings {
|
||||
bool enabled = 1;
|
||||
bool frequently_used = 2;
|
||||
int32 frequently_used_rows = 3;
|
||||
bool edit_button = 4;
|
||||
}
|
||||
FavoritesSettings favorites = 8;
|
||||
|
||||
|
||||
@ -22,6 +22,8 @@ open class FavoritesVM : ViewModel(), KoinComponent {
|
||||
|
||||
val selectedTag = MutableStateFlow<String?>(null)
|
||||
|
||||
val showEditButton = dataStore.data.map { it.favorites.editButton }
|
||||
|
||||
val pinnedTags = favoritesRepository.getFavorites(
|
||||
includeTypes = listOf("tag"),
|
||||
manuallySorted = true,
|
||||
|
||||
@ -2,14 +2,39 @@ package de.mm20.launcher2.ui.launcher.search
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material.icons.rounded.Edit
|
||||
import androidx.compose.material.icons.rounded.Person
|
||||
import androidx.compose.material.icons.rounded.Star
|
||||
import androidx.compose.material.icons.rounded.Tag
|
||||
import androidx.compose.material.icons.rounded.Work
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FloatingActionButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.SmallFloatingActionButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
@ -82,6 +107,7 @@ fun SearchColumn(
|
||||
val pinnedTags by favoritesVM.pinnedTags.collectAsState(emptyList())
|
||||
val selectedTag by favoritesVM.selectedTag.collectAsState(null)
|
||||
val tagsScrollState = rememberScrollState()
|
||||
val favoritesEditButton by favoritesVM.showEditButton.collectAsState(false)
|
||||
|
||||
LazyColumn(
|
||||
state = state,
|
||||
@ -115,56 +141,62 @@ fun SearchColumn(
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
after = {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = if (reverse) 8.dp else 4.dp,
|
||||
bottom = if (reverse) 4.dp else 8.dp,
|
||||
end = 8.dp
|
||||
),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
after = if (pinnedTags.isEmpty() && !favoritesEditButton) {
|
||||
null
|
||||
} else {
|
||||
{
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.horizontalScroll(tagsScrollState)
|
||||
.padding(end = 12.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = if (reverse) 8.dp else 4.dp,
|
||||
bottom = if (reverse) 4.dp else 8.dp,
|
||||
end = if (favoritesEditButton) 8.dp else 0.dp
|
||||
),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
selected = selectedTag == null,
|
||||
onClick = { favoritesVM.selectTag(null) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Star,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.favorites)) }
|
||||
)
|
||||
for (tag in pinnedTags) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.horizontalScroll(tagsScrollState)
|
||||
.padding(end = 12.dp),
|
||||
) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
selected = selectedTag == tag.tag,
|
||||
onClick = { favoritesVM.selectTag(tag.tag) },
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
selected = selectedTag == null,
|
||||
onClick = { favoritesVM.selectTag(null) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Tag,
|
||||
imageVector = Icons.Rounded.Star,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(tag.label) }
|
||||
label = { Text(stringResource(R.string.favorites)) }
|
||||
)
|
||||
for (tag in pinnedTags) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
selected = selectedTag == tag.tag,
|
||||
onClick = { favoritesVM.selectTag(tag.tag) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Tag,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(tag.label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (favoritesEditButton) {
|
||||
SmallFloatingActionButton(
|
||||
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation(),
|
||||
onClick = { showEditFavoritesDialog = true }
|
||||
) {
|
||||
Icon(imageVector = Icons.Rounded.Edit, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
SmallFloatingActionButton(
|
||||
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation(),
|
||||
onClick = { showEditFavoritesDialog = true }
|
||||
) {
|
||||
Icon(imageVector = Icons.Rounded.Edit, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -221,22 +253,24 @@ fun SearchColumn(
|
||||
} else null
|
||||
)
|
||||
ListResults(
|
||||
before = if (missingShortcutsPermission && !isSearchEmpty){{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_appshortcuts_search),
|
||||
onClick = { viewModel.requestAppShortcutPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableAppShortcutSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
before = if (missingShortcutsPermission && !isSearchEmpty) {
|
||||
{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_appshortcuts_search),
|
||||
onClick = { viewModel.requestAppShortcutPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableAppShortcutSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}} else null,
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
items = appShortcuts.toImmutableList(),
|
||||
reverse = reverse,
|
||||
key = "shortcuts"
|
||||
@ -254,42 +288,47 @@ fun SearchColumn(
|
||||
}
|
||||
}
|
||||
ListResults(
|
||||
before = if (missingCalendarPermission && !isSearchEmpty){{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_calendar_search),
|
||||
onClick = { viewModel.requestCalendarPermission(context as AppCompatActivity) },secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableCalendarSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
before = if (missingCalendarPermission && !isSearchEmpty) {
|
||||
{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_calendar_search),
|
||||
onClick = { viewModel.requestCalendarPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableCalendarSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}} else null,
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
items = events.toImmutableList(),
|
||||
reverse = reverse,
|
||||
key = "events"
|
||||
)
|
||||
ListResults(
|
||||
before = if (missingContactsPermission && !isSearchEmpty){{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_contact_search),
|
||||
onClick = { viewModel.requestContactsPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableContactsSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
before = if (missingContactsPermission && !isSearchEmpty) {
|
||||
{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_contact_search),
|
||||
onClick = { viewModel.requestContactsPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableContactsSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}} else null,
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
items = contacts.toImmutableList(),
|
||||
reverse = reverse,
|
||||
key = "contacts"
|
||||
@ -307,22 +346,24 @@ fun SearchColumn(
|
||||
}
|
||||
}
|
||||
ListResults(
|
||||
before = if (missingFilesPermission && !isSearchEmpty){{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_files_search),
|
||||
onClick = { viewModel.requestFilesPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableFilesSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
before = if (missingFilesPermission && !isSearchEmpty) {
|
||||
{
|
||||
MissingPermissionBanner(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.missing_permission_files_search),
|
||||
onClick = { viewModel.requestFilesPermission(context as AppCompatActivity) },
|
||||
secondaryAction = {
|
||||
OutlinedButton(onClick = {
|
||||
viewModel.disableFilesSearch()
|
||||
}) {
|
||||
Text(
|
||||
stringResource(R.string.turn_off),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}} else null,
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
items = files.toImmutableList(),
|
||||
reverse = reverse,
|
||||
key = "files"
|
||||
|
||||
@ -1,14 +1,28 @@
|
||||
package de.mm20.launcher2.ui.launcher.widgets.favorites
|
||||
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Edit
|
||||
import androidx.compose.material.icons.rounded.Star
|
||||
import androidx.compose.material.icons.rounded.Tag
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FloatingActionButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SmallFloatingActionButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@ -25,6 +39,7 @@ fun FavoritesWidget() {
|
||||
val pinnedTags by viewModel.pinnedTags.collectAsState(emptyList())
|
||||
val selectedTag by viewModel.selectedTag.collectAsState(null)
|
||||
var showEditFavoritesDialog by remember { mutableStateOf(false) }
|
||||
val favoritesEditButton by viewModel.showEditButton.collectAsState(false)
|
||||
|
||||
Column {
|
||||
if (favorites.isNotEmpty()) {
|
||||
@ -41,54 +56,59 @@ fun FavoritesWidget() {
|
||||
color = MaterialTheme.colorScheme.outline
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = 4.dp,
|
||||
bottom = 8.dp,
|
||||
end = 8.dp
|
||||
),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (pinnedTags.isNotEmpty() || favoritesEditButton) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.horizontalScroll(rememberScrollState()),
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = 4.dp,
|
||||
bottom = 8.dp,
|
||||
end = if (favoritesEditButton) 8.dp else 0.dp
|
||||
),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
selected = selectedTag == null,
|
||||
onClick = { viewModel.selectTag(null) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Star,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(stringResource(R.string.favorites)) }
|
||||
)
|
||||
for (tag in pinnedTags) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.horizontalScroll(rememberScrollState())
|
||||
.padding(end = 12.dp),
|
||||
) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
selected = selectedTag == tag.tag,
|
||||
onClick = { viewModel.selectTag(tag.tag) },
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
selected = selectedTag == null,
|
||||
onClick = { viewModel.selectTag(null) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Tag,
|
||||
imageVector = Icons.Rounded.Star,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(tag.label) }
|
||||
label = { Text(stringResource(R.string.favorites)) }
|
||||
)
|
||||
for (tag in pinnedTags) {
|
||||
FilterChip(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
selected = selectedTag == tag.tag,
|
||||
onClick = { viewModel.selectTag(tag.tag) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Tag,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(tag.label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (favoritesEditButton) {
|
||||
SmallFloatingActionButton(
|
||||
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation(),
|
||||
onClick = { showEditFavoritesDialog = true }
|
||||
) {
|
||||
Icon(imageVector = Icons.Rounded.Edit, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
SmallFloatingActionButton(
|
||||
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation(),
|
||||
onClick = { showEditFavoritesDialog = true }
|
||||
) {
|
||||
Icon(imageVector = Icons.Rounded.Edit, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,19 @@ fun FavoritesSettingsScreen() {
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
val editButton by viewModel.editButton.observeAsState()
|
||||
PreferenceCategory {
|
||||
SwitchPreference(
|
||||
title = stringResource(R.string.preference_edit_button),
|
||||
summary = stringResource(R.string.preference_favorites_edit_button_summary),
|
||||
value = editButton == true,
|
||||
onValueChanged = {
|
||||
viewModel.setEditButton(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showEditSheet) {
|
||||
|
||||
@ -39,4 +39,18 @@ class FavoritesSettingsScreenVM: ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val editButton = dataStore.data.map { it.favorites.editButton }.asLiveData()
|
||||
fun setEditButton(editButton: Boolean) {
|
||||
viewModelScope.launch {
|
||||
dataStore.updateData {
|
||||
it.toBuilder()
|
||||
.setFavorites(
|
||||
it.favorites.toBuilder()
|
||||
.setEditButton(editButton)
|
||||
)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user