Under the Hood.fr - dsblank/gramps-connect GitHub Wiki

🌐 English · Deutsch · Español · Nederlands · 简体中文

Sous le capot

Notes d'implémentation qui ne s'intègrent pas dans le fil narratif de Architecture — des détails utiles à connaître si vous déboguez quelque chose, vérifiez ce que l'application stocke et où, ou vous demandez pourquoi elle se comporte d'une certaine façon.

Stockage navigateur : sessionStorage vs localStorage

Les deux sont délimités au profil de navigateur + origine, pas à qui est connecté. Si l'Utilisateur A se déconnecte et que l'Utilisateur B se connecte sur le même navigateur (même machine, même profil de navigateur), l'onglet de l'Utilisateur B démarre avec ce que le stockage de cette origine contenait déjà — sauf si l'application l'efface explicitement ou lui applique un espace de noms. Gramps Connect répartit son stockage côté client entre les deux API exactement selon cette ligne :

sessionStorage (app/src/auth/auth.ts) contient le jeton d'accès, le jeton de rafraîchissement, et le nom d'utilisateur. logout() efface explicitement les trois, et sessionStorage lui-même ne survit pas à un onglet fermé — une nouvelle connexion démarre donc toujours propre, et rien ici ne fuit entre utilisateurs.

localStorage contient les préférences d'interface, et — contrairement aux jetons d'authentification — rien de tout cela n'est effacé à la déconnexion :

Clé Portée Fichier
gramps-connect_home_person par arbre (indexée par getTreeId()) app/src/store/homePersonPreference.ts
gramps-connect_column_widths globale app/src/store/columnWidths.ts
gramps-connect_tree_manual_expand globale app/src/store/treeExpandPreference.ts
gramps-connect_aside_widths globale app/src/App.tsx
gramps-connect:map-viewport globale app/src/components/visuals/MapCanvas.tsx
gramps-connect_browser_notifications_enabled globale app/src/store/browserNotifications.ts

Aucune n'a d'espace de noms par utilisateur, et seule home_person en a un par arbre. Effet pratique : sur une machine partagée, la prochaine personne à se connecter (même dans un arbre différent, pour les clés globales) hérite des largeurs de colonnes, tailles de panneaux, cadrage de carte, et bascule de notifications de l'utilisateur précédent — et, si c'est le même arbre, aussi son choix de personne de référence. Rien de sensible n'est exposé (aucune donnée d'arbre ni identifiant ne réside ici, seulement des préférences d'affichage), mais c'est un comportement réel qu'un utilisateur pourrait remarquer et sur lequel il pourrait poser des questions.

Si une isolation par utilisateur est un jour souhaitée, la solution est le même schéma que homePersonPreference.ts utilise déjà pour la délimitation par arbre — indexer l'objet stocké par ID utilisateur (ou nom d'utilisateur) au lieu de, ou en plus de, l'ID d'arbre.

Panneau lié/détail : redessin instantané en cas de nouvelle visite

La récupération par fiche (fetchObjectExtended, app/src/store/objectDetail.ts) du panneau supérieur droit (et du bas « Détail de référence ») s'appuie sur un petit cache en mémoire, « stale-while-revalidate », indexé par vue + handle et plafonné à 50 entrées (évincées en LRU). Quitter une fiche puis y revenir redessine immédiatement le dernier détail connu au lieu d'afficher un indicateur de chargement — les vues de liste sous-jacentes (DataTable) le faisaient déjà via leur propre cache persistant ViewStore/SQLite (voir Architecture) ; cela comble la même lacune pour le panneau de détail, qui auparavant récupérait tout depuis zéro à chaque montage.

Ce n'est pas un vrai cache au sens « éviter la récupération » : chaque montage appelle toujours fetchObjectExtended exactement comme avant et écrase l'entrée du cache avec le résultat frais. Comme les clés localStorage ci-dessus, c'est un cache au niveau du module — non effacé à la déconnexion ou au changement d'arbre.

Le panneau récupère aussi à nouveau chaque fois que la synchronisation en direct signale n'importe quel changement de l'arbre, pas seulement un changement à sa propre (vue, handle). Le chemin normal de la synchronisation en direct n'incrémente que la révision d'un ViewStore pour un changement correspondant à la propre table/handle de ce store, ce qui est précis pour les vues de liste mais insuffisant ici : une modification apportée à une autre fiche intégrée dans les références résolues de celle-ci (le texte d'une Note, la date d'un Événement ramenée via extend=all/rétro-liens) ne déclencherait sinon aucune nouvelle récupération, et resterait donc obsolète jusqu'à ce que le panneau soit remonté. Récupérer à nouveau à chaque changement de l'arbre échange un peu de trafic de requêtes supplémentaire contre la correctitude, plutôt que de redériver quels handles sont intégrés — cette forme varie selon le type d'objet (voir Modèle de données et édition).