Skip to content

Commit 4addd8c

Browse files
Add configurable default profile for Save Silently feature (#354)
* Initial plan * Add silent save profile preference and UI Co-authored-by: yogeshpaliyal <[email protected]> * feat: fix lint formatting * feat: minor changes --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: yogeshpaliyal <[email protected]> Co-authored-by: Yogesh Choudhary Paliyal <[email protected]>
1 parent bf7ae6d commit 4addd8c

File tree

6 files changed

+141
-1
lines changed

6 files changed

+141
-1
lines changed

app/src/main/java/com/yogeshpaliyal/deepr/SilentSaveActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class SilentSaveActivity : ComponentActivity() {
7272
// Launch in application scope so it continues after activity finishes
7373
lifecycleScope.launch {
7474
try {
75-
val profileId = preferenceDataStore.getSelectedProfileId.first()
75+
val profileId = preferenceDataStore.getSilentSaveProfileId.first()
7676

7777
// Check if link already exists
7878
val existingLink =

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.datastore.preferences.preferencesDataStore
1212
import com.yogeshpaliyal.deepr.ui.screens.home.ViewType
1313
import com.yogeshpaliyal.deepr.viewmodel.SortType
1414
import kotlinx.coroutines.flow.Flow
15+
import kotlinx.coroutines.flow.firstOrNull
1516
import kotlinx.coroutines.flow.map
1617

1718
private val Context.appDataStore: DataStore<Preferences> by preferencesDataStore(name = "app_data_store")
@@ -37,6 +38,7 @@ class AppPreferenceDataStore(
3738
private val THEME_MODE = stringPreferencesKey("theme_mode")
3839
private val SHOW_OPEN_COUNTER = booleanPreferencesKey("show_open_counter")
3940
private val SELECTED_PROFILE_ID = longPreferencesKey("selected_profile_id")
41+
private val SILENT_SAVE_PROFILE_ID = longPreferencesKey("silent_save_profile_id")
4042
private val GOOGLE_DRIVE_AUTO_BACKUP_ENABLED =
4143
booleanPreferencesKey("google_drive_auto_backup_enabled")
4244
private val CLIPBOARD_LINK_DETECTION_ENABLED =
@@ -123,6 +125,11 @@ class AppPreferenceDataStore(
123125
preferences[SELECTED_PROFILE_ID] ?: 1L // Default to profile ID 1
124126
}
125127

128+
val getSilentSaveProfileId: Flow<Long> =
129+
context.appDataStore.data.map { preferences ->
130+
preferences[SILENT_SAVE_PROFILE_ID] ?: getSelectedProfileId.firstOrNull() ?: 1L // Default to profile ID 1
131+
}
132+
126133
val getGoogleDriveAutoBackupEnabled: Flow<Boolean> =
127134
context.appDataStore.data.map { preferences ->
128135
preferences[GOOGLE_DRIVE_AUTO_BACKUP_ENABLED] ?: false // Default to disabled
@@ -235,6 +242,12 @@ class AppPreferenceDataStore(
235242
}
236243
}
237244

245+
suspend fun setSilentSaveProfileId(profileId: Long) {
246+
context.appDataStore.edit { prefs ->
247+
prefs[SILENT_SAVE_PROFILE_ID] = profileId
248+
}
249+
}
250+
238251
suspend fun setGoogleDriveAutoBackupEnabled(enabled: Boolean) {
239252
context.appDataStore.edit { prefs ->
240253
prefs[GOOGLE_DRIVE_AUTO_BACKUP_ENABLED] = enabled
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.yogeshpaliyal.deepr.ui.components
2+
3+
import androidx.compose.foundation.clickable
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.fillMaxWidth
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.foundation.shape.RoundedCornerShape
8+
import androidx.compose.material3.AlertDialog
9+
import androidx.compose.material3.ListItem
10+
import androidx.compose.material3.ListItemDefaults
11+
import androidx.compose.material3.MaterialTheme
12+
import androidx.compose.material3.RadioButton
13+
import androidx.compose.material3.Text
14+
import androidx.compose.material3.TextButton
15+
import androidx.compose.runtime.Composable
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.draw.clip
18+
import androidx.compose.ui.graphics.Color
19+
import androidx.compose.ui.res.stringResource
20+
import androidx.compose.ui.unit.dp
21+
import com.yogeshpaliyal.deepr.Profile
22+
import com.yogeshpaliyal.deepr.R
23+
24+
@Composable
25+
fun ProfileSelectionDialog(
26+
profiles: List<Profile>,
27+
currentProfileId: Long,
28+
onProfileSelect: (Long) -> Unit,
29+
onDismiss: () -> Unit,
30+
modifier: Modifier = Modifier,
31+
title: String = stringResource(R.string.select_profile),
32+
) {
33+
AlertDialog(
34+
modifier = modifier,
35+
onDismissRequest = onDismiss,
36+
title = {
37+
Text(
38+
text = title,
39+
style = MaterialTheme.typography.headlineSmall,
40+
)
41+
},
42+
text = {
43+
Column {
44+
profiles.forEach { profile ->
45+
ListItem(
46+
modifier =
47+
Modifier
48+
.fillMaxWidth()
49+
.clip(RoundedCornerShape(8.dp))
50+
.clickable {
51+
onProfileSelect(profile.id)
52+
onDismiss()
53+
}.padding(vertical = 4.dp),
54+
headlineContent = {
55+
Text(
56+
text = profile.name,
57+
style = MaterialTheme.typography.bodyLarge,
58+
)
59+
},
60+
trailingContent = {
61+
RadioButton(
62+
selected = currentProfileId == profile.id,
63+
onClick = {
64+
onProfileSelect(profile.id)
65+
onDismiss()
66+
},
67+
)
68+
},
69+
colors =
70+
ListItemDefaults.colors(
71+
containerColor = Color.Transparent,
72+
),
73+
)
74+
}
75+
}
76+
},
77+
confirmButton = {
78+
TextButton(onClick = onDismiss) {
79+
Text(stringResource(R.string.cancel))
80+
}
81+
},
82+
)
83+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import com.yogeshpaliyal.deepr.R
4444
import com.yogeshpaliyal.deepr.ui.LocalNavigator
4545
import com.yogeshpaliyal.deepr.ui.TopLevelRoute
4646
import com.yogeshpaliyal.deepr.ui.components.LanguageSelectionDialog
47+
import com.yogeshpaliyal.deepr.ui.components.ProfileSelectionDialog
4748
import com.yogeshpaliyal.deepr.ui.components.ServerStatusBar
4849
import com.yogeshpaliyal.deepr.ui.components.SettingsItem
4950
import com.yogeshpaliyal.deepr.ui.components.SettingsSection
@@ -56,6 +57,7 @@ import compose.icons.tablericons.ArrowLeft
5657
import compose.icons.tablericons.Clipboard
5758
import compose.icons.tablericons.Download
5859
import compose.icons.tablericons.ExternalLink
60+
import compose.icons.tablericons.Folders
5961
import compose.icons.tablericons.InfoCircle
6062
import compose.icons.tablericons.Language
6163
import compose.icons.tablericons.Moon
@@ -106,6 +108,11 @@ fun SettingsScreen(
106108
val showOpenCounter by viewModel.showOpenCounter.collectAsStateWithLifecycle()
107109
val clipboardLinkDetectionEnabled by viewModel.clipboardLinkDetectionEnabled.collectAsStateWithLifecycle()
108110

111+
// Collect profiles and silent save profile preference
112+
val allProfiles by viewModel.allProfiles.collectAsStateWithLifecycle()
113+
val silentSaveProfileId by viewModel.silentSaveProfileId.collectAsStateWithLifecycle()
114+
var showSilentSaveProfileDialog by remember { mutableStateOf(false) }
115+
109116
Scaffold(
110117
contentWindowInsets = windowInsets,
111118
modifier = modifier.fillMaxSize(),
@@ -290,6 +297,17 @@ fun SettingsScreen(
290297
},
291298
)
292299

300+
SettingsItem(
301+
TablerIcons.Folders,
302+
title = stringResource(R.string.silent_save_profile),
303+
description =
304+
allProfiles.find { it.id == silentSaveProfileId }?.name
305+
?: stringResource(R.string.silent_save_profile_description),
306+
onClick = {
307+
showSilentSaveProfileDialog = true
308+
},
309+
)
310+
293311
SettingsItem(
294312
TablerIcons.Clipboard,
295313
title = stringResource(R.string.clipboard_link_detection),
@@ -430,5 +448,19 @@ fun SettingsScreen(
430448
onDismiss = { showThemeDialog = false },
431449
)
432450
}
451+
452+
// Silent Save Profile Selection Dialog
453+
if (showSilentSaveProfileDialog) {
454+
ProfileSelectionDialog(
455+
profiles = allProfiles,
456+
currentProfileId = silentSaveProfileId,
457+
onProfileSelect = { selectedProfileId ->
458+
viewModel.setSilentSaveProfile(selectedProfileId)
459+
showSilentSaveProfileDialog = false
460+
},
461+
onDismiss = { showSilentSaveProfileDialog = false },
462+
title = stringResource(R.string.silent_save_profile),
463+
)
464+
}
433465
}
434466
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,16 @@ class AccountViewModel(
809809
}
810810
}
811811

812+
fun setSilentSaveProfile(profileId: Long) {
813+
viewModelScope.launch(Dispatchers.IO) {
814+
preferenceDataStore.setSilentSaveProfileId(profileId)
815+
}
816+
}
817+
818+
val silentSaveProfileId =
819+
preferenceDataStore.getSilentSaveProfileId
820+
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), 1L)
821+
812822
fun insertProfile(name: String) {
813823
viewModelScope.launch(Dispatchers.IO) {
814824
linkRepository.insertProfile(name)

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@
275275
<string name="invalid_link_silent_save">Invalid link</string>
276276
<string name="failed_to_save_link">Failed to save link</string>
277277
<string name="link_already_exists">Link already exists</string>
278+
<string name="silent_save_profile">Silent Save Profile</string>
279+
<string name="silent_save_profile_description">Links saved via \'Save Silently\' will go to this profile</string>
278280

279281
<!-- Clipboard Link Detection Setting -->
280282
<string name="clipboard_link_detection">Clipboard link detection</string>

0 commit comments

Comments
 (0)