add cancel button to scanner

This commit is contained in:
Boof2015
2026-07-25 17:10:31 -04:00
parent 80c27b039f
commit 0bde96e321
13 changed files with 452 additions and 76 deletions
+46 -4
View File
@@ -1,6 +1,7 @@
import { View } from 'react-native';
import { Pressable, View } from 'react-native';
import { Text } from '@/components/Text';
import { spacing } from '@/theme';
import { useRipple } from '@/theme/ripple';
import { createThemedStyles, useColors } from '@/theme/themed';
import { useLibraryStore } from '@/stores/libraryStore';
@@ -8,8 +9,11 @@ import { useLibraryStore } from '@/stores/libraryStore';
export function ScanProgress() {
const styles = useStyles();
const colors = useColors();
const ripple = useRipple();
const isScanning = useLibraryStore((s) => s.isScanning);
const isCancelling = useLibraryStore((s) => s.isCancelling);
const progress = useLibraryStore((s) => s.scanProgress);
const cancelScan = useLibraryStore((s) => s.cancelScan);
if (!isScanning) return null;
@@ -29,9 +33,33 @@ export function ScanProgress() {
return (
<View style={styles.container}>
<Text variant="caption" color={colors.textSecondary} numberOfLines={1}>
{label}
</Text>
<View style={styles.labelRow}>
<Text
variant="caption"
color={colors.textSecondary}
numberOfLines={1}
style={styles.label}
>
{label}
</Text>
<Pressable
android_ripple={ripple.bounded}
disabled={isCancelling}
onPress={cancelScan}
accessibilityRole="button"
accessibilityLabel={isCancelling ? 'Cancelling library scan' : 'Cancel library scan'}
accessibilityState={{ disabled: isCancelling, busy: isCancelling }}
hitSlop={6}
style={styles.cancelButton}
>
<Text
variant="caption"
color={isCancelling ? colors.textTertiary : colors.warning}
>
{isCancelling ? 'Cancelling…' : 'Cancel'}
</Text>
</Pressable>
</View>
<View style={styles.track}>
<View
style={[
@@ -50,6 +78,20 @@ const useStyles = createThemedStyles((colors) => ({
gap: spacing.xs,
marginBottom: spacing.md,
},
labelRow: {
minHeight: 32,
flexDirection: 'row',
alignItems: 'center',
gap: spacing.sm,
},
label: {
flex: 1,
},
cancelButton: {
minHeight: 32,
justifyContent: 'center',
paddingHorizontal: spacing.xs,
},
track: {
height: 2,
backgroundColor: colors.glassBorder,
+29 -2
View File
@@ -368,8 +368,11 @@ function StepHeader({
function ScanBanner() {
const styles = useStyles();
const colors = useColors();
const ripple = useRipple();
const isScanning = useLibraryStore((s) => s.isScanning);
const isCancelling = useLibraryStore((s) => s.isCancelling);
const progress = useLibraryStore((s) => s.scanProgress);
const cancelScan = useLibraryStore((s) => s.cancelScan);
if (!isScanning) return null;
const detail =
(progress.phase === 'extracting' || progress.phase === 'analyzing') && progress.total > 0
@@ -388,8 +391,27 @@ function ScanBanner() {
numberOfLines={1}
style={styles.scanBannerText}
>
Scanning your library{detail ? ` · ${detail}` : '…'}
{isCancelling
? 'Cancelling library scan…'
: `Scanning your library${detail ? ` · ${detail}` : '…'}`}
</Text>
<Pressable
android_ripple={ripple.bounded}
disabled={isCancelling}
onPress={cancelScan}
accessibilityRole="button"
accessibilityLabel={isCancelling ? 'Cancelling library scan' : 'Cancel library scan'}
accessibilityState={{ disabled: isCancelling, busy: isCancelling }}
hitSlop={6}
style={styles.scanBannerCancel}
>
<Text
variant="caption"
color={isCancelling ? colors.textTertiary : colors.warning}
>
{isCancelling ? 'Cancelling…' : 'Cancel'}
</Text>
</Pressable>
</Animated.View>
);
}
@@ -431,7 +453,12 @@ const useStyles = createThemedStyles((colors) => ({
backgroundColor: colors.glassBg,
},
scanBannerText: {
maxWidth: 240,
flexShrink: 1,
},
scanBannerCancel: {
minHeight: 32,
justifyContent: 'center',
paddingHorizontal: spacing.xs,
},
scroll: {
flex: 1,