Skip to content

Commit 6ed6b82

Browse files
Add shortcut icon preference and update related functionality (#40)
1 parent 9969ac9 commit 6ed6b82

File tree

8 files changed

+122
-31
lines changed

8 files changed

+122
-31
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5+
<queries>
6+
<intent>
7+
<action android:name="android.intent.action.VIEW" />
8+
<data android:scheme="*" />
9+
</intent>
10+
</queries>
11+
512
<application
613
android:name=".DeeprApplication"
714
android:allowBackup="true"
@@ -15,7 +22,6 @@
1522
<activity
1623
android:name=".MainActivity"
1724
android:exported="true"
18-
android:label="@string/app_name"
1925
android:theme="@style/Theme.Deepr"
2026
android:windowSoftInputMode="adjustNothing">
2127
<intent-filter>

app/src/main/java/com/yogeshpaliyal/deepr/preference/AppPreferenceDataStore.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.yogeshpaliyal.deepr.preference
33
import android.content.Context
44
import androidx.datastore.core.DataStore
55
import androidx.datastore.preferences.core.Preferences
6+
import androidx.datastore.preferences.core.booleanPreferencesKey
67
import androidx.datastore.preferences.core.edit
78
import androidx.datastore.preferences.core.stringPreferencesKey
89
import androidx.datastore.preferences.preferencesDataStore
@@ -17,16 +18,28 @@ class AppPreferenceDataStore(
1718
) {
1819
companion object {
1920
private val SORTING_ORDER = stringPreferencesKey("sorting_order")
21+
private val USE_LINK_BASED_ICONS = booleanPreferencesKey("use_link_based_icons")
2022
}
2123

2224
val getSortingOrder: Flow<String> =
2325
context.appDataStore.data.map { preferences ->
2426
preferences[SORTING_ORDER] ?: SortOrder.DESC.name
2527
}
2628

29+
val getUseLinkBasedIcons: Flow<Boolean> =
30+
context.appDataStore.data.map { preferences ->
31+
preferences[USE_LINK_BASED_ICONS] ?: true // Default to link-based icons
32+
}
33+
2734
suspend fun setSortingOrder(order: String) {
2835
context.appDataStore.edit { prefs ->
2936
prefs[SORTING_ORDER] = order
3037
}
3138
}
39+
40+
suspend fun setUseLinkBasedIcons(useLink: Boolean) {
41+
context.appDataStore.edit { prefs ->
42+
prefs[USE_LINK_BASED_ICONS] = useLink
43+
}
44+
}
3245
}

app/src/main/java/com/yogeshpaliyal/deepr/ui/components/CreateShortcutDialog.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.compose.material3.Button
55
import androidx.compose.material3.Text
66
import androidx.compose.material3.TextField
77
import androidx.compose.runtime.Composable
8+
import androidx.compose.runtime.collectAsState
89
import androidx.compose.runtime.getValue
910
import androidx.compose.runtime.mutableStateOf
1011
import androidx.compose.runtime.remember
@@ -14,15 +15,20 @@ import com.yogeshpaliyal.deepr.Deepr
1415
import com.yogeshpaliyal.deepr.util.createShortcut
1516
import com.yogeshpaliyal.deepr.util.getShortcut
1617
import com.yogeshpaliyal.deepr.util.isShortcutSupported
18+
import com.yogeshpaliyal.deepr.viewmodel.AccountViewModel
19+
import org.koin.androidx.compose.koinViewModel
1720

1821
@Composable
1922
fun CreateShortcutDialog(
2023
deepr: Deepr,
2124
onDismiss: () -> Unit,
22-
onCreate: (Deepr, String) -> Unit,
25+
viewModel: AccountViewModel = koinViewModel(),
2326
) {
2427
val context = LocalContext.current
2528
val existingShortcut = getShortcut(context, deepr.id)
29+
// Collect the shortcut icon preference state
30+
val useLinkBasedIcons by viewModel.useLinkBasedIcons.collectAsState()
31+
2632
if (isShortcutSupported(context)) {
2733
var shortcutName by remember {
2834
mutableStateOf(
@@ -43,8 +49,8 @@ fun CreateShortcutDialog(
4349
confirmButton = {
4450
Button(
4551
onClick = {
46-
onCreate(deepr, shortcutName)
47-
createShortcut(context, deepr, shortcutName, existingShortcut != null)
52+
onDismiss()
53+
createShortcut(context, deepr, shortcutName, existingShortcut != null, useLinkBasedIcons)
4854
},
4955
enabled = shortcutName.isNotBlank(),
5056
) {

app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/Home.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,6 @@ fun Content(
363363
CreateShortcutDialog(
364364
deepr = deepr,
365365
onDismiss = { showShortcutDialog = null },
366-
onCreate = { d, name ->
367-
showShortcutDialog = null
368-
},
369366
)
370367
}
371368

app/src/main/java/com/yogeshpaliyal/deepr/ui/screens/Settings.kt

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ import androidx.compose.material3.IconButton
2424
import androidx.compose.material3.ListItem
2525
import androidx.compose.material3.MaterialTheme
2626
import androidx.compose.material3.Scaffold
27+
import androidx.compose.material3.Switch
2728
import androidx.compose.material3.Text
2829
import androidx.compose.material3.TopAppBar
2930
import androidx.compose.runtime.Composable
3031
import androidx.compose.runtime.LaunchedEffect
32+
import androidx.compose.runtime.collectAsState
33+
import androidx.compose.runtime.getValue
3134
import androidx.compose.runtime.snapshots.SnapshotStateList
3235
import androidx.compose.ui.Alignment
3336
import androidx.compose.ui.Modifier
@@ -43,6 +46,7 @@ import compose.icons.TablerIcons
4346
import compose.icons.tablericons.ArrowLeft
4447
import compose.icons.tablericons.Download
4548
import compose.icons.tablericons.InfoCircle
49+
import compose.icons.tablericons.Settings
4650
import compose.icons.tablericons.Upload
4751
import kotlinx.coroutines.flow.collectLatest
4852
import org.koin.androidx.compose.koinViewModel
@@ -67,6 +71,9 @@ fun SettingsScreen(
6771
}
6872
}
6973

74+
// Collect the shortcut icon preference state
75+
val useLinkBasedIcons by viewModel.useLinkBasedIcons.collectAsState()
76+
7077
LaunchedEffect(storagePermissionState.status) {
7178
if (storagePermissionState.status.isGranted) {
7279
viewModel.exportCsvData()
@@ -117,20 +124,8 @@ fun SettingsScreen(
117124
.fillMaxSize(),
118125
) {
119126
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
120-
ListItem(
121-
modifier =
122-
Modifier.clickable(true) {
123-
backStack.add(AboutUs)
124-
},
125-
headlineContent = { Text("About Us") },
126-
leadingContent = {
127-
Icon(
128-
TablerIcons.InfoCircle,
129-
contentDescription = "About Us",
130-
)
131-
},
132-
)
133127
HorizontalDivider()
128+
134129
ListItem(
135130
modifier =
136131
Modifier.clickable {
@@ -143,7 +138,7 @@ fun SettingsScreen(
143138
)
144139
},
145140
headlineContent = { Text("Import Deeplinks") },
146-
supportingContent = { Text("Live Now") },
141+
supportingContent = { Text("Import Deeplinks from CSV file") },
147142
leadingContent = {
148143
Icon(
149144
TablerIcons.Download,
@@ -165,21 +160,53 @@ fun SettingsScreen(
165160
}
166161
},
167162
headlineContent = { Text("Export Deeplinks") },
168-
supportingContent = { Text("Live Now") },
163+
supportingContent = { Text("Export Deeplinks to CSV file") },
169164
leadingContent = {
170165
Icon(
171166
TablerIcons.Upload,
172167
contentDescription = "Export Deeplinks",
173168
)
174169
},
175170
)
171+
172+
HorizontalDivider()
173+
174+
// Add Shortcut Icon Setting
175+
ListItem(
176+
modifier =
177+
Modifier.clickable {
178+
// Toggle the preference
179+
viewModel.setUseLinkBasedIcons(!useLinkBasedIcons)
180+
},
181+
headlineContent = { Text("Shortcut Icon") },
182+
supportingContent = {
183+
Text(if (useLinkBasedIcons) "Use link supporting app icon" else "Use Deepr app icon")
184+
},
185+
leadingContent = {
186+
Icon(
187+
TablerIcons.Settings,
188+
contentDescription = "Shortcut Icon Setting",
189+
)
190+
},
191+
trailingContent = {
192+
Switch(
193+
checked = useLinkBasedIcons,
194+
onCheckedChange = { viewModel.setUseLinkBasedIcons(it) },
195+
)
196+
},
197+
)
198+
HorizontalDivider()
199+
176200
ListItem(
177-
headlineContent = { Text("Transfer Deeplinks") },
178-
supportingContent = { Text("Coming Soon") },
201+
modifier =
202+
Modifier.clickable(true) {
203+
backStack.add(AboutUs)
204+
},
205+
headlineContent = { Text("About Us") },
179206
leadingContent = {
180207
Icon(
181-
TablerIcons.Upload,
182-
contentDescription = "Transfer Deeplinks",
208+
TablerIcons.InfoCircle,
209+
contentDescription = "About Us",
183210
)
184211
},
185212
)

app/src/main/java/com/yogeshpaliyal/deepr/util/ShortcutUtils.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,25 @@ import android.content.pm.ShortcutInfo
66
import android.os.Build
77
import androidx.core.content.pm.ShortcutInfoCompat
88
import androidx.core.content.pm.ShortcutManagerCompat
9-
import androidx.core.graphics.drawable.IconCompat
109
import androidx.core.net.toUri
1110
import com.yogeshpaliyal.deepr.Deepr
12-
import com.yogeshpaliyal.deepr.R
1311

1412
fun createShortcut(
1513
context: Context,
1614
deepr: Deepr,
1715
shortcutName: String,
1816
alreadyExists: Boolean,
17+
useLinkBasedIcon: Boolean,
1918
) {
2019
if (isShortcutSupported(context)) {
2120
val shortcutInfo =
2221
ShortcutInfoCompat
2322
.Builder(context, "deepr_${deepr.id}")
2423
.setShortLabel(shortcutName)
2524
.setLongLabel(shortcutName)
26-
.setIcon(IconCompat.createWithResource(context, R.mipmap.ic_launcher))
25+
.setIcon(getShortcutAppIcon(context, deepr.link, useLinkBasedIcon))
2726
.setIntent(
28-
Intent(Intent.ACTION_VIEW, deepr.link.toUri()).apply {
29-
},
27+
Intent(Intent.ACTION_VIEW, deepr.link.toUri()),
3028
).build()
3129
if (alreadyExists) {
3230
// If the shortcut already exists, we update it

app/src/main/java/com/yogeshpaliyal/deepr/util/Utils.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ package com.yogeshpaliyal.deepr.util
22

33
import android.content.Context
44
import android.content.Intent
5+
import android.content.pm.PackageManager
6+
import android.graphics.Canvas
57
import android.widget.Toast
8+
import androidx.core.graphics.createBitmap
9+
import androidx.core.graphics.drawable.IconCompat
610
import androidx.core.net.toUri
11+
import com.yogeshpaliyal.deepr.R
712

813
fun openDeeplink(
914
context: Context,
@@ -22,6 +27,34 @@ fun openDeeplink(
2227
}
2328
}
2429

30+
fun getShortcutAppIcon(
31+
context: Context,
32+
link: String,
33+
useLinkBasedIcon: Boolean,
34+
): IconCompat {
35+
if (!useLinkBasedIcon) {
36+
// If link-based icons are not used, return the default app icon
37+
return IconCompat.createWithResource(context, R.mipmap.ic_launcher)
38+
}
39+
try {
40+
val intent = Intent(Intent.ACTION_VIEW, link.toUri())
41+
val appIconDrawable = context.packageManager.getActivityIcon(intent)
42+
43+
// Convert the Drawable to a Bitmap
44+
val bitmap =
45+
createBitmap(appIconDrawable.intrinsicWidth, appIconDrawable.intrinsicHeight)
46+
val canvas = Canvas(bitmap)
47+
appIconDrawable.setBounds(0, 0, canvas.width, canvas.height)
48+
appIconDrawable.draw(canvas)
49+
// Create and return the IconCompat object
50+
return IconCompat.createWithBitmap(bitmap)
51+
} catch (e: PackageManager.NameNotFoundException) {
52+
e.printStackTrace()
53+
// If the icon cannot be found, return a default icon
54+
return IconCompat.createWithResource(context, R.mipmap.ic_launcher)
55+
}
56+
}
57+
2558
fun isValidDeeplink(link: String): Boolean {
2659
if (link.isBlank()) return false
2760
return try {

app/src/main/java/com/yogeshpaliyal/deepr/viewmodel/AccountViewModel.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,15 @@ class AccountViewModel(
147147
}
148148
}
149149
}
150+
151+
// Shortcut icon preference methods
152+
val useLinkBasedIcons =
153+
preferenceDataStore.getUseLinkBasedIcons
154+
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), true)
155+
156+
fun setUseLinkBasedIcons(useLink: Boolean) {
157+
viewModelScope.launch {
158+
preferenceDataStore.setUseLinkBasedIcons(useLink)
159+
}
160+
}
150161
}

0 commit comments

Comments
 (0)