get images, and display images

This commit is contained in:
m
2026-07-11 22:59:25 +02:00
parent 1cc8b94b60
commit f7cf2a2bef
5 changed files with 164 additions and 4 deletions
+32 -3
View File
@@ -1,7 +1,8 @@
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { View, Text, Image, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native';
import { FileItem } from '../types';
import { TagChip } from './TagChip';
import { useFileImage } from '../hooks/useFileImage';
interface FileCardProps {
file: FileItem;
@@ -9,16 +10,25 @@ interface FileCardProps {
}
export function FileCard({ file, onPress }: FileCardProps) {
const { localUri, loading } = useFileImage(file.url);
console.log(localUri)
const formatSize = (bytes: number) => {
if (bytes < 1024) return `${bytes} B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
};
console.log(file)
return (
<TouchableOpacity style={styles.container} onPress={() => onPress?.(file)}>
{file.url && (
<View style={styles.imageContainer}>
{loading && <ActivityIndicator style={styles.imageLoader} />}
{localUri && (
<Image source={{ uri: localUri }} style={styles.image} resizeMode="cover" />
)}
</View>
)}
<View style={styles.header}>
<Text style={styles.name} numberOfLines={1}>
{file.name}
@@ -53,6 +63,25 @@ const styles = StyleSheet.create({
shadowRadius: 2,
elevation: 2,
},
imageContainer: {
width: '100%',
height: 200,
borderRadius: 8,
overflow: 'hidden',
marginBottom: 12,
backgroundColor: '#f0f0f0',
},
image: {
width: '100%',
height: '100%',
},
imageLoader: {
position: 'absolute',
top: '50%',
left: '50%',
marginTop: -10,
marginLeft: -10,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
+64
View File
@@ -0,0 +1,64 @@
import { useEffect, useState } from 'react';
import { downloadAsync, documentDirectory, makeDirectoryAsync, getInfoAsync } from 'expo-file-system/legacy';
const CACHE_DIR = `${documentDirectory}file-images/`;
function getCacheKey(url: string): string {
let hash = 0;
for (let i = 0; i < url.length; i++) {
hash = ((hash << 5) - hash + url.charCodeAt(i)) | 0;
}
return Math.abs(hash).toString(36);
}
function getExtension(url: string): string {
const pathname = new URL(url).pathname;
const dot = pathname.lastIndexOf('.');
return dot >= 0 ? pathname.slice(dot) : '.jpg';
}
export function useFileImage(url: string | undefined) {
const [localUri, setLocalUri] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!url) return;
const resolvedUrl = url;
let cancelled = false;
async function load() {
const fileName = `${getCacheKey(resolvedUrl)}${getExtension(resolvedUrl)}`;
const fileUri = `${CACHE_DIR}${fileName}`;
const info = await getInfoAsync(fileUri);
if (info.exists) {
if (!cancelled) setLocalUri(info.uri);
return;
}
setLoading(true);
try {
await makeDirectoryAsync(CACHE_DIR, { intermediates: true });
const result = await downloadAsync(resolvedUrl, fileUri);
if (!cancelled) {
setLocalUri(result.uri);
}
} catch {
if (!cancelled) {
setLocalUri(null);
}
} finally {
if (!cancelled) setLoading(false);
}
}
load();
return () => {
cancelled = true;
};
}, [url]);
return { localUri, loading };
}
+1
View File
@@ -7,6 +7,7 @@ export interface FileItem {
updatedAt: string;
ocrText?: string;
tags: Tag[];
url?: string;
}
export interface Tag {