mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 16:25:27 +02:00
Create shortcuts manually
This commit is contained in:
parent
93ca31a955
commit
83f092fb7c
@ -46,6 +46,7 @@ import com.sadellie.unitto.core.ui.common.isOpen
|
||||
import com.sadellie.unitto.core.ui.common.open
|
||||
import com.sadellie.unitto.core.ui.common.rememberUnittoDrawerState
|
||||
import com.sadellie.unitto.core.ui.model.DrawerItems
|
||||
import com.sadellie.unitto.core.ui.pushDynamicShortcut
|
||||
import com.sadellie.unitto.core.ui.theme.AppTypographySystem
|
||||
import com.sadellie.unitto.core.ui.theme.AppTypographyUnitto
|
||||
import com.sadellie.unitto.core.ui.theme.DarkThemeColors
|
||||
|
@ -101,11 +101,12 @@ sealed class TopLevelDestinations(
|
||||
}
|
||||
|
||||
// Shown in settings
|
||||
val TOP_LEVEL_GRAPH_ROUTES: Map<String, Int> by lazy {
|
||||
mapOf(
|
||||
TopLevelDestinations.Calculator.graph to R.string.calculator,
|
||||
TopLevelDestinations.Converter.graph to R.string.unit_converter,
|
||||
TopLevelDestinations.DateCalculator.graph to R.string.date_calculator,
|
||||
val TOP_LEVEL_DESTINATIONS by lazy {
|
||||
listOf(
|
||||
TopLevelDestinations.Calculator,
|
||||
TopLevelDestinations.Converter,
|
||||
TopLevelDestinations.DateCalculator,
|
||||
// TopLevelDestinations.TimeZone,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto
|
||||
package com.sadellie.unitto.core.ui
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
@ -41,7 +44,56 @@ suspend fun Context.pushDynamicShortcut(
|
||||
|
||||
val context = this@pushDynamicShortcut
|
||||
|
||||
val shortcut = ShortcutInfoCompat.Builder(context, route)
|
||||
val shortcut = shortcutInfoCompat(
|
||||
context = context,
|
||||
route = route,
|
||||
shortLabel = shortLabel,
|
||||
longLabel = longLabel,
|
||||
drawable = drawable
|
||||
)
|
||||
|
||||
kotlin.runCatching {
|
||||
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.addShortcut(
|
||||
route: String,
|
||||
@StringRes shortLabel: Int,
|
||||
@StringRes longLabel: Int,
|
||||
@DrawableRes drawable: Int,
|
||||
) {
|
||||
val context = this@addShortcut
|
||||
|
||||
val shortcut = shortcutInfoCompat(
|
||||
context = context,
|
||||
route = route,
|
||||
shortLabel = shortLabel,
|
||||
longLabel = longLabel,
|
||||
drawable = drawable
|
||||
)
|
||||
|
||||
val shortCutIntent = ShortcutManagerCompat.createShortcutResultIntent(context, shortcut)
|
||||
|
||||
try {
|
||||
ShortcutManagerCompat.requestPinShortcut(
|
||||
context,
|
||||
shortcut,
|
||||
PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.shortcutInfoCompat(
|
||||
context: Context,
|
||||
route: String,
|
||||
shortLabel: Int,
|
||||
longLabel: Int,
|
||||
drawable: Int,
|
||||
): ShortcutInfoCompat {
|
||||
return ShortcutInfoCompat.Builder(context, route)
|
||||
.setShortLabel(getString(shortLabel))
|
||||
.setLongLabel(getString(longLabel))
|
||||
.setIcon(IconCompat.createWithResource(context, drawable))
|
||||
@ -54,6 +106,4 @@ suspend fun Context.pushDynamicShortcut(
|
||||
)
|
||||
)
|
||||
.build()
|
||||
|
||||
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)
|
||||
}
|
@ -85,7 +85,12 @@ fun UnittoListItem(
|
||||
)
|
||||
}
|
||||
}
|
||||
trailingContent?.invoke()
|
||||
trailingContent?.let {
|
||||
ProvideColor(
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
content = it
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,6 @@ data class AppPreferences(
|
||||
)
|
||||
|
||||
data class GeneralPreferences(
|
||||
val startingScreen: String = TopLevelDestinations.Calculator.graph,
|
||||
val enableVibrations: Boolean = true,
|
||||
val middleZero: Boolean = false,
|
||||
)
|
||||
@ -133,6 +132,10 @@ data class AboutPreferences(
|
||||
val enableToolsExperiment: Boolean = false,
|
||||
)
|
||||
|
||||
data class StartingScreenPreferences(
|
||||
val startingScreen: String = TopLevelDestinations.Calculator.graph,
|
||||
)
|
||||
|
||||
class UserPreferencesRepository @Inject constructor(private val dataStore: DataStore<Preferences>) {
|
||||
private val data = dataStore.data
|
||||
.catch { if (it is IOException) emit(emptyPreferences()) else throw it }
|
||||
@ -160,8 +163,6 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
||||
val generalPrefs: Flow<GeneralPreferences> = data
|
||||
.map { preferences ->
|
||||
GeneralPreferences(
|
||||
startingScreen = preferences[PrefsKeys.STARTING_SCREEN]
|
||||
?: TopLevelDestinations.Calculator.graph,
|
||||
enableVibrations = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true,
|
||||
middleZero = preferences[PrefsKeys.MIDDLE_ZERO] ?: false,
|
||||
)
|
||||
@ -245,6 +246,14 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
||||
)
|
||||
}
|
||||
|
||||
val startingScreenPrefs: Flow<StartingScreenPreferences> = data
|
||||
.map { preferences ->
|
||||
StartingScreenPreferences(
|
||||
startingScreen = preferences[PrefsKeys.STARTING_SCREEN]
|
||||
?: TopLevelDestinations.Calculator.graph,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun updateDigitsPrecision(precision: Int) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[PrefsKeys.DIGITS_PRECISION] = precision
|
||||
|
@ -46,7 +46,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.sadellie.unitto.core.base.BuildConfig
|
||||
import com.sadellie.unitto.core.base.R
|
||||
import com.sadellie.unitto.core.base.TOP_LEVEL_GRAPH_ROUTES
|
||||
import com.sadellie.unitto.core.ui.common.Header
|
||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
||||
@ -58,43 +57,40 @@ import com.sadellie.unitto.feature.settings.navigation.aboutRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.calculatorSettingsRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.converterSettingsRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.formattingRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.startingScreenRoute
|
||||
import com.sadellie.unitto.feature.settings.navigation.themesRoute
|
||||
|
||||
@Composable
|
||||
internal fun SettingsRoute(
|
||||
viewModel: SettingsViewModel = hiltViewModel(),
|
||||
menuButtonClick: () -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
navControllerAction: (String) -> Unit,
|
||||
) {
|
||||
val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle()
|
||||
|
||||
SettingsScreen(
|
||||
userPrefs = userPrefs.value,
|
||||
menuButtonClick = menuButtonClick,
|
||||
navigateUp = navigateUp,
|
||||
navControllerAction = navControllerAction,
|
||||
updateMiddleZero = viewModel::updateMiddleZero,
|
||||
updateVibrations = viewModel::updateVibrations,
|
||||
updateStartingScreen = viewModel::updateStartingScreen
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsScreen(
|
||||
userPrefs: GeneralPreferences,
|
||||
menuButtonClick: () -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
navControllerAction: (String) -> Unit,
|
||||
updateMiddleZero: (Boolean) -> Unit,
|
||||
updateVibrations: (Boolean) -> Unit,
|
||||
updateStartingScreen: (String) -> Unit
|
||||
) {
|
||||
val mContext = LocalContext.current
|
||||
var dialogState: DialogState by rememberSaveable {
|
||||
mutableStateOf(DialogState.NONE)
|
||||
}
|
||||
var dialogState: DialogState by rememberSaveable { mutableStateOf(DialogState.NONE) }
|
||||
|
||||
UnittoScreenWithLargeTopBar(
|
||||
title = stringResource(R.string.settings_screen),
|
||||
navigationIcon = { NavigateUpButton(menuButtonClick) }
|
||||
navigationIcon = { NavigateUpButton(navigateUp) }
|
||||
) { padding ->
|
||||
LazyColumn(contentPadding = padding) {
|
||||
|
||||
@ -116,7 +112,7 @@ private fun SettingsScreen(
|
||||
iconDescription = stringResource(R.string.starting_screen_setting),
|
||||
headlineText = stringResource(R.string.starting_screen_setting),
|
||||
supportingText = stringResource(R.string.starting_screen_setting_support),
|
||||
modifier = Modifier.clickable { dialogState = DialogState.START_SCREEN }
|
||||
modifier = Modifier.clickable { navControllerAction(startingScreenRoute) }
|
||||
)
|
||||
}
|
||||
|
||||
@ -225,16 +221,6 @@ private fun SettingsScreen(
|
||||
|
||||
// Showing dialog
|
||||
when (dialogState) {
|
||||
DialogState.START_SCREEN -> {
|
||||
AlertDialogWithList(
|
||||
title = stringResource(R.string.starting_screen_setting),
|
||||
selectedItemIndex = userPrefs.startingScreen,
|
||||
listItems = TOP_LEVEL_GRAPH_ROUTES,
|
||||
selectAction = updateStartingScreen,
|
||||
dismissAction = { resetDialog() }
|
||||
)
|
||||
}
|
||||
|
||||
DialogState.LANGUAGE -> {
|
||||
AlertDialogWithList(
|
||||
title = stringResource(R.string.language_setting),
|
||||
@ -266,7 +252,7 @@ private fun SettingsScreen(
|
||||
* All possible states for alert dialog that opens when user clicks on settings.
|
||||
*/
|
||||
private enum class DialogState {
|
||||
NONE, START_SCREEN, LANGUAGE
|
||||
NONE, LANGUAGE
|
||||
}
|
||||
|
||||
@Preview
|
||||
@ -274,10 +260,9 @@ private enum class DialogState {
|
||||
private fun PreviewSettingsScreen() {
|
||||
SettingsScreen(
|
||||
userPrefs = GeneralPreferences(),
|
||||
menuButtonClick = { /*TODO*/ },
|
||||
navigateUp = {},
|
||||
navControllerAction = {},
|
||||
updateMiddleZero = {},
|
||||
updateVibrations = {},
|
||||
updateStartingScreen = {}
|
||||
)
|
||||
}
|
||||
|
@ -47,11 +47,4 @@ internal class SettingsViewModel @Inject constructor(
|
||||
fun updateMiddleZero(enabled: Boolean) = viewModelScope.launch {
|
||||
userPrefsRepository.updateMiddleZero(enabled)
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserPreferencesRepository.updateStartingScreen
|
||||
*/
|
||||
fun updateStartingScreen(startingScreen: String) = viewModelScope.launch {
|
||||
userPrefsRepository.updateStartingScreen(startingScreen)
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import com.sadellie.unitto.feature.settings.about.AboutScreen
|
||||
import com.sadellie.unitto.feature.settings.calculator.CalculatorSettingsScreen
|
||||
import com.sadellie.unitto.feature.settings.converter.ConverterSettingsScreen
|
||||
import com.sadellie.unitto.feature.settings.formatting.FormattingRoute
|
||||
import com.sadellie.unitto.feature.settings.startingscreen.StartingScreenRoute
|
||||
import com.sadellie.unitto.feature.settings.themes.ThemesRoute
|
||||
import com.sadellie.unitto.feature.settings.thirdparty.ThirdPartyLicensesScreen
|
||||
import com.sadellie.unitto.feature.settings.unitgroups.UnitGroupsScreen
|
||||
@ -38,6 +39,7 @@ import io.github.sadellie.themmo.ThemmoController
|
||||
private val graph = TopLevelDestinations.Settings.graph
|
||||
private val start = TopLevelDestinations.Settings.start
|
||||
internal const val themesRoute = "themes_route"
|
||||
internal const val startingScreenRoute = "starting_screen_route"
|
||||
internal const val unitsGroupRoute = "units_group_route"
|
||||
internal const val thirdPartyRoute = "third_party_route"
|
||||
internal const val aboutRoute = "about_route"
|
||||
@ -66,7 +68,7 @@ fun NavGraphBuilder.settingGraph(
|
||||
) {
|
||||
unittoComposable(start) {
|
||||
SettingsRoute(
|
||||
menuButtonClick = navController::navigateUp,
|
||||
navigateUp = navController::navigateUp,
|
||||
navControllerAction = navController::navigate
|
||||
)
|
||||
}
|
||||
@ -78,6 +80,12 @@ fun NavGraphBuilder.settingGraph(
|
||||
)
|
||||
}
|
||||
|
||||
unittoComposable(startingScreenRoute) {
|
||||
StartingScreenRoute(
|
||||
navigateUp = navController::navigateUp,
|
||||
)
|
||||
}
|
||||
|
||||
unittoComposable(formattingRoute) {
|
||||
FormattingRoute(
|
||||
navigateUpAction = navController::navigateUp
|
||||
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.settings.startingscreen
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AppShortcut
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.sadellie.unitto.core.base.R
|
||||
import com.sadellie.unitto.core.base.Shortcut
|
||||
import com.sadellie.unitto.core.base.TOP_LEVEL_DESTINATIONS
|
||||
import com.sadellie.unitto.core.base.TopLevelDestinations
|
||||
import com.sadellie.unitto.core.ui.addShortcut
|
||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
|
||||
|
||||
@Composable
|
||||
internal fun StartingScreenRoute(
|
||||
viewModel: StartingScreenViewModel = hiltViewModel(),
|
||||
navigateUp: () -> Unit
|
||||
) {
|
||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
||||
|
||||
StartingScreenScreen(
|
||||
startingScreen = prefs.value.startingScreen,
|
||||
updateStartingScreen = viewModel::updateStartingScreen,
|
||||
navigateUp = navigateUp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StartingScreenScreen(
|
||||
startingScreen: String,
|
||||
updateStartingScreen: (String) -> Unit,
|
||||
navigateUp: () -> Unit
|
||||
) {
|
||||
val mContext = LocalContext.current
|
||||
|
||||
UnittoScreenWithLargeTopBar(
|
||||
title = stringResource(R.string.starting_screen_setting),
|
||||
navigationIcon = { NavigateUpButton(navigateUp) }
|
||||
) { padding ->
|
||||
LazyColumn(contentPadding = padding) {
|
||||
|
||||
TOP_LEVEL_DESTINATIONS.forEach { destination ->
|
||||
item {
|
||||
UnittoListItem(
|
||||
modifier = Modifier.clickable { updateStartingScreen(destination.graph) },
|
||||
headlineContent = {
|
||||
Text(stringResource(destination.name))
|
||||
},
|
||||
leadingContent = {
|
||||
RadioButton(
|
||||
selected = destination.graph == startingScreen,
|
||||
onClick = { updateStartingScreen(destination.graph) }
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
destination.shortcut?.let { shortcut: Shortcut ->
|
||||
mContext.addShortcut(
|
||||
destination.graph,
|
||||
shortcut.shortcutShortLabel,
|
||||
shortcut.shortcutLongLabel,
|
||||
shortcut.shortcutDrawable
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Default.AppShortcut, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun StartingScreenPreview() {
|
||||
StartingScreenScreen(
|
||||
startingScreen = TopLevelDestinations.Converter.graph,
|
||||
updateStartingScreen = {},
|
||||
navigateUp = {}
|
||||
)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.settings.startingscreen
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.sadellie.unitto.data.common.stateIn
|
||||
import com.sadellie.unitto.data.userprefs.StartingScreenPreferences
|
||||
import com.sadellie.unitto.data.userprefs.UserPreferencesRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class StartingScreenViewModel @Inject constructor(
|
||||
private val userPrefsRepository: UserPreferencesRepository,
|
||||
) : ViewModel() {
|
||||
val prefs = userPrefsRepository.startingScreenPrefs
|
||||
.stateIn(viewModelScope, StartingScreenPreferences())
|
||||
|
||||
fun updateStartingScreen(startingScreen: String) = viewModelScope.launch {
|
||||
userPrefsRepository.updateStartingScreen(startingScreen)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user