This commit is contained in:
MM20
2023-01-17 18:55:30 +01:00
parent 4fba96a75a
commit c12c07fa45
28 changed files with 752 additions and 45 deletions
+1
View File
@@ -137,6 +137,7 @@ dependencies {
implementation(project(":data:wikipedia"))
implementation(project(":core:database"))
implementation(project(":data:search-actions"))
implementation(project(":services:global-actions"))
// Uncomment this if you want annoying notifications in your debug builds yelling at you how terrible your code is
//debugImplementation(libs.leakcanary)
@@ -24,6 +24,7 @@ import de.mm20.launcher2.websites.websitesModule
import de.mm20.launcher2.widgets.widgetsModule
import de.mm20.launcher2.wikipedia.wikipediaModule
import de.mm20.launcher2.database.databaseModule
import de.mm20.launcher2.globalactions.globalActionsModule
import de.mm20.launcher2.notifications.notificationsModule
import de.mm20.launcher2.permissions.permissionsModule
import de.mm20.launcher2.preferences.preferencesModule
@@ -64,6 +65,7 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory {
databaseModule,
favoritesModule,
filesModule,
globalActionsModule,
iconsModule,
musicModule,
notificationsModule,
+1
View File
@@ -143,4 +143,5 @@ dependencies {
implementation(project(":services:accounts"))
implementation(project(":services:backup"))
implementation(project(":data:search-actions"))
implementation(project(":services:global-actions"))
}
@@ -0,0 +1,9 @@
package de.mm20.launcher2.ui.gestures
enum class Gesture {
DoubleTap,
LongPress,
SwipeDown,
SwipeLeft,
SwipeRight,
}
@@ -1,12 +1,23 @@
package de.mm20.launcher2.ui.launcher
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.globalactions.GlobalActionsService
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.preferences.Settings.GestureSettings
import de.mm20.launcher2.preferences.Settings.GestureSettings.GestureAction
import de.mm20.launcher2.ui.gestures.Gesture
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@@ -17,6 +28,19 @@ import org.koin.core.component.inject
class LauncherScaffoldVM : ViewModel(), KoinComponent {
private val dataStore: LauncherDataStore by inject()
private val globalActionsService: GlobalActionsService by inject()
private val permissionsManager: PermissionsManager by inject()
private var gestureSettings : GestureSettings? = null
init {
viewModelScope.launch {
dataStore.data.map { it.gestures }.collectLatest {
gestureSettings = it
}
}
}
private var isSystemInDarkMode = MutableStateFlow(false)
@@ -84,4 +108,68 @@ class LauncherScaffoldVM : ViewModel(), KoinComponent {
val fillClockHeight = dataStore.data.map { it.clockWidget.fillHeight }.asLiveData()
val searchBarColor = dataStore.data.map { it.searchBar.color }.asLiveData()
val searchBarStyle = dataStore.data.map { it.searchBar.searchBarStyle }.asLiveData()
}
var failedGestureState by mutableStateOf<FailedGesture?>(null)
fun handleGesture(gesture: Gesture): Boolean {
val action = when (gesture) {
Gesture.DoubleTap -> gestureSettings?.doubleTap
Gesture.LongPress -> gestureSettings?.longPress
Gesture.SwipeDown -> gestureSettings?.swipeDown?.takeIf { baseLayout.value != Settings.LayoutSettings.Layout.PullDown }
Gesture.SwipeLeft -> gestureSettings?.swipeLeft?.takeIf { baseLayout.value != Settings.LayoutSettings.Layout.Pager }
Gesture.SwipeRight -> gestureSettings?.swipeRight?.takeIf { baseLayout.value != Settings.LayoutSettings.Layout.PagerReversed }
}
val requiresAccessibilityService =
action == GestureAction.OpenRecents
|| action == GestureAction.OpenPowerDialog
|| action == GestureAction.OpenQuickSettings
|| action == GestureAction.OpenNotificationDrawer
|| action == GestureAction.LockScreen
if (action != null && requiresAccessibilityService && !permissionsManager.checkPermissionOnce(PermissionGroup.Accessibility)) {
failedGestureState = FailedGesture(gesture, action)
return true
}
return when (action) {
GestureAction.OpenSearch -> {
openSearch()
true
}
GestureAction.OpenNotificationDrawer -> {
globalActionsService.openNotificationDrawer()
true
}
GestureAction.OpenQuickSettings -> {
globalActionsService.openQuickSettings()
true
}
GestureAction.LockScreen -> {
globalActionsService.lockScreen()
true
}
GestureAction.OpenPowerDialog -> {
globalActionsService.openPowerDialog()
true
}
GestureAction.OpenRecents -> {
globalActionsService.openRecents()
true
}
else -> false
}
}
fun dismissGestureFailedSheet() {
failedGestureState = null
}
}
data class FailedGesture(val gesture: Gesture, val action: GestureAction)
@@ -4,7 +4,6 @@ import android.app.WallpaperManager
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.background
@@ -37,6 +36,7 @@ import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import de.mm20.launcher2.globalactions.GlobalActionsService
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.preferences.Settings.SystemBarsSettings.SystemBarColors
import de.mm20.launcher2.ui.assistant.AssistantScaffold
@@ -44,13 +44,14 @@ import de.mm20.launcher2.ui.base.BaseActivity
import de.mm20.launcher2.ui.base.ProvideCurrentTime
import de.mm20.launcher2.ui.base.ProvideSettings
import de.mm20.launcher2.ui.component.NavBarEffects
import de.mm20.launcher2.ui.gestures.Gesture
import de.mm20.launcher2.ui.gestures.GestureDetector
import de.mm20.launcher2.ui.gestures.GestureHandler
import de.mm20.launcher2.ui.gestures.LocalGestureDetector
import de.mm20.launcher2.ui.ktx.animateTo
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.sheets.CustomizeSearchableSheet
import de.mm20.launcher2.ui.launcher.sheets.EditFavoritesSheet
import de.mm20.launcher2.ui.launcher.sheets.FailedGestureSheet
import de.mm20.launcher2.ui.launcher.sheets.LauncherBottomSheets
import de.mm20.launcher2.ui.launcher.sheets.LauncherBottomSheetManager
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
import de.mm20.launcher2.ui.launcher.transitions.HomeTransition
@@ -62,6 +63,7 @@ import de.mm20.launcher2.ui.locals.LocalWallpaperColors
import de.mm20.launcher2.ui.locals.LocalWindowSize
import de.mm20.launcher2.ui.theme.LauncherTheme
import de.mm20.launcher2.ui.theme.wallpaperColorsAsState
import org.koin.android.ext.android.inject
import kotlin.math.absoluteValue
import kotlin.math.pow
@@ -70,7 +72,9 @@ abstract class SharedLauncherActivity(
private val mode: LauncherActivityMode
) : BaseActivity() {
private val viewModel: LauncherActivityVM by viewModels()
private val viewModel: LauncherScaffoldVM by viewModels()
private val globalActionsService: GlobalActionsService by inject()
internal val homeTransitionManager = HomeTransitionManager()
@@ -256,52 +260,43 @@ abstract class SharedLauncherActivity(
) { enterTransitionProgress.value }
}
}
bottomSheetManager.customizeSearchableSheetShown.value?.let {
CustomizeSearchableSheet(
searchable = it,
onDismiss = { bottomSheetManager.dismissCustomizeSearchableModal() })
}
if (bottomSheetManager.editFavoritesSheetShown.value) {
EditFavoritesSheet(onDismiss = { bottomSheetManager.dismissEditFavoritesSheet() })
}
LauncherBottomSheets()
}
val swipeThreshold = 150.dp.toPixels()
GestureHandler(
detector = gestureDetector,
onDoubleTap = {
Log.d("MM20", "Double tap")
viewModel.handleGesture(Gesture.DoubleTap)
},
onLongPress = {
Log.d("MM20", "Long press")
viewModel.handleGesture(Gesture.LongPress)
},
onDrag = {
return@GestureHandler when {
it.x > swipeThreshold && it.x.absoluteValue > it.y.absoluteValue * 2f -> {
Log.d("MM20", "Swipe right")
true
viewModel.handleGesture(Gesture.SwipeRight)
}
it.x < -swipeThreshold && it.x.absoluteValue > it.y.absoluteValue * 2f -> {
Log.d("MM20", "Swipe left")
true
viewModel.handleGesture(Gesture.SwipeLeft)
}
it.y > swipeThreshold && it.y.absoluteValue > it.x.absoluteValue * 2f -> {
Log.d("MM20", "Swipe down")
true
viewModel.handleGesture(Gesture.SwipeDown)
}
it.y < -swipeThreshold && it.y.absoluteValue > it.x.absoluteValue * 2f -> {
Log.d("MM20", "Swipe up")
true
}
else -> false
}
}
)
if (viewModel.failedGestureState != null) {
FailedGestureSheet(
failedGesture = viewModel.failedGestureState!!,
onDismiss = {
viewModel.dismissGestureFailedSheet()
}
)
}
}
}
}
@@ -0,0 +1,79 @@
package de.mm20.launcher2.ui.launcher.sheets
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.BottomSheetDialog
import de.mm20.launcher2.ui.component.MissingPermissionBanner
import de.mm20.launcher2.ui.gestures.Gesture
import de.mm20.launcher2.ui.launcher.FailedGesture
@Composable
fun FailedGestureSheet(
failedGesture: FailedGesture,
onDismiss: () -> Unit,
) {
val viewModel: FailedGestureSheetVM = viewModel()
val actionName = stringResource(when(failedGesture.action) {
Settings.GestureSettings.GestureAction.OpenSearch -> R.string.gesture_action_open_search
Settings.GestureSettings.GestureAction.OpenNotificationDrawer -> R.string.gesture_action_notifications
Settings.GestureSettings.GestureAction.LockScreen -> R.string.gesture_action_lock_screen
Settings.GestureSettings.GestureAction.OpenQuickSettings -> R.string.gesture_action_quick_settings
Settings.GestureSettings.GestureAction.OpenRecents -> R.string.gesture_action_recents
Settings.GestureSettings.GestureAction.OpenPowerDialog -> R.string.gesture_action_power_menu
else -> R.string.gesture_action_none
})
val gestureName = stringResource(when(failedGesture.gesture) {
Gesture.DoubleTap -> R.string.preference_gesture_double_tap
Gesture.LongPress -> R.string.preference_gesture_long_press
Gesture.SwipeDown -> R.string.preference_gesture_swipe_down
Gesture.SwipeLeft -> R.string.preference_gesture_swipe_left
Gesture.SwipeRight -> R.string.preference_gesture_swipe_right
})
BottomSheetDialog(
title = { Text(actionName) },
onDismissRequest = onDismiss,
) {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(it)
) {
Text(
stringResource(R.string.gesture_failed_message, gestureName, actionName),
style = MaterialTheme.typography.bodySmall
)
val context = LocalLifecycleOwner.current
MissingPermissionBanner(
modifier = Modifier.padding(vertical = 16.dp),
text = stringResource(id = R.string.missing_permission_accessibility_gesture_failed),
secondaryAction = {
OutlinedButton(onClick = {
viewModel.disableGesture(failedGesture.gesture)
onDismiss()
}) {
Text(stringResource(R.string.turn_off))
}
},
onClick = {
viewModel.requestPermission(context as AppCompatActivity)
onDismiss()
})
}
}
}
@@ -0,0 +1,40 @@
package de.mm20.launcher2.ui.launcher.sheets
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings.GestureSettings.GestureAction
import de.mm20.launcher2.ui.gestures.Gesture
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class FailedGestureSheetVM : ViewModel(), KoinComponent {
private val permissionsManager: PermissionsManager by inject()
private val dataStore: LauncherDataStore by inject()
fun requestPermission(context: AppCompatActivity) {
permissionsManager.requestPermission(context, PermissionGroup.Accessibility)
}
fun disableGesture(gesture: Gesture) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(
it.gestures.toBuilder().apply {
when (gesture) {
Gesture.SwipeDown -> swipeDown = GestureAction.None
Gesture.SwipeLeft -> swipeLeft = GestureAction.None
Gesture.SwipeRight -> swipeRight = GestureAction.None
Gesture.DoubleTap -> doubleTap = GestureAction.None
Gesture.LongPress -> longPress = GestureAction.None
}
}.build()
).build()
}
}
}
}
@@ -0,0 +1,16 @@
package de.mm20.launcher2.ui.launcher.sheets
import androidx.compose.runtime.Composable
@Composable
fun LauncherBottomSheets() {
val bottomSheetManager = LocalBottomSheetManager.current
bottomSheetManager.customizeSearchableSheetShown.value?.let {
CustomizeSearchableSheet(
searchable = it,
onDismiss = { bottomSheetManager.dismissCustomizeSearchableModal() })
}
if (bottomSheetManager.editFavoritesSheetShown.value) {
EditFavoritesSheet(onDismiss = { bottomSheetManager.dismissEditFavoritesSheet() })
}
}
@@ -39,6 +39,7 @@ import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
import de.mm20.launcher2.ui.settings.easteregg.EasterEggSettingsScreen
import de.mm20.launcher2.ui.settings.favorites.FavoritesSettingsScreen
import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen
import de.mm20.launcher2.ui.settings.gestures.GestureSettingsScreen
import de.mm20.launcher2.ui.settings.hiddenitems.HiddenItemsSettingsScreen
import de.mm20.launcher2.ui.settings.layout.LayoutSettingsScreen
import de.mm20.launcher2.ui.settings.license.LicenseScreen
@@ -115,6 +116,9 @@ class SettingsActivity : BaseActivity() {
composable("settings/search") {
SearchSettingsScreen()
}
composable("settings/gestures") {
GestureSettingsScreen()
}
composable("settings/search/unitconverter") {
UnitConverterSettingsScreen()
}
@@ -0,0 +1,131 @@
package de.mm20.launcher2.ui.settings.gestures
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.Settings.GestureSettings.GestureAction
import de.mm20.launcher2.preferences.Settings.LayoutSettings.Layout
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.MissingPermissionBanner
import de.mm20.launcher2.ui.component.preferences.ListPreference
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
@Composable
fun GestureSettingsScreen() {
val viewModel: GestureSettingsScreenVM = viewModel()
val layout by viewModel.layout.observeAsState()
val hasPermission by viewModel.hasPermission.observeAsState()
val options = buildList {
add(stringResource(R.string.gesture_action_none) to GestureAction.None)
add(stringResource(R.string.gesture_action_notifications) to GestureAction.OpenNotificationDrawer)
add(stringResource(R.string.gesture_action_quick_settings) to GestureAction.OpenQuickSettings)
if (isAtLeastApiLevel(28)) add(stringResource(R.string.gesture_action_lock_screen) to GestureAction.LockScreen)
add(stringResource(R.string.gesture_action_recents) to GestureAction.OpenRecents)
add(stringResource(R.string.gesture_action_power_menu) to GestureAction.OpenPowerDialog)
add(stringResource(R.string.gesture_action_open_search) to GestureAction.OpenSearch)
}
val context = LocalContext.current
PreferenceScreen(title = stringResource(R.string.preference_screen_gestures)) {
item {
PreferenceCategory {
val doubleTap by viewModel.doubleTap.observeAsState()
AnimatedVisibility(hasPermission == false && requiresAccessibilityService(doubleTap)) {
MissingPermissionBanner(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.missing_permission_accessibility_gesture_settings),
onClick = { viewModel.requestPermission(context as AppCompatActivity) }
)
}
ListPreference(
title = stringResource(R.string.preference_gesture_double_tap),
items = options,
value = doubleTap,
onValueChanged = { if (it != null) viewModel.setDoubleTap(it) }
)
val longPress by viewModel.longPress.observeAsState()
AnimatedVisibility(hasPermission == false && requiresAccessibilityService(longPress)) {
MissingPermissionBanner(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.missing_permission_accessibility_gesture_settings),
onClick = { viewModel.requestPermission(context as AppCompatActivity) }
)
}
ListPreference(
title = stringResource(R.string.preference_gesture_long_press),
items = options,
value = longPress,
onValueChanged = { if (it != null) viewModel.setLongPress(it) }
)
val swipeDown by viewModel.swipeDown.observeAsState()
AnimatedVisibility(hasPermission == false && requiresAccessibilityService(swipeDown)) {
MissingPermissionBanner(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.missing_permission_accessibility_gesture_settings),
onClick = { viewModel.requestPermission(context as AppCompatActivity) }
)
}
ListPreference(
title = stringResource(R.string.preference_gesture_swipe_down),
enabled = layout != Layout.PullDown,
items = options,
value = if (layout == Layout.PullDown) GestureAction.OpenSearch else swipeDown,
onValueChanged = { if (it != null) viewModel.setSwipeDown(it) }
)
val swipeLeft by viewModel.swipeLeft.observeAsState()
AnimatedVisibility(hasPermission == false && requiresAccessibilityService(swipeLeft)) {
MissingPermissionBanner(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.missing_permission_accessibility_gesture_settings),
onClick = { viewModel.requestPermission(context as AppCompatActivity) }
)
}
ListPreference(
title = stringResource(R.string.preference_gesture_swipe_left),
enabled = layout != Layout.Pager,
items = options,
value = if (layout == Layout.Pager) GestureAction.OpenSearch else swipeLeft,
onValueChanged = { if (it != null) viewModel.setSwipeLeft(it) }
)
val swipeRight by viewModel.swipeRight.observeAsState()
AnimatedVisibility(hasPermission == false && requiresAccessibilityService(swipeRight)) {
MissingPermissionBanner(
modifier = Modifier.padding(16.dp),
text = stringResource(R.string.missing_permission_accessibility_gesture_settings),
onClick = { viewModel.requestPermission(context as AppCompatActivity) }
)
}
ListPreference(
title = stringResource(R.string.preference_gesture_swipe_right),
enabled = layout != Layout.PagerReversed,
items = options,
value = if (layout == Layout.PagerReversed) GestureAction.OpenSearch else swipeRight,
onValueChanged = { if (it != null) viewModel.setSwipeRight(it) }
)
}
}
}
}
fun requiresAccessibilityService(action: GestureAction?) : Boolean{
return when(action) {
GestureAction.OpenNotificationDrawer,
GestureAction.LockScreen,
GestureAction.OpenQuickSettings,
GestureAction.OpenRecents,
GestureAction.OpenPowerDialog -> true
else -> false
}
}
@@ -0,0 +1,78 @@
package de.mm20.launcher2.ui.settings.gestures
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings.GestureSettings.GestureAction
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class GestureSettingsScreenVM : ViewModel(), KoinComponent {
private val dataStore: LauncherDataStore by inject()
private val permissionsManager: PermissionsManager by inject()
val hasPermission = permissionsManager.hasPermission(PermissionGroup.Accessibility).asLiveData()
val layout = dataStore.data.map { it.layout.baseLayout }.asLiveData()
val swipeDown = dataStore.data.map { it.gestures.swipeDown }.asLiveData()
val swipeLeft = dataStore.data.map { it.gestures.swipeLeft }.asLiveData()
val swipeRight = dataStore.data.map { it.gestures.swipeRight }.asLiveData()
val doubleTap = dataStore.data.map { it.gestures.doubleTap }.asLiveData()
val longPress = dataStore.data.map { it.gestures.longPress }.asLiveData()
fun setSwipeDown(action: GestureAction) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(it.gestures.toBuilder().setSwipeDown(action).build())
.build()
}
}
}
fun setSwipeLeft(action: GestureAction) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(it.gestures.toBuilder().setSwipeLeft(action).build())
.build()
}
}
}
fun setSwipeRight(action: GestureAction) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(it.gestures.toBuilder().setSwipeRight(action).build())
.build()
}
}
}
fun setDoubleTap(action: GestureAction) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(it.gestures.toBuilder().setDoubleTap(action).build())
.build()
}
}
}
fun setLongPress(action: GestureAction) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder().setGestures(it.gestures.toBuilder().setLongPress(action).build())
.build()
}
}
}
fun requestPermission(context: AppCompatActivity) {
permissionsManager.requestPermission(context, PermissionGroup.Accessibility)
}
}
@@ -46,6 +46,14 @@ fun MainSettingsScreen() {
navController?.navigate("settings/widgets")
}
)
Preference(
icon = Icons.Rounded.Gesture,
title = stringResource(id = R.string.preference_screen_gestures),
summary = stringResource(id = R.string.preference_screen_gestures_summary),
onClick = {
navController?.navigate("settings/gestures")
}
)
Preference(
icon = Icons.Rounded.NotificationBadge,
title = stringResource(id = R.string.preference_screen_badges),