From 393ee9df245c388b5326ae74be75e12703bbe6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Sat, 18 Jul 2026 10:25:43 +0200 Subject: [PATCH] Clear all storage implemented --- static/js/node_store.mjs | 46 ++++++++++++++++++++++++++++++++++++++ static/js/page_storage.mjs | 41 +++++++++++++++++++++++---------- views/layouts/main.gotmpl | 3 ++- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/static/js/node_store.mjs b/static/js/node_store.mjs index 531626b..a086d85 100644 --- a/static/js/node_store.mjs +++ b/static/js/node_store.mjs @@ -328,6 +328,52 @@ export class NodeStore { this.nodes[ORPHANED_NODE] = new Node({ UUID: ORPHANED_NODE, Name: 'Orphaned nodes', Special: true }, -1) }// }}} + deleteAll() {// {{{ + this.db.close() + + const req = indexedDB.deleteDatabase('notes') + + req.onsuccess = async () => { + try { + console.log('Database deleted successfully') + + // Deleting the storage will log out the user. + await this.deleteStorage() + await this.deleteCaches() + await this.deleteServiceWorkers() + + alert('Database deleted, will now log out.') + location.href = '/login' + } catch (e) { + console.error(e) + alert(e.message) + } + } + + req.onerror = (event) => { + console.error('Error deleting database:', event.target.errorCode) + } + + req.onblocked = () => { + console.warn('Deletion blocked. Close all other tabs/connections to this DB.') + } + }// }}} + async deleteStorage() {// {{{ + // Clearing local- and session-storage in case + // something of value to evil people gets stored there. + localStorage.clear() + sessionStorage.clear() + console.log('Local- and session-storage cleared.') + }// }}} + async deleteCaches() {// {{{ + const keys = await caches.keys() + return Promise.all(keys.map(key => caches.delete(key))) + }// }}} + async deleteServiceWorkers() {// {{{ + const registrations = await navigator.serviceWorker.getRegistrations() + await Promise.all(registrations.map(r => r.unregister())) + }// }}} + node(uuid, dataIfUndefined, newLevel) {//{{{ let n = this.nodes[uuid] if (n === undefined && dataIfUndefined !== undefined) diff --git a/static/js/page_storage.mjs b/static/js/page_storage.mjs index f6f562f..ed3970b 100644 --- a/static/js/page_storage.mjs +++ b/static/js/page_storage.mjs @@ -2,7 +2,7 @@ import { CustomHTMLElement } from "./lib/custom_html_element.mjs" import { API } from 'api' export class N2PageStorage extends CustomHTMLElement { - static { + static {// {{{ this.tmpl = document.createElement('template') this.tmpl.innerHTML = `

Local storage

-

Nodes

+

Notes

-
Local nodes
+
Local notes
-
Queued to sync
-
- -
History nodes
+
History notes
+ +
Notes to send
+

Files

@@ -52,17 +56,24 @@ export class N2PageStorage extends CustomHTMLElement {
Files to send
+ +

Clear storage

+
Remove all data from this device (not server) and logout the session.
+
This ensures that no notes or files is left on the browser.
+ ` - } - constructor() { + }// }}} + constructor() {// {{{ super(true) + .elBtnClearAll.addEventListener('click', ()=>this.clearAll()) + window._mbus.subscribe('SHOW_PAGE', event => { if (event.detail.data?.page == 'storage') this.render() }) - } - async render() { + }// }}} + async render() {// {{{ API.query('GET', '/file/count') .then(res => { this.elCountFilesOnServer.innerText = res.Count @@ -80,6 +91,12 @@ export class N2PageStorage extends CustomHTMLElement { this.elCountQueuedFiles.innerText = await globalThis.nodeStore.filesMetadata.countToUpload() this.elCountFilesOnDevice.innerText = await globalThis.nodeStore.filesMetadata.count() - } + }// }}} + clearAll() {// {{{ + if (!confirm('Do you want to remove ALL data from this device and logout?')) + return + + globalThis.nodeStore.deleteAll() + }// }}} } customElements.define('n2-pagestorage', N2PageStorage) diff --git a/views/layouts/main.gotmpl b/views/layouts/main.gotmpl index 13a0bcf..3385bec 100644 --- a/views/layouts/main.gotmpl +++ b/views/layouts/main.gotmpl @@ -20,7 +20,8 @@