diff --git a/memento-mobile/app/(tabs)/home.tsx b/memento-mobile/app/(tabs)/home.tsx index 01c8a08..ff96da0 100644 --- a/memento-mobile/app/(tabs)/home.tsx +++ b/memento-mobile/app/(tabs)/home.tsx @@ -5,7 +5,7 @@ import { } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' import { useRouter } from 'expo-router' -import { CalendarDays, Search, BookOpen, Clock, ChevronRight } from 'lucide-react-native' +import { CalendarDays, PenLine, GraduationCap, Clock, ChevronRight } from 'lucide-react-native' import { apiFetch } from '@/lib/api' import { ENDPOINTS } from '@/lib/config' import { useAuthStore } from '@/lib/store' @@ -71,7 +71,7 @@ export default function HomeScreen() { - {/* Quick actions */} + {/* Quick actions — actions uniques, pas de doublons avec le tab bar */} @@ -79,17 +79,17 @@ export default function HomeScreen() { Note du jour - router.push('/(tabs)/notebooks')} style={s.quickCard} activeOpacity={0.7}> + router.push('/(tabs)/search')} style={s.quickCard} activeOpacity={0.7}> - + - Carnets + Nouvelle note router.push('/(tabs)/search')} style={s.quickCard} activeOpacity={0.7}> - + - Recherche + Révision diff --git a/memento-mobile/app/note/[id].tsx b/memento-mobile/app/note/[id].tsx index 59ad99c..ffb53b8 100644 --- a/memento-mobile/app/note/[id].tsx +++ b/memento-mobile/app/note/[id].tsx @@ -19,16 +19,17 @@ interface Note { notebookName?: string } -// Le markdown est parsé côté WebView (JS natif) — évite tout problème Metro bundler +// Le contenu TipTap est stocké en HTML — on l'enveloppe dans un style CSS propre function buildHtml(content: string, title: string) { - // On passe le contenu comme JSON pour éviter les problèmes d'échappement - const safeContent = JSON.stringify(content) - const safeTitle = JSON.stringify(title || 'Sans titre') + const safeTitle = title.replace(//g, '>') + // Détecter si le contenu est déjà du HTML ou du texte brut + const isHtml = content.trimStart().startsWith('<') + const body = isHtml ? content : `

${content.replace(/\n/g, '
')}

` return ` - + -
-
-
- +
${safeTitle}
+
+
${body}
` } @@ -144,12 +98,18 @@ export default function NoteScreen() { const { id } = useLocalSearchParams<{ id: string }>() const [note, setNote] = useState(null) const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) const router = useRouter() useEffect(() => { - apiFetch(ENDPOINTS.note(id)) - .then((r) => r.json()) + if (!id) return + apiFetch(ENDPOINTS.note(id as string)) + .then((r) => { + if (!r.ok) throw new Error(`Erreur ${r.status}`) + return r.json() + }) .then((data) => setNote(data.note ?? null)) + .catch((e) => setError(e.message)) .finally(() => setLoading(false)) }, [id]) @@ -161,33 +121,37 @@ export default function NoteScreen() { return ( - router.back()} style={s.backBtn}> + router.back()} style={s.backBtn} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}> {note?.title ?? '…'} - - - + {note && ( + + + + )} - {loading - ? - : note - ? - : Note introuvable.} + {loading && } + {error && {error}} + {!loading && !error && !note && Note introuvable.} + {note && ( + + )} ) } const s = StyleSheet.create({ safe: { flex: 1, backgroundColor: C.paper }, - header: { flexDirection: 'row', alignItems: 'center', gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: C.border }, + header: { flexDirection: 'row', alignItems: 'center', gap: 12, paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: C.border, backgroundColor: C.paper }, backBtn: { padding: 4 }, headerTitle: { flex: 1, fontSize: 15, fontWeight: '600', color: C.ink }, shareBtn: { padding: 4 },