From a0c0997c50411157be310684e83869ad4b102677 Mon Sep 17 00:00:00 2001 From: sadellie Date: Thu, 3 Aug 2023 13:13:50 +0300 Subject: [PATCH] Dynamic random shortcuts --- .../sadellie/unitto/PushDynamicShortcut.kt | 59 +++++++++++++++++++ .../java/com/sadellie/unitto/UnittoApp.kt | 22 ++++++- .../unitto/core/base/TopLevelDestinations.kt | 36 +++++++++-- .../main/res/drawable/calculator_shortcut.xml | 31 ++++++++++ .../res/drawable/date_calculator_shortcut.xml | 31 ++++++++++ .../main/res/drawable/time_zone_shortcut.xml | 31 ++++++++++ .../res/drawable/unit_converter_shortcut.xml | 31 ++++++++++ .../unitto/core/ui/common/UnittoDrawerItem.kt | 4 +- .../core/ui/common/UnittoDrawerSheet.kt | 3 +- .../navigation/ConverterNavigation.kt | 8 ++- .../timezone/navigation/TimeZoneNavigation.kt | 8 ++- 11 files changed, 252 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/sadellie/unitto/PushDynamicShortcut.kt create mode 100644 core/base/src/main/res/drawable/calculator_shortcut.xml create mode 100644 core/base/src/main/res/drawable/date_calculator_shortcut.xml create mode 100644 core/base/src/main/res/drawable/time_zone_shortcut.xml create mode 100644 core/base/src/main/res/drawable/unit_converter_shortcut.xml diff --git a/app/src/main/java/com/sadellie/unitto/PushDynamicShortcut.kt b/app/src/main/java/com/sadellie/unitto/PushDynamicShortcut.kt new file mode 100644 index 00000000..ed344190 --- /dev/null +++ b/app/src/main/java/com/sadellie/unitto/PushDynamicShortcut.kt @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +package com.sadellie.unitto + +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +// I think it makes sense to run in coroutine +suspend fun Context.pushDynamicShortcut( + route: String, + @StringRes shortLabel: Int, + @StringRes longLabel: Int, + @DrawableRes drawable: Int, +) = withContext(Dispatchers.IO) { + // Low chance that we WILL push the shortcut + if ((0..10).random() != 0) return@withContext + + val context = this@pushDynamicShortcut + + val shortcut = ShortcutInfoCompat.Builder(context, route) + .setShortLabel(getString(shortLabel)) + .setLongLabel(getString(longLabel)) + .setIcon(IconCompat.createWithResource(context, drawable)) + .setIntent( + Intent( + Intent.ACTION_VIEW, + Uri.parse("app://com.sadellie.unitto/$route"), + context, + this.javaClass + ) + ) + .build() + + ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) +} diff --git a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt index 195f4520..ce65f29c 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoApp.kt +++ b/app/src/main/java/com/sadellie/unitto/UnittoApp.kt @@ -32,10 +32,12 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.platform.LocalContext import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.sadellie.unitto.core.base.Shortcut import com.sadellie.unitto.core.base.TOP_LEVEL_START_ROUTES import com.sadellie.unitto.core.ui.common.UnittoDrawerSheet import com.sadellie.unitto.core.ui.common.UnittoModalNavigationDrawer @@ -56,6 +58,7 @@ import kotlinx.coroutines.launch @Composable internal fun UnittoApp(uiPrefs: UIPreferences) { + val mContext = LocalContext.current val themmoController = rememberThemmoController( lightColorScheme = LightThemeColors, darkColorScheme = DarkThemeColors, @@ -71,6 +74,9 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { // Navigation drawer stuff val drawerState = rememberUnittoDrawerState() val drawerScope = rememberCoroutineScope() + + val shortcutsScope = rememberCoroutineScope() + val mainTabs by remember(uiPrefs.enableToolsExperiment) { derivedStateOf { if (uiPrefs.enableToolsExperiment) { @@ -110,15 +116,27 @@ internal fun UnittoApp(uiPrefs: UIPreferences) { mainTabs = mainTabs, additionalTabs = additionalTabs, currentDestination = navBackStackEntry?.destination?.route - ) { + ) { destination -> drawerScope.launch { drawerState.close() } - navController.navigate(it) { + + navController.navigate(destination.graph) { popUpTo(navController.graph.findStartDestination().id) { saveState = true } launchSingleTop = true restoreState = true } + + shortcutsScope.launch { + destination.shortcut?.let { shortcut: Shortcut -> + mContext.pushDynamicShortcut( + destination.graph, + shortcut.shortcutShortLabel, + shortcut.shortcutLongLabel, + shortcut.shortcutDrawable + ) + } + } } }, modifier = Modifier, diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt b/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt index 6f90618d..dfaaeb4f 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt +++ b/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt @@ -18,6 +18,7 @@ package com.sadellie.unitto.core.base +import androidx.annotation.DrawableRes import androidx.annotation.StringRes // Don't touch, users have "..._route" in their settings @@ -36,33 +37,60 @@ private const val TIME_ZONE_START = "time_zone_start" private const val SETTINGS_GRAPH = "settings_route" private const val SETTINGS_START = "settings_start" +data class Shortcut( + @StringRes val shortcutShortLabel: Int, + @StringRes val shortcutLongLabel: Int, + @DrawableRes val shortcutDrawable: Int, +) + sealed class TopLevelDestinations( val graph: String, val start: String = graph, @StringRes val name: Int, + val shortcut: Shortcut? = null ) { data object Converter : TopLevelDestinations( graph = CONVERTER_GRAPH, start = CONVERTER_START, - name = R.string.unit_converter + name = R.string.unit_converter, + shortcut = Shortcut( + R.string.unit_converter, + R.string.unit_converter, + R.drawable.unit_converter_shortcut + ) ) data object Calculator : TopLevelDestinations( graph = CALCULATOR_GRAPH, start = CALCULATOR_START, - name = R.string.calculator + name = R.string.calculator, + shortcut = Shortcut( + R.string.calculator, + R.string.calculator, + R.drawable.calculator_shortcut + ) ) data object DateCalculator : TopLevelDestinations( graph = DATE_CALCULATOR_GRAPH, start = DATE_CALCULATOR_START, - name = R.string.date_calculator + name = R.string.date_calculator, + shortcut = Shortcut( + R.string.date_calculator, + R.string.date_calculator, + R.drawable.date_calculator_shortcut + ) ) data object TimeZone : TopLevelDestinations( graph = TIME_ZONE_GRAPH, start = TIME_ZONE_START, - name = R.string.time_zone_screen + name = R.string.time_zone_screen, + shortcut = Shortcut( + R.string.time_zone_screen, + R.string.time_zone_screen, + R.drawable.time_zone_shortcut + ) ) data object Settings : TopLevelDestinations( diff --git a/core/base/src/main/res/drawable/calculator_shortcut.xml b/core/base/src/main/res/drawable/calculator_shortcut.xml new file mode 100644 index 00000000..e8c47bc0 --- /dev/null +++ b/core/base/src/main/res/drawable/calculator_shortcut.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/base/src/main/res/drawable/date_calculator_shortcut.xml b/core/base/src/main/res/drawable/date_calculator_shortcut.xml new file mode 100644 index 00000000..f95f05d8 --- /dev/null +++ b/core/base/src/main/res/drawable/date_calculator_shortcut.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/base/src/main/res/drawable/time_zone_shortcut.xml b/core/base/src/main/res/drawable/time_zone_shortcut.xml new file mode 100644 index 00000000..ac6d8c6a --- /dev/null +++ b/core/base/src/main/res/drawable/time_zone_shortcut.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/base/src/main/res/drawable/unit_converter_shortcut.xml b/core/base/src/main/res/drawable/unit_converter_shortcut.xml new file mode 100644 index 00000000..021b54a7 --- /dev/null +++ b/core/base/src/main/res/drawable/unit_converter_shortcut.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerItem.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerItem.kt index a83fad29..15375324 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerItem.kt +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerItem.kt @@ -33,13 +33,13 @@ internal fun UnittoDrawerItem( destination: TopLevelDestinations, icon: ImageVector, selected: Boolean, - onClick: (String) -> Unit + onClick: (TopLevelDestinations) -> Unit ) { NavigationDrawerItem( modifier = modifier, label = { Text(stringResource(destination.name)) }, icon = { Icon(icon, stringResource(destination.name)) }, selected = selected, - onClick = { onClick(destination.graph) } + onClick = { onClick(destination) } ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerSheet.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerSheet.kt index 54ceb934..5a134bb5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerSheet.kt +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/UnittoDrawerSheet.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.sadellie.unitto.core.base.R +import com.sadellie.unitto.core.base.TopLevelDestinations import com.sadellie.unitto.core.ui.model.DrawerItems @Composable @@ -40,7 +41,7 @@ fun UnittoDrawerSheet( mainTabs: List, additionalTabs: List, currentDestination: String?, - onItemClick: (String) -> Unit + onItemClick: (TopLevelDestinations) -> Unit ) { ModalDrawerSheet( modifier = modifier diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt index d9e22af0..c374a153 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt @@ -20,6 +20,7 @@ package com.sadellie.unitto.feature.converter.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import androidx.navigation.navDeepLink import androidx.navigation.navigation import com.sadellie.unitto.core.base.TopLevelDestinations import com.sadellie.unitto.feature.converter.ConverterRoute @@ -36,7 +37,12 @@ fun NavGraphBuilder.converterGraph( viewModel: ConverterViewModel ) { navigation(start, graph) { - composable(start) { + composable( + route = start, + deepLinks = listOf( + navDeepLink { uriPattern = "app://com.sadellie.unitto/$start" } + ) + ) { ConverterRoute( viewModel = viewModel, navigateToLeftScreen = navigateToLeftScreen, diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/timezone/navigation/TimeZoneNavigation.kt b/feature/timezone/src/main/java/com/sadellie/unitto/timezone/navigation/TimeZoneNavigation.kt index 98397a23..14105a31 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/timezone/navigation/TimeZoneNavigation.kt +++ b/feature/timezone/src/main/java/com/sadellie/unitto/timezone/navigation/TimeZoneNavigation.kt @@ -55,9 +55,13 @@ fun NavGraphBuilder.timeZoneGraph( navigation( startDestination = start, route = graph, - deepLinks = listOf(navDeepLink { uriPattern = "app://com.sadellie.unitto/$start" }) ) { - composable(start) { + composable( + route = start, + deepLinks = listOf( + navDeepLink { uriPattern = "app://com.sadellie.unitto/$start" } + ) + ) { TimeZoneRoute( navigateToMenu = navigateToMenu, navigateToSettings = navigateToSettings,