Clarify local backup permission recovery
All checks were successful
Deploy Sokko G / deploy (push) Successful in 17s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 17s
This commit is contained in:
parent
7b23a8601a
commit
34e542be28
6 changed files with 20 additions and 11 deletions
|
|
@ -36,7 +36,9 @@ locale du navigateur et conservent les dix fichiers `sokkog-global-YYYY-MM-DD.js
|
||||||
les plus récents. La vérification au démarrage ne demande pas de permission et ne
|
les plus récents. La vérification au démarrage ne demande pas de permission et ne
|
||||||
crée pas les jours manquants lorsque l'application était fermée. Une nouvelle
|
crée pas les jours manquants lorsque l'application était fermée. Une nouvelle
|
||||||
sauvegarde automatique est ignorée si son contenu est identique à la version la
|
sauvegarde automatique est ignorée si son contenu est identique à la version la
|
||||||
plus récente, en excluant uniquement l'horodatage d'export.
|
plus récente, en excluant uniquement l'horodatage d'export. Si le navigateur ne
|
||||||
|
conserve pas l'autorisation du dossier entre deux sessions, l'interface propose
|
||||||
|
une réautorisation explicite ; le démarrage n'ouvre aucune demande de permission.
|
||||||
|
|
||||||
Entrée type dans `modules` :
|
Entrée type dans `modules` :
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,13 +94,17 @@ test("manual backup replaces the day and retains ten non-consecutive versions",
|
||||||
assert.equal(directory.files.get("notes.json"), "old");
|
assert.equal(directory.files.get("notes.json"), "old");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("permission failure prevents export and cleanup", async () => {
|
test("missing permission never opens a prompt or starts an export", async () => {
|
||||||
|
for (const permission of ["prompt", "denied"]) {
|
||||||
const directory = new FakeDirectory();
|
const directory = new FakeDirectory();
|
||||||
directory.permission = "prompt";
|
directory.permission = permission;
|
||||||
|
directory.requestPermission = () => { throw new Error("Permission popup must require user interaction"); };
|
||||||
let generated = false;
|
let generated = false;
|
||||||
const result = await saveBackup({ directoryHandle: directory, generateJson: async () => { generated = true; return "{}"; } });
|
const result = await saveBackup({ directoryHandle: directory, generateJson: async () => { generated = true; return "{}"; } });
|
||||||
assert.equal(result.reason, "permission");
|
assert.equal(result.reason, "permission");
|
||||||
|
assert.equal(result.permission, permission);
|
||||||
assert.equal(generated, false);
|
assert.equal(generated, false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("cleanup failure does not invalidate a successfully written backup", async () => {
|
test("cleanup failure does not invalidate a successfully written backup", async () => {
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ export function validateSiteContent(site) {
|
||||||
"toolboxes.autoBackup.chooseFolder",
|
"toolboxes.autoBackup.chooseFolder",
|
||||||
"toolboxes.autoBackup.changeFolder",
|
"toolboxes.autoBackup.changeFolder",
|
||||||
"toolboxes.autoBackup.reauthorize",
|
"toolboxes.autoBackup.reauthorize",
|
||||||
|
"toolboxes.autoBackup.permissionRequired",
|
||||||
"toolboxes.autoBackup.saveNow",
|
"toolboxes.autoBackup.saveNow",
|
||||||
"toolboxes.autoBackup.noFolder",
|
"toolboxes.autoBackup.noFolder",
|
||||||
"toolboxes.autoBackup.never",
|
"toolboxes.autoBackup.never",
|
||||||
|
|
|
||||||
|
|
@ -1829,6 +1829,7 @@
|
||||||
"chooseFolder": "Choisir un dossier",
|
"chooseFolder": "Choisir un dossier",
|
||||||
"changeFolder": "Changer de dossier",
|
"changeFolder": "Changer de dossier",
|
||||||
"reauthorize": "Réautoriser l’accès",
|
"reauthorize": "Réautoriser l’accès",
|
||||||
|
"permissionRequired": "L’accès au dossier doit être réautorisé pour reprendre les sauvegardes. Utilisez « Réautoriser l’accès » ci-dessous.",
|
||||||
"saveNow": "Sauvegarder maintenant",
|
"saveNow": "Sauvegarder maintenant",
|
||||||
"noFolder": "Aucun dossier",
|
"noFolder": "Aucun dossier",
|
||||||
"never": "Jamais",
|
"never": "Jamais",
|
||||||
|
|
|
||||||
|
|
@ -118,10 +118,11 @@ export function AutoBackupModal({ backup, content, onClose }) {
|
||||||
<span className="switch-track" aria-hidden="true"><span className="switch-thumb" /></span>
|
<span className="switch-track" aria-hidden="true"><span className="switch-thumb" /></span>
|
||||||
<span className="auto-backup-toggle-copy"><strong>{content.enabled}</strong><small>{content.toggleHelp}</small><small>{content.retention}</small></span>
|
<span className="auto-backup-toggle-copy"><strong>{content.enabled}</strong><small>{content.toggleHelp}</small><small>{content.retention}</small></span>
|
||||||
</label>
|
</label>
|
||||||
|
{backup.config.directoryHandle && (backup.permission === "prompt" || backup.permission === "denied") && <p className="nds-inline-notice" data-variant="warning" role="status">{content.permissionRequired}</p>}
|
||||||
{backup.error && <p className="nds-inline-notice" data-variant="danger" role="alert">{backup.error}</p>}
|
{backup.error && <p className="nds-inline-notice" data-variant="danger" role="alert">{backup.error}</p>}
|
||||||
<footer className="nds-modal-footer auto-backup-modal-footer">
|
<footer className="nds-modal-footer auto-backup-modal-footer">
|
||||||
{backup.config.directoryHandle && backup.permission !== "granted" && <button className="nds-button" data-size="sm" type="button" disabled={backup.busy} onClick={() => void backup.requestPermission()}>{content.reauthorize}</button>}
|
{backup.config.directoryHandle && (backup.permission === "prompt" || backup.permission === "denied") && <button className="nds-button" data-size="sm" type="button" disabled={backup.busy} onClick={() => void backup.requestPermission()}>{content.reauthorize}</button>}
|
||||||
<button className="nds-button" data-size="sm" data-variant="primary" type="button" disabled={backup.busy || !backup.config.directoryHandle} onClick={() => void backup.saveNow()}>{content.saveNow}</button>
|
<button className="nds-button" data-size="sm" data-variant="primary" type="button" disabled={backup.busy || !backup.config.directoryHandle || backup.permission !== "granted"} onClick={() => void backup.saveNow()}>{content.saveNow}</button>
|
||||||
</footer>
|
</footer>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ export function useAutoBackup(store) {
|
||||||
const next = { ...configOverride, directoryHandle, lastBackup: new Date().toISOString() };
|
const next = { ...configOverride, directoryHandle, lastBackup: new Date().toISOString() };
|
||||||
await persist(next);
|
await persist(next);
|
||||||
}
|
}
|
||||||
if (!result.ok) setError(result.error?.message || "La sauvegarde locale a échoué.");
|
if (!result.ok) setError(result.reason === "permission" ? "" : result.error?.message || "La sauvegarde locale a échoué.");
|
||||||
if (result.ok && result.cleanupError) setError(result.cleanupError);
|
if (result.ok && result.cleanupError) setError(result.cleanupError);
|
||||||
return result;
|
return result;
|
||||||
} catch (runError) {
|
} catch (runError) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue