Skip to content

Commit dcdb1cf

Browse files
committed
feat(ui): Add tooltips, 'To Edit' shortcut, and Summary Sheet layout enhancement
This commit introduces several UI enhancements and bug fixes across the app. Bumps app version to 0.9.3. - Added Material 3 long-press tooltips to icon-only buttons in `SwiperScreen`, `DuplicatesScreen`, and `SessionSetupScreen` to improve usability and discoverability. - Implemented a "Move to 'To Edit'" option in the Swiper's media context menu. This adds a pending change to move the current item to a "To Edit" subfolder within its current directory. - Enhanced the `SummarySheet` expansion behavior. The sheet now properly wraps its content for small lists and expands to a reasonable maximum height for long lists. - Increased the maximum height of the `FastScrollbar` thumb for better aesthetic. VERSION: 0.9.2 -> 0.9.3
1 parent c358106 commit dcdb1cf

File tree

7 files changed

+332
-100
lines changed

7 files changed

+332
-100
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ android {
3939
minSdk = 29
4040
targetSdk = 36
4141
versionCode = 1
42-
versionName = "0.9.2"
42+
versionName = "0.9.3"
4343

4444
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
4545
vectorDrawables {

app/src/main/java/com/cleansweep/ui/components/FastScrollbar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import androidx.compose.ui.platform.LocalDensity
2525
import androidx.compose.ui.unit.dp
2626

2727
private const val SCROLLBAR_MIN_THUMB_HEIGHT = 0.1f
28-
private const val SCROLLBAR_MAX_THUMB_HEIGHT = 0.4f
28+
private const val SCROLLBAR_MAX_THUMB_HEIGHT = 0.6f
2929
private const val SCROLLBAR_INACTIVE_ALPHA = 0f
3030
private const val SCROLLBAR_ACTIVE_ALPHA = 0.8f
3131

app/src/main/java/com/cleansweep/ui/screens/duplicates/DuplicatesScreen.kt

Lines changed: 107 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -149,27 +149,51 @@ fun DuplicatesScreen(
149149
TopAppBar(
150150
title = { Text(title) },
151151
navigationIcon = {
152-
IconButton(onClick = onNavigateUp) {
153-
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Navigate back")
152+
TooltipBox(
153+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
154+
tooltip = { PlainTooltip { Text("Navigate back") } },
155+
state = rememberTooltipState()
156+
) {
157+
IconButton(onClick = onNavigateUp) {
158+
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Navigate back")
159+
}
154160
}
155161
},
156162
actions = {
157163
if (uiState.scanState == ScanState.Complete) {
158-
IconButton(onClick = viewModel::resetToIdle) {
159-
Icon(Icons.Outlined.Cached, contentDescription = "New Scan")
164+
TooltipBox(
165+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
166+
tooltip = { PlainTooltip { Text("New Scan") } },
167+
state = rememberTooltipState()
168+
) {
169+
IconButton(onClick = viewModel::resetToIdle) {
170+
Icon(Icons.Outlined.Cached, contentDescription = "New Scan")
171+
}
160172
}
161173
}
162174
if (uiState.resultViewMode == ResultViewMode.GRID && uiState.scanState == ScanState.Complete) {
163-
IconButton(onClick = viewModel::cycleGridViewZoom) {
164-
Icon(Icons.Outlined.ZoomIn, contentDescription = "Change grid columns")
175+
TooltipBox(
176+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
177+
tooltip = { PlainTooltip { Text("Change grid columns") } },
178+
state = rememberTooltipState()
179+
) {
180+
IconButton(onClick = viewModel::cycleGridViewZoom) {
181+
Icon(Icons.Outlined.ZoomIn, contentDescription = "Change grid columns")
182+
}
165183
}
166184
}
167185
if (uiState.scanState == ScanState.Complete && uiState.resultGroups.isNotEmpty()) {
168-
IconButton(onClick = viewModel::toggleResultViewMode) {
169-
Icon(
170-
imageVector = if (uiState.resultViewMode == ResultViewMode.LIST) Icons.Outlined.ViewModule else Icons.AutoMirrored.Outlined.ViewList,
171-
contentDescription = "Toggle View Mode"
172-
)
186+
TooltipBox(
187+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
188+
tooltip = { PlainTooltip { Text("Toggle View Mode") } },
189+
state = rememberTooltipState()
190+
) {
191+
IconButton(onClick = viewModel::toggleResultViewMode) {
192+
Icon(
193+
imageVector = if (uiState.resultViewMode == ResultViewMode.LIST) Icons.Outlined.ViewModule else Icons.AutoMirrored.Outlined.ViewList,
194+
contentDescription = "Toggle View Mode"
195+
)
196+
}
173197
}
174198
}
175199
}
@@ -271,19 +295,37 @@ fun GroupDetailsScreen(
271295
TopAppBar(
272296
title = { Text(if (group != null) "View Group (${group.items.size} items)" else "View Group") },
273297
navigationIcon = {
274-
IconButton(onClick = onNavigateUp) {
275-
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
298+
TooltipBox(
299+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
300+
tooltip = { PlainTooltip { Text("Back") } },
301+
state = rememberTooltipState()
302+
) {
303+
IconButton(onClick = onNavigateUp) {
304+
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
305+
}
276306
}
277307
},
278308
actions = {
279309
if (group != null) {
280-
IconButton(onClick = viewModel::cycleDetailViewZoom) {
281-
Icon(Icons.Outlined.ZoomIn, contentDescription = "Change layout columns")
310+
TooltipBox(
311+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
312+
tooltip = { PlainTooltip { Text("Change layout columns") } },
313+
state = rememberTooltipState()
314+
) {
315+
IconButton(onClick = viewModel::cycleDetailViewZoom) {
316+
Icon(Icons.Outlined.ZoomIn, contentDescription = "Change layout columns")
317+
}
282318
}
283319
var showMenu by remember { mutableStateOf(false) }
284320
Box {
285-
IconButton(onClick = { showMenu = true }) {
286-
Icon(Icons.Default.MoreVert, contentDescription = "More options")
321+
TooltipBox(
322+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
323+
tooltip = { PlainTooltip { Text("More options") } },
324+
state = rememberTooltipState()
325+
) {
326+
IconButton(onClick = { showMenu = true }) {
327+
Icon(Icons.Default.MoreVert, contentDescription = "More options")
328+
}
287329
}
288330
DropdownMenu(
289331
expanded = showMenu,
@@ -629,6 +671,7 @@ private fun ResultsView(
629671
}
630672
}
631673

674+
@OptIn(ExperimentalMaterial3Api::class)
632675
@Composable
633676
private fun StaleResultsWarningCard(
634677
timestamp: Long,
@@ -676,15 +719,21 @@ private fun StaleResultsWarningCard(
676719
)
677720
}
678721
}
679-
IconButton(
680-
onClick = onDismiss,
681-
modifier = Modifier.align(Alignment.TopEnd)
722+
TooltipBox(
723+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
724+
tooltip = { PlainTooltip { Text("Dismiss warning") } },
725+
state = rememberTooltipState()
682726
) {
683-
Icon(
684-
imageVector = Icons.Default.Close,
685-
contentDescription = "Dismiss warning",
686-
tint = MaterialTheme.colorScheme.onTertiaryContainer
687-
)
727+
IconButton(
728+
onClick = onDismiss,
729+
modifier = Modifier.align(Alignment.TopEnd)
730+
) {
731+
Icon(
732+
imageVector = Icons.Default.Close,
733+
contentDescription = "Dismiss warning",
734+
tint = MaterialTheme.colorScheme.onTertiaryContainer
735+
)
736+
}
688737
}
689738
}
690739
TextButton(
@@ -700,6 +749,7 @@ private fun StaleResultsWarningCard(
700749
}
701750

702751

752+
@OptIn(ExperimentalMaterial3Api::class)
703753
@Composable
704754
private fun UnscannableFilesSummaryCard(
705755
count: Int,
@@ -739,15 +789,21 @@ private fun UnscannableFilesSummaryCard(
739789
)
740790
}
741791
}
742-
IconButton(
743-
onClick = onDismiss,
744-
modifier = Modifier.align(Alignment.TopEnd)
792+
TooltipBox(
793+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
794+
tooltip = { PlainTooltip { Text("Dismiss warning") } },
795+
state = rememberTooltipState()
745796
) {
746-
Icon(
747-
imageVector = Icons.Default.Close,
748-
contentDescription = "Dismiss warning",
749-
tint = MaterialTheme.colorScheme.onTertiaryContainer
750-
)
797+
IconButton(
798+
onClick = onDismiss,
799+
modifier = Modifier.align(Alignment.TopEnd)
800+
) {
801+
Icon(
802+
imageVector = Icons.Default.Close,
803+
contentDescription = "Dismiss warning",
804+
tint = MaterialTheme.colorScheme.onTertiaryContainer
805+
)
806+
}
751807
}
752808
}
753809
}
@@ -1148,6 +1204,7 @@ private fun GridGroupCard(
11481204
}
11491205
}
11501206

1207+
@OptIn(ExperimentalMaterial3Api::class)
11511208
@Composable
11521209
private fun DuplicateGroupCard(
11531210
group: DuplicateGroup,
@@ -1181,8 +1238,14 @@ private fun DuplicateGroupCard(
11811238
)
11821239
}
11831240
Box(modifier = Modifier.align(Alignment.TopEnd)) {
1184-
IconButton(onClick = { showMenu = true }) {
1185-
Icon(Icons.Default.MoreVert, contentDescription = "More options")
1241+
TooltipBox(
1242+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
1243+
tooltip = { PlainTooltip { Text("More options") } },
1244+
state = rememberTooltipState()
1245+
) {
1246+
IconButton(onClick = { showMenu = true }) {
1247+
Icon(Icons.Default.MoreVert, contentDescription = "More options")
1248+
}
11861249
}
11871250
DropdownMenu(
11881251
expanded = showMenu,
@@ -1237,6 +1300,7 @@ private fun DuplicateGroupCard(
12371300
}
12381301
}
12391302

1303+
@OptIn(ExperimentalMaterial3Api::class)
12401304
@Composable
12411305
private fun SimilarMediaGroupCard(
12421306
group: SimilarGroup,
@@ -1271,8 +1335,14 @@ private fun SimilarMediaGroupCard(
12711335
)
12721336
}
12731337
Box(modifier = Modifier.align(Alignment.TopEnd)) {
1274-
IconButton(onClick = { showMenu = true }) {
1275-
Icon(Icons.Default.MoreVert, contentDescription = "More options")
1338+
TooltipBox(
1339+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
1340+
tooltip = { PlainTooltip { Text("More options") } },
1341+
state = rememberTooltipState()
1342+
) {
1343+
IconButton(onClick = { showMenu = true }) {
1344+
Icon(Icons.Default.MoreVert, contentDescription = "More options")
1345+
}
12761346
}
12771347
DropdownMenu(
12781348
expanded = showMenu,

app/src/main/java/com/cleansweep/ui/screens/session/SessionSetupScreen.kt

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -435,13 +435,25 @@ private fun DefaultTopAppBar(
435435
actions = {
436436
var showSortMenu by remember { mutableStateOf(false) }
437437

438-
IconButton(onClick = onNavigateToDuplicates) {
439-
Icon(Icons.Default.ControlPointDuplicate, contentDescription = "Find Duplicates")
438+
TooltipBox(
439+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
440+
tooltip = { PlainTooltip { Text("Find Duplicates") } },
441+
state = rememberTooltipState()
442+
) {
443+
IconButton(onClick = onNavigateToDuplicates) {
444+
Icon(Icons.Default.ControlPointDuplicate, contentDescription = "Find Duplicates")
445+
}
440446
}
441447

442448
Box {
443-
IconButton(onClick = { showSortMenu = true }) {
444-
Icon(Icons.AutoMirrored.Filled.Sort, contentDescription = "Sort")
449+
TooltipBox(
450+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
451+
tooltip = { PlainTooltip { Text("Sort") } },
452+
state = rememberTooltipState()
453+
) {
454+
IconButton(onClick = { showSortMenu = true }) {
455+
Icon(Icons.AutoMirrored.Filled.Sort, contentDescription = "Sort")
456+
}
445457
}
446458
DropdownMenu(expanded = showSortMenu, onDismissRequest = { showSortMenu = false }) {
447459
DropdownMenuItem(
@@ -500,8 +512,14 @@ private fun DefaultTopAppBar(
500512
})
501513
}
502514
}
503-
IconButton(onClick = onNavigateToSettings) {
504-
Icon(Icons.Filled.Settings, contentDescription = "Settings")
515+
TooltipBox(
516+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
517+
tooltip = { PlainTooltip { Text("Settings") } },
518+
state = rememberTooltipState()
519+
) {
520+
IconButton(onClick = onNavigateToSettings) {
521+
Icon(Icons.Filled.Settings, contentDescription = "Settings")
522+
}
505523
}
506524
}
507525
)
@@ -520,21 +538,45 @@ private fun ContextualTopAppBar(
520538
TopAppBar(
521539
title = { Text("$selectionCount Selected") },
522540
navigationIcon = {
523-
IconButton(onClick = onClose) {
524-
Icon(Icons.Default.Close, contentDescription = "Close selection mode")
541+
TooltipBox(
542+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
543+
tooltip = { PlainTooltip { Text("Close selection mode") } },
544+
state = rememberTooltipState()
545+
) {
546+
IconButton(onClick = onClose) {
547+
Icon(Icons.Default.Close, contentDescription = "Close selection mode")
548+
}
525549
}
526550
},
527551
actions = {
528552
if (canFavorite) {
529-
IconButton(onClick = onToggleFavorite) {
530-
Icon(Icons.Default.Star, contentDescription = "Add to Favorites")
553+
TooltipBox(
554+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
555+
tooltip = { PlainTooltip { Text("Add to Favorites") } },
556+
state = rememberTooltipState()
557+
) {
558+
IconButton(onClick = onToggleFavorite) {
559+
Icon(Icons.Default.Star, contentDescription = "Add to Favorites")
560+
}
531561
}
532562
}
533-
IconButton(onClick = onMarkAsSorted) {
534-
Icon(Icons.Default.CheckCircleOutline, contentDescription = "Mark as Sorted")
563+
TooltipBox(
564+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
565+
tooltip = { PlainTooltip { Text("Mark as Sorted") } },
566+
state = rememberTooltipState()
567+
) {
568+
IconButton(onClick = onMarkAsSorted) {
569+
Icon(Icons.Default.CheckCircleOutline, contentDescription = "Mark as Sorted")
570+
}
535571
}
536-
IconButton(onClick = onSelectAll) {
537-
Icon(Icons.Default.SelectAll, contentDescription = "Select All")
572+
TooltipBox(
573+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
574+
tooltip = { PlainTooltip { Text("Select All") } },
575+
state = rememberTooltipState()
576+
) {
577+
IconButton(onClick = onSelectAll) {
578+
Icon(Icons.Default.SelectAll, contentDescription = "Select All")
579+
}
538580
}
539581
},
540582
colors = TopAppBarDefaults.topAppBarColors(
@@ -546,7 +588,7 @@ private fun ContextualTopAppBar(
546588
)
547589
}
548590

549-
@OptIn(ExperimentalFoundationApi::class)
591+
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
550592
@Composable
551593
private fun EnhancedFolderItem(
552594
folderInfo: FolderInfo,
@@ -640,8 +682,14 @@ private fun EnhancedFolderItem(
640682

641683
if (!isContextualMode) {
642684
Box {
643-
IconButton(onClick = { showContextMenu = true }) {
644-
Icon(Icons.Default.MoreVert, "More Options")
685+
TooltipBox(
686+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
687+
tooltip = { PlainTooltip { Text("More Options") } },
688+
state = rememberTooltipState()
689+
) {
690+
IconButton(onClick = { showContextMenu = true }) {
691+
Icon(Icons.Default.MoreVert, "More Options")
692+
}
645693
}
646694
AppDropdownMenu(
647695
expanded = showContextMenu,

0 commit comments

Comments
 (0)