preview screen and rename file (#6)

* preview screen

* rename work
This commit is contained in:
2026-04-21 02:46:52 +05:30
committed by GitHub
parent 04c4bf7442
commit 520a9029db
4 changed files with 73 additions and 27 deletions

29
App.tsx
View File

@@ -1,5 +1,5 @@
import React, {useState, useCallback, useEffect} from 'react';
import {Alert, BackHandler} from 'react-native';
import {BackHandler} from 'react-native';
import HomeScreen from './src/screens/HomeScreen';
import ScanScreen from './src/screens/ScanScreen';
import ReviewScreen from './src/screens/ReviewScreen';
@@ -30,10 +30,12 @@ export default function App() {
const handleSaveDocument = useCallback(
(pages: ScannedPage[], _filter: FilterMode) => {
createDocument(pages);
goHome();
const doc = createDocument(pages);
setPendingPages([]);
setViewingDoc(doc);
setScreen('viewer');
},
[createDocument, goHome],
[createDocument],
);
const handleView = useCallback((doc: ScannedDocument) => {
@@ -51,23 +53,8 @@ export default function App() {
}, [screen, goHome]);
const handleRenameFromViewer = useCallback(
(_currentName: string) => {
if (!viewingDoc) return;
// Alert.prompt is iOS-only; on Android show a simple alert
if (Alert.prompt) {
Alert.prompt(
'Rename',
undefined,
text => {
if (text?.trim()) renameDocument(viewingDoc.id, text.trim());
},
'plain-text',
_currentName,
);
} else {
// Android fallback: navigate home and use HomeScreen rename modal
renameDocument(viewingDoc.id, _currentName);
}
(name: string) => {
if (viewingDoc) renameDocument(viewingDoc.id, name);
},
[viewingDoc, renameDocument],
);

View File

@@ -7,9 +7,10 @@ interface Props {
document: ScannedDocument;
onPress: () => void;
onDelete: () => void;
onRename: () => void;
}
export default function DocumentCard({document, onPress, onDelete}: Props) {
export default function DocumentCard({document, onPress, onDelete, onRename}: Props) {
const thumb = document.pages[0]?.uri;
return (
<TouchableOpacity testID={`document-card-${document.id}`} style={styles.card} onPress={onPress} activeOpacity={0.8}>
@@ -32,9 +33,14 @@ export default function DocumentCard({document, onPress, onDelete}: Props) {
{document.pages.length} {document.pages.length === 1 ? 'page' : 'pages'}
</Text>
</View>
<TouchableOpacity testID={`delete-card-${document.id}`} style={styles.deleteBtn} onPress={onDelete} hitSlop={{top: 8, bottom: 8, left: 8, right: 8}}>
<Text style={styles.deleteText}></Text>
</TouchableOpacity>
<View style={styles.actions}>
<TouchableOpacity testID={`rename-card-${document.id}`} onPress={onRename} hitSlop={{top: 8, bottom: 8, left: 8, right: 8}}>
<Text style={styles.renameText}></Text>
</TouchableOpacity>
<TouchableOpacity testID={`delete-card-${document.id}`} onPress={onDelete} hitSlop={{top: 8, bottom: 8, left: 8, right: 8}}>
<Text style={styles.deleteText}></Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
);
}
@@ -97,9 +103,14 @@ const styles = StyleSheet.create({
color: '#666',
fontSize: 12,
},
deleteBtn: {
actions: {
padding: 12,
justifyContent: 'center',
gap: 16,
},
renameText: {
color: '#007AFF',
fontSize: 18,
},
deleteText: {
color: '#ff453a',

View File

@@ -68,6 +68,7 @@ export default function HomeScreen({documents, onScan, onView, onDelete, onRenam
document={item}
onPress={() => onView(item)}
onDelete={() => confirmDelete(item)}
onRename={() => startRename(item)}
/>
)}
contentContainerStyle={styles.list}

View File

@@ -10,6 +10,8 @@ import {
StatusBar,
Alert,
ActivityIndicator,
Modal,
TextInput,
} from 'react-native';
import Share from 'react-native-share';
import {ScannedDocument} from '../types';
@@ -27,6 +29,8 @@ interface Props {
export default function ViewerScreen({document, onBack, onDelete, onRename}: Props) {
const [currentIndex, setCurrentIndex] = useState(0);
const [generating, setGenerating] = useState(false);
const [renaming, setRenaming] = useState(false);
const [renameText, setRenameText] = useState('');
const sharePdf = async (pageIndices?: number[]) => {
setGenerating(true);
@@ -129,7 +133,7 @@ export default function ViewerScreen({document, onBack, onDelete, onRename}: Pro
<Text style={styles.toolIcon}>📄</Text>
<Text style={styles.toolLabel}>Share All</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.toolBtn} onPress={() => onRename(document.name)}>
<TouchableOpacity style={styles.toolBtn} onPress={() => { setRenameText(document.name); setRenaming(true); }}>
<Text style={styles.toolIcon}></Text>
<Text style={styles.toolLabel}>Rename</Text>
</TouchableOpacity>
@@ -145,6 +149,35 @@ export default function ViewerScreen({document, onBack, onDelete, onRename}: Pro
<Text style={styles.loadingText}>Generating PDF</Text>
</View>
)}
<Modal visible={renaming} transparent animationType="fade">
<View style={styles.modalBg}>
<View style={styles.modalBox}>
<Text style={styles.modalTitle}>Rename Document</Text>
<TextInput
style={styles.modalInput}
value={renameText}
onChangeText={setRenameText}
autoFocus
selectTextOnFocus
placeholderTextColor="#666"
/>
<View style={styles.modalActions}>
<TouchableOpacity onPress={() => setRenaming(false)} style={styles.modalBtn}>
<Text style={styles.modalCancel}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
if (renameText.trim()) onRename(renameText.trim());
setRenaming(false);
}}
style={styles.modalBtn}>
<Text style={styles.modalConfirm}>Rename</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</View>
);
}
@@ -208,4 +241,18 @@ const styles = StyleSheet.create({
gap: 12,
},
loadingText: {color: '#fff', fontSize: 15},
modalBg: {flex: 1, backgroundColor: 'rgba(0,0,0,0.7)', justifyContent: 'center', padding: 24},
modalBox: {backgroundColor: '#1c1c1e', borderRadius: 16, padding: 20, gap: 16},
modalTitle: {color: '#fff', fontSize: 17, fontWeight: '600'},
modalInput: {
backgroundColor: '#2c2c2e',
borderRadius: 10,
padding: 12,
color: '#fff',
fontSize: 15,
},
modalActions: {flexDirection: 'row', justifyContent: 'flex-end', gap: 16},
modalBtn: {padding: 4},
modalCancel: {color: '#888', fontSize: 15},
modalConfirm: {color: '#007AFF', fontSize: 15, fontWeight: '600'},
});