From c5db5290ac2fae10929faba2aa66aef97355c0fc Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Thu, 24 Sep 2026 23:27:54 +0200 Subject: [PATCH] add storage quota display --- dist/index.js | 98 ++++- dist/styles.css | 4 + dist/sw.js | 2 +- dist/version.txt | 2 +- src/Model/Global/.settingsModel.ts.swp | Bin 12288 -> 0 bytes src/Model/Global/storageModel.ts | 37 +- src/Model/Utility/utility.ts | 4 + src/View/Components/usageBar.tsx | 26 ++ src/View/Modals/storageModal.tsx | 138 ++++--- src/View/translations.ts | 505 ++++++++++++----------- src/ViewModel/Global/storageViewModel.ts | 10 + 11 files changed, 500 insertions(+), 326 deletions(-) delete mode 100644 src/Model/Global/.settingsModel.ts.swp create mode 100644 src/View/Components/usageBar.tsx diff --git a/dist/index.js b/dist/index.js index dfbf090f..6709e8f1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -306,12 +306,13 @@ applyButton: "Apply", backButton: "Back", cancelButton: "Cancel", + confirmButton: "Confirm", + continueButton: "Continue", closeButton: "Close", deleteButton: "Delete", exitButton: "Exit", fullscreenButton: "Fullscreen", - continueButton: "Continue", - confirmButton: "Confirm", + refreshButton: "Refresh", saveButton: "Save", setButton: "Set", filterOrCreateLabel: "Search or create", @@ -424,6 +425,8 @@ noItemSelected: "No item selected", notAFile: "(not a file)", contentEmpty: "(empty)", + usageLabel: "Usage", + usageVauleLabel: (used, max) => `${used} of ${max} MB`, path: "Path", content: "Content", deleteItem: "Delete item", @@ -551,12 +554,13 @@ applyButton: "Anwenden", backButton: "Zur\xFCck", cancelButton: "Abbrechen", + continueButton: "Weiter", + confirmButton: "Best\xE4tigen", closeButton: "Schlie\xDFen", deleteButton: "L\xF6schen", exitButton: "Schlie\xDFen", fullscreenButton: "Vollbild", - continueButton: "Weiter", - confirmButton: "Best\xE4tigen", + refreshButton: "Aktualisieren", saveButton: "Speichern", setButton: "OK", filterOrCreateLabel: "Suchen oder erstellen", @@ -661,6 +665,8 @@ noItemSelected: "Kein Element ausgew\xE4hlt", notAFile: "(keine Datei)", contentEmpty: "(leer)", + usageLabel: "Speicher", + usageVauleLabel: (used, max) => `${used} von ${max} MB belegt`, path: "Pfad", content: "Inhalt", deleteItem: "Element l\xF6schen", @@ -776,12 +782,13 @@ applyButton: "Guardar", backButton: "Atr\xE1s", cancelButton: "Cancelar", + continueButton: "Continuar", + confirmButton: "Confirmar", closeButton: "Cerrar", deleteButton: "Borrar", exitButton: "Salir", fullscreenButton: "Pantalla completa", - continueButton: "Continuar", - confirmButton: "Confirmar", + refreshButton: "Actualizar", saveButton: "Guardar", setButton: "OK", filterOrCreateLabel: "Buscar o crear", @@ -886,6 +893,8 @@ noItemSelected: "Ning\xFAn elemento seleccionado", notAFile: "(no es un archivo)", contentEmpty: "(vac\xEDo)", + usageLabel: "Almacenamiento", + usageVauleLabel: (used, max) => `${used} de ${max} MB en uso`, path: "Ruta", content: "Contenido", deleteItem: "Eliminar elemento", @@ -1121,6 +1130,9 @@ if (value != null) localStorage.setItem(`_${key}`, value); return value; } + function bytesToMB(bytes) { + return bytes / (1024 * 1024); + } function stringify(data) { return JSON.stringify(data, null, 4); } @@ -1607,13 +1619,41 @@ if (object == null) return null; return object; }; - // cleaning + // cleaning & usage this.removeJunk = () => { this.recurse([], (path) => { if (path[0] == DATA_VERSION) return; this.remove(path); }); }; + this.determineCapacity = () => { + const KEY = "storage-capacity-check"; + let chunk = "0"; + for (let i = 0; i < 1024 * 256; i++) { + chunk += "0"; + } + localStorage.setItem(KEY, ""); + while (true) { + try { + const current = localStorage.getItem(KEY); + console.log(current); + localStorage.setItem(KEY, current + chunk); + } catch (e) { + const capacity = this.calculateUsage(); + localStorage.removeItem(KEY); + return capacity; + } + } + }; + this.calculateUsage = () => { + let data = JSON.stringify(localStorage); + const encoder = new TextEncoder(); + const encoded = encoder.encode(data); + const bytes = encoded.byteLength; + const mb = bytesToMB(bytes); + const rounded = Math.round(mb * 100) / 100; + return rounded; + }; // tree this.initializeTree = () => { console.log("initializing tree"); @@ -1721,6 +1761,8 @@ PATH_COMPONENT_SEPARATOR ); this.didMakeChanges = new State(false); + this.occupiedSpaceMB = new State(0); + this.maximumSpaceMB = new State(0); this.lastDeletedItemPath = new State(""); // methods this.getSelectedItemContent = () => { @@ -1742,10 +1784,16 @@ this.coreViewModel.storageModel.removeJunk(); this.selectedPath.value = PATH_COMPONENT_SEPARATOR; }; + this.calculateUsage = () => { + this.occupiedSpaceMB.value = this.coreViewModel.storageModel.calculateUsage(); + this.maximumSpaceMB.value = this.coreViewModel.storageModel.determineCapacity(); + console.log(this.occupiedSpaceMB.value, this.maximumSpaceMB.value); + }; // view this.showStorageModal = () => { this.coreViewModel.context = this; this.isShowingStorageModal.value = true; + this.calculateUsage(); }; // exit this.close = () => { @@ -7125,13 +7173,47 @@ )); } + // src/View/Components/usageBar.tsx + function UsageBar(label, valueLabel, value, maximum) { + const style = createProxyState([value, maximum], () => `width: ${100 * (value.value / maximum.value)}%`); + return /* @__PURE__ */ createElement( + "div", + { + class: "surface flex-column padding gap" + }, + /* @__PURE__ */ createElement("b", null, label), + /* @__PURE__ */ createElement( + "div", + { + class: "width-100 surface-alt", + style: "height: 18px" + }, + /* @__PURE__ */ createElement( + "div", + { + class: "height-100 background-primary", + "set:style": style + } + ) + ), + /* @__PURE__ */ createElement( + "span", + { + class: "secondary", + "subscribe:innerText": valueLabel + } + ) + ); + } + // src/View/Modals/storageModal.tsx function StorageModal(coreViewModel2, storageViewModel2) { + const usageValueLabel = createProxyState([storageViewModel2.occupiedSpaceMB, storageViewModel2.maximumSpaceMB], () => coreViewModel2.translations.storage.usageVauleLabel(storageViewModel2.occupiedSpaceMB.value, storageViewModel2.maximumSpaceMB.value)); const detailView = createProxyState( [storageViewModel2.selectedPath], () => { if (storageViewModel2.selectedPath.value == PATH_COMPONENT_SEPARATOR) - return /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.storage.noItemSelected), /* @__PURE__ */ createElement("hr", null), DangerousActionButton( + return /* @__PURE__ */ createElement("div", { class: "flex-column gap" }, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.storage.noItemSelected), /* @__PURE__ */ createElement("hr", null), UsageBar(coreViewModel2.translations.storage.usageLabel, usageValueLabel, storageViewModel2.occupiedSpaceMB, storageViewModel2.maximumSpaceMB), /* @__PURE__ */ createElement("hr", null), DangerousActionButton( coreViewModel2, coreViewModel2.translations.storage.removeJunkButton, "delete_forever", diff --git a/dist/styles.css b/dist/styles.css index 2ff852c0..e5532e16 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -145,6 +145,10 @@ a { color: var(--link); } +.background-primary { + background: var(--primary); +} + /* text */ .success { diff --git a/dist/sw.js b/dist/sw.js index d796792c..a8856036 100644 --- a/dist/sw.js +++ b/dist/sw.js @@ -1,4 +1,4 @@ -const VERSION = "2610 Beta 1" +const VERSION = "2610 Beta 2" function processUrl(event) { const url = event.request.url; diff --git a/dist/version.txt b/dist/version.txt index fb83658c..ac0e4b32 100644 --- a/dist/version.txt +++ b/dist/version.txt @@ -1 +1 @@ -2610 Beta 1 +2610 Beta 2 diff --git a/src/Model/Global/.settingsModel.ts.swp b/src/Model/Global/.settingsModel.ts.swp deleted file mode 100644 index 864d2fa77bf19e1d49ffdd99a9f0a6e6423ebf63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2%WoS+9LJ}Dl=5g=%7F?58q7nEWbBY$h@%n(0#(!mBDqbFA`TOKY%f{wT066O zs0~nVoO?m3kl@hXDhe0i1`=?pM7fm#PD+0jq#jz$#!BunJfOtO8bn|Cs`^dw{%+ISs_~^5Xk} zzI*)9-mC&v0jq#jz$#!BunJfOtO8a6tAJI&Dqt130~KHmLLB_~AG;gQBgc0-GQNGvG9s08fFtz^_Au+yLK!FTo~Q0;fS0909iu6LJk)2CJY8d{70)!7mRG z@)NiPJ_KuE5>&w$AmGRQ3AqZcfXl!KbD#ho1&@Fs@Y{Wad;&Is4<^7-FbHnmOUU=& z2DkzksDcw<6byjR4iWMmco$p%3*Z>Ieh(qvfUm&^U=chG9tV$s2f@z=3Hbti4laQ; zum~o>IH-alaC4B5ufY4@0$2bqg5zKa90CWyAovsO@&ou5deI1}`N2#i}FgZCdo$iqm2^dsTMhiI+vVBxHbNR>hGL9UUHq5Xw~{ znZ!D`xQy1&Ou0B*O{T9zQ;id$WZMyC*JlmAWX0jcvtCVNDW~!kClGRqt^3Ud&X;rh zpA|en+zv7eOwF?kp37ARrfv2HLOE`V!F0UYteZ$-PK4?sZhsLhu_oy z8-3176_OYPCMEYIotVf*X*rTD>7~au&8u)uX->~mFLYhl(Gv(bYs6t*Ea(vmv4X0` z_uO^b(-wWyTCDg^gPwe$w-U*Kk>K$%XFWBk6dkO~S>wdY-*(#sR<7q}?f2$lYF$ip|HtzI=%S2~kw;ZoEy6L3lUD7cg%%pl#djF?nCi$s}3 zm`CYyUL}hTc2%q{<3yD%b8H$^u6H?Z+xQ%f+zp%+COLNFIHyu+r<5ehFp^)TT7L4Y zy~BJTnM5s7kFU-%H{>b(wBTl|F!fQ~_C|-Qdb3nRn{eA|0tnqW9H z+E$0sd1_kSu1|frw!LTBhCBLalC!rn>|42Bo^9`+X|khdDkE-xCGjQ_?a8ZwBe_n@ z5?$#Fs#JWbNZlsZ|K0pdqExx0F7366nIz@^k%UbLy%L+K0gc;)Xb*H1>gKH^6 tC3-HiTbgaQl*9tvpv}PV&_dZ9wbyY42?!jmyPSDpw@T;Q>Roe^`~|km^UVMN diff --git a/src/Model/Global/storageModel.ts b/src/Model/Global/storageModel.ts index 5a0340c4..3e660b19 100644 --- a/src/Model/Global/storageModel.ts +++ b/src/Model/Global/storageModel.ts @@ -1,6 +1,5 @@ -// cleanup: Phase A -import { localeCompare, parseValidObject, stringify } from "../Utility/utility"; +import { bytesToMB, localeCompare, parseValidObject, stringify } from "../Utility/utility"; import { DATA_VERSION, ValidObject } from "../Utility/typeSafety"; export const PATH_COMPONENT_SEPARATOR = "\\"; @@ -144,7 +143,7 @@ export default class StorageModel { return object; }; - // cleaning + // cleaning & usage readonly removeJunk = (): void => { this.recurse([], (path: string[]) => { if (path[0] == DATA_VERSION) return; @@ -152,6 +151,38 @@ export default class StorageModel { }); }; + readonly determineCapacity = (): number => { + const KEY = "storage-capacity-check"; + + let chunk = "0"; + for (let i = 0; i < 1024*256; i++) { + chunk += "0"; + } + + localStorage.setItem(KEY, ""); + while (true) { + try { + const current = localStorage.getItem(KEY); + console.log(current); + localStorage.setItem(KEY, current + chunk); + } catch (e) { + const capacity = this.calculateUsage(); + localStorage.removeItem(KEY); + return capacity; + } + } + } + + readonly calculateUsage = (): number => { + let data = JSON.stringify(localStorage); + const encoder = new TextEncoder(); + const encoded = encoder.encode(data); + const bytes = encoded.byteLength; + const mb = bytesToMB(bytes); + const rounded = Math.round(mb * 100)/100; + return rounded; + } + // tree readonly initializeTree = (): void => { console.log("initializing tree"); diff --git a/src/Model/Utility/utility.ts b/src/Model/Utility/utility.ts index fd58bdb2..d411d949 100644 --- a/src/Model/Utility/utility.ts +++ b/src/Model/Utility/utility.ts @@ -177,6 +177,10 @@ export function getLocalStorageItemAndClear(key: string): string | null { return value; } +export function bytesToMB(bytes: number): number { + return bytes / (1024*1024); +} + // string & parsing export function stringify(data: any): string { return JSON.stringify(data, null, 4); diff --git a/src/View/Components/usageBar.tsx b/src/View/Components/usageBar.tsx new file mode 100644 index 00000000..9b2808d1 --- /dev/null +++ b/src/View/Components/usageBar.tsx @@ -0,0 +1,26 @@ +import * as React from "../../react"; + +export function UsageBar(label: string, valueLabel: React.State, value: React.State, maximum: React.State) { + const style = React.createProxyState([value, maximum], ()=>`width: ${100*(value.value/maximum.value)}%`) + + return ( +
+ {label} +
+
+
+ +
+ ); +} diff --git a/src/View/Modals/storageModal.tsx b/src/View/Modals/storageModal.tsx index d1169e12..6ce5cfaa 100644 --- a/src/View/Modals/storageModal.tsx +++ b/src/View/Modals/storageModal.tsx @@ -5,82 +5,90 @@ import * as React from "../../react"; import StorageViewModel from "../../ViewModel/Global/storageViewModel"; import CoreViewModel from "../../ViewModel/Global/coreViewModel"; import { PATH_COMPONENT_SEPARATOR } from "../../Model/Global/storageModel"; +import {UsageBar} from "../Components/usageBar"; export function StorageModal( coreViewModel: CoreViewModel, storageViewModel: StorageViewModel, ) { + const usageValueLabel = React.createProxyState([storageViewModel.occupiedSpaceMB, storageViewModel.maximumSpaceMB], ()=> + coreViewModel.translations.storage.usageVauleLabel(storageViewModel.occupiedSpaceMB.value, storageViewModel.maximumSpaceMB.value)); + const detailView = React.createProxyState( - [storageViewModel.selectedPath], - () => { - if (storageViewModel.selectedPath.value == PATH_COMPONENT_SEPARATOR) - return ( -
- - {coreViewModel.translations.storage.noItemSelected} - + [storageViewModel.selectedPath], + () => { + if (storageViewModel.selectedPath.value == PATH_COMPONENT_SEPARATOR) + return ( +
+ + {coreViewModel.translations.storage.noItemSelected} + -
+
- {DangerousActionButton( - coreViewModel, - coreViewModel.translations.storage.removeJunkButton, - "delete_forever", - storageViewModel.removeJunk, - )} -
- ); + {UsageBar(coreViewModel.translations.storage.usageLabel, usageValueLabel, storageViewModel.occupiedSpaceMB, storageViewModel.maximumSpaceMB)} - return ( -
-
-
- {coreViewModel.translations.storage.path} - -
-
-
-
- {coreViewModel.translations.storage.content} - -
-
+
- {DangerousActionButton( - coreViewModel, - coreViewModel.translations.storage.deleteItem, - "delete_forever", - storageViewModel.deleteSelectedItem, - )} -
- ); - }, + {DangerousActionButton( + coreViewModel, + coreViewModel.translations.storage.removeJunkButton, + "delete_forever", + storageViewModel.removeJunk, + )} +
+ ); + + return ( +
+
+
+ {coreViewModel.translations.storage.path} + +
+
+
+
+ {coreViewModel.translations.storage.content} + +
+
+ + {DangerousActionButton( + coreViewModel, + coreViewModel.translations.storage.deleteItem, + "delete_forever", + storageViewModel.deleteSelectedItem, + )} +
+ ); + }, ); return ( - + ); } diff --git a/src/View/translations.ts b/src/View/translations.ts index 2a06210f..fe03bae3 100644 --- a/src/View/translations.ts +++ b/src/View/translations.ts @@ -1,338 +1,341 @@ const englishTranslations = { updater: { - migrated: "Migrated", + migrated: "Migrated", }, general: { - deleteItemButtonAudioLabel: "delete item", - searchButtonAudioLabel: "search", - searchButtonClearAudioLabel: "clear search query", + deleteItemButtonAudioLabel: "delete item", + searchButtonAudioLabel: "search", + searchButtonClearAudioLabel: "clear search query", - abortButton: "Abort", - applyButton: "Apply", - backButton: "Back", - cancelButton: "Cancel", - closeButton: "Close", - deleteButton: "Delete", - exitButton: "Exit", - fullscreenButton: "Fullscreen", - - continueButton: "Continue", - confirmButton: "Confirm", - saveButton: "Save", - setButton: "Set", + abortButton: "Abort", + applyButton: "Apply", + backButton: "Back", + cancelButton: "Cancel", + confirmButton: "Confirm", + continueButton: "Continue", + closeButton: "Close", + deleteButton: "Delete", + exitButton: "Exit", + fullscreenButton: "Fullscreen", + refreshButton: "Refresh", + saveButton: "Save", + setButton: "Set", filterOrCreateLabel: "Search or create", createLabel: (query: string) => `Create "${query}"`, - reloadAppButton: "Reload App", + reloadAppButton: "Reload App", - fileVersionLabel: "Version", - searchLabel: "Search", - searchSuggestionsLabel: "Recent searches", - waitingLabel: "Waiting...", + fileVersionLabel: "Version", + searchLabel: "Search", + searchSuggestionsLabel: "Recent searches", + waitingLabel: "Waiting...", - restoreConnection: "Restore connection", + restoreConnection: "Restore connection", - noPageSelected: "No page selected", + noPageSelected: "No page selected", }, regional: { - weekdays: { - full: [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - ], - abbreviated: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - }, + weekdays: { + full: [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ], + abbreviated: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + }, }, homePage: { - appName: "Comms", + appName: "Comms", - /// + /// - overviewHeadline: "Overview", + overviewHeadline: "Overview", - serverAddress: "Server address", - serverAddressPlaceholder: "wss://192.168.0.69:3000", - connectAudioLabel: "connect to server", - disconnectAudioLabel: "disconnect from server", - manageConnectionsAudioLabel: "manage connections", + serverAddress: "Server address", + serverAddressPlaceholder: "wss://192.168.0.69:3000", + connectAudioLabel: "connect to server", + disconnectAudioLabel: "disconnect from server", + manageConnectionsAudioLabel: "manage connections", - yourNameLabel: "Your name", - yourNamePlaceholder: "Jane Doe", - setNameButtonAudioLabel: "set name", + yourNameLabel: "Your name", + yourNamePlaceholder: "Jane Doe", + setNameButtonAudioLabel: "set name", - settingsButton: "Settings", - manageStorageButton: "Manage storage", - transferDataButton: "Transfer or export data", + settingsButton: "Settings", + manageStorageButton: "Manage storage", + transferDataButton: "Transfer or export data", updateButton: (version: string) => `Update to ${version}`, - scrollToChatButton: "Chats", + scrollToChatButton: "Chats", - /// + /// - backToOverviewAudioLabel: "go back to overview", - chatsHeadline: "Chats", + backToOverviewAudioLabel: "go back to overview", + chatsHeadline: "Chats", - addChatAudioLabel: "name of new chat", - addChatPlaceholder: "Add chat", - addChatButton: "Add chat", + addChatAudioLabel: "name of new chat", + addChatPlaceholder: "Add chat", + addChatButton: "Add chat", }, settings: { - pages: { - appearance: "Appearance", - regional: "Language & Region", - info: "About Comms", - }, - themes: { - dynamic: "Dynamic", - dark: "Dark", - light: "Light", - system: "Device theme", - }, + pages: { + appearance: "Appearance", + regional: "Language & Region", + info: "About Comms", + }, + themes: { + dynamic: "Dynamic", + dark: "Dark", + light: "Light", + system: "Device theme", + }, - version: "Version", - language: "Language", + version: "Version", + language: "Language", - firstDayOfWeekLabel: "First day of week", + firstDayOfWeekLabel: "First day of week", }, connectionModal: { - connectionModalHeadline: "Manage Connections", + connectionModalHeadline: "Manage Connections", - /// + /// - connectButtonAudioLabel: "connect", + connectButtonAudioLabel: "connect", }, dataTransferModal: { - transferDataHeadline: "Data Transfer", - sendHeadline: "Transfer to other device", - receiveHeadline: "Transfer to This Device", - exportHeadline: "Export Data", - importHeadline: "Import Data", - selectionDescription: "Select the data that you want to transfer.", - exportSelectionDescription: "Select the data that you want to export.", - dataEntryDescription: "Enter this data on the other device.", - dataEntryInputDescription: - "Enter the data displayed on the other device.", + transferDataHeadline: "Data Transfer", + sendHeadline: "Transfer to other device", + receiveHeadline: "Transfer to This Device", + exportHeadline: "Export Data", + importHeadline: "Import Data", + selectionDescription: "Select the data that you want to transfer.", + exportSelectionDescription: "Select the data that you want to export.", + dataEntryDescription: "Enter this data on the other device.", + dataEntryInputDescription: + "Enter the data displayed on the other device.", - /// + /// - fromThisDeviceButton: "Send to other device", - toThisDeviceButton: "Send to this device", - exportButton: "Export to file", - importButton: "Import from file", + fromThisDeviceButton: "Send to other device", + toThisDeviceButton: "Send to this device", + exportButton: "Export to file", + importButton: "Import from file", - /// + /// - generalHeadline: "General", + generalHeadline: "General", - connectionData: "Connection Data", - settingsData: "Settings Data", + connectionData: "Connection Data", + settingsData: "Settings Data", - chatsHeadline: "Chats", + chatsHeadline: "Chats", - /// + /// - transferChannelHeadline: "Transfer Chanel", - transferKeyHeadline: "Transfer Encryption Key", + transferChannelHeadline: "Transfer Chanel", + transferKeyHeadline: "Transfer Encryption Key", - sendButton: "Send", - sendAgainButton: "Send again", + sendButton: "Send", + sendAgainButton: "Send again", - /// + /// - filesSentCount: (count: number) => `Files sent: ${count}.`, - allFilesSent: "Done.", + filesSentCount: (count: number) => `Files sent: ${count}.`, + allFilesSent: "Done.", - filesReceivedCount: (count: number) => `Files processed: ${count}.`, + filesReceivedCount: (count: number) => `Files processed: ${count}.`, - // + // - exportKey: "Encryption key", - exportKeyConfirmation: "Confirm", - downloadFileButton: "Download", - importFileButton: "Import", - decryptImportButton: "Decrypt", - incorrectPassphraseError: "The encryption key is incorrect", + exportKey: "Encryption key", + exportKeyConfirmation: "Confirm", + downloadFileButton: "Download", + importFileButton: "Import", + decryptImportButton: "Decrypt", + incorrectPassphraseError: "The encryption key is incorrect", }, storage: { - noItemSelected: "No item selected", - notAFile: "(not a file)", - contentEmpty: "(empty)", + noItemSelected: "No item selected", + notAFile: "(not a file)", + contentEmpty: "(empty)", - path: "Path", - content: "Content", + usageLabel: "Usage", + usageVauleLabel: (used: number, max: number) => `${used} of ${max} MB`, - deleteItem: "Delete item", + path: "Path", + content: "Content", - removeJunkButton: "Delete junk files", + deleteItem: "Delete item", + + removeJunkButton: "Delete junk files", }, chatPage: { - closeChatAudioLabe: "close chat", - chatSettingsAudioLabel: "chat settings", + closeChatAudioLabe: "close chat", + chatSettingsAudioLabel: "chat settings", - pages: { - settings: "Settings", - messages: "Messages", - tasks: "Tasks", - calendar: "Calendar", - }, + pages: { + settings: "Settings", + messages: "Messages", + tasks: "Tasks", + calendar: "Calendar", + }, - settings: { - settingsHeadline: "Settings", + settings: { + settingsHeadline: "Settings", - primaryChannelLabel: "Primary channel", - setPrimaryChannelButtonAudioLabel: "set primary channel", + primaryChannelLabel: "Primary channel", + setPrimaryChannelButtonAudioLabel: "set primary channel", - namespaceLabel: "Namespace", - namespacePlaceholder: "No namespace", - setNamespaceButtonAudioLabel: "set namespace", + namespaceLabel: "Namespace", + namespacePlaceholder: "No namespace", + setNamespaceButtonAudioLabel: "set namespace", - newSecondaryChannelPlaceholder: "Add secondary channel", - newSecondaryChannelAudioLabel: "name of new secondary channel", - addSecondaryChannelButtonAudioLabel: "add secondary channel", + newSecondaryChannelPlaceholder: "Add secondary channel", + newSecondaryChannelAudioLabel: "name of new secondary channel", + addSecondaryChannelButtonAudioLabel: "add secondary channel", - encryptionKeyLabel: "Encryption key", - setEncryptionKeyButtonAudioLabel: "set encryption key", - showEncryptionKey: "Show encryption key", + encryptionKeyLabel: "Encryption key", + setEncryptionKeyButtonAudioLabel: "set encryption key", + showEncryptionKey: "Show encryption key", - deleteChatButton: "Delete entire chat", - }, + deleteChatButton: "Delete entire chat", + }, - message: { - messagesHeadline: "Messages", + message: { + messagesHeadline: "Messages", - messageFilterHeadline: "Filter messages", - messageFilterReactionsHadline: "Reactions", - messageFilterAllReactionsButton: "Show all", + messageFilterHeadline: "Filter messages", + messageFilterReactionsHadline: "Reactions", + messageFilterAllReactionsButton: "Show all", - /// + /// - composerInputPlaceholder: "Type a message...", - sendMessageButtonAudioLabel: "send message", - filterMessagesButtonAudioLabel: "filter messages", + composerInputPlaceholder: "Type a message...", + sendMessageButtonAudioLabel: "send message", + filterMessagesButtonAudioLabel: "filter messages", - /// + /// - showMessageInfoButtonAudioLabel: "show message info", - messageInfoHeadline: "Message Info", - cancelReplyAudioLabel: "cancel reply", + showMessageInfoButtonAudioLabel: "show message info", + messageInfoHeadline: "Message Info", + cancelReplyAudioLabel: "cancel reply", - sentBy: "Sent by", - timeSent: "Time sent", - channel: "Channel", - messageContent: "Message content", + sentBy: "Sent by", + timeSent: "Time sent", + channel: "Channel", + messageContent: "Message content", - copyMessageButton: "Copy message", - resendMessageButton: "Resend message", - decryptMessageButton: "Decrypt message", - replyToMessageButton: "Reply to message", - deleteMessageButton: "Delete message", - - // - - thumbsUpReaction: "Reaction: thumbs up", - checkReaction: "Reaction: check", - stopReaction: "Reaction: stop sign", - attentionReaction: "Reaction: exclamation mark", - doubleAttentionReaction: "Reaction: double exclamation mark", - questionReaction: "Reaction: question mark", + copyMessageButton: "Copy message", + resendMessageButton: "Resend message", + decryptMessageButton: "Decrypt message", + replyToMessageButton: "Reply to message", + deleteMessageButton: "Delete message", // - + + thumbsUpReaction: "Reaction: thumbs up", + checkReaction: "Reaction: check", + stopReaction: "Reaction: stop sign", + attentionReaction: "Reaction: exclamation mark", + doubleAttentionReaction: "Reaction: double exclamation mark", + questionReaction: "Reaction: question mark", + + // + replyPrefixLabel: "Replies: ", replyHeaderLabel: (message: string) => `Replies to "${message}"`, - }, + }, - task: { - noBoardSelected: "No board selected", - boardNotFound: "Board not found", + task: { + noBoardSelected: "No board selected", + boardNotFound: "Board not found", - /// + /// - closeBoardButtonAudioLabel: "close board", - toggleBoardButtonAudioLabel: "toggle board list", - showBoardSettingsButtonAudioLabel: "show board settigns", + closeBoardButtonAudioLabel: "close board", + toggleBoardButtonAudioLabel: "toggle board list", + showBoardSettingsButtonAudioLabel: "show board settigns", - listViewButtonAudioLabel: "list view", - kanbanViewButtonAudioLabel: "kanban view", - statusViewButtonAudioLabel: "status grid view", + listViewButtonAudioLabel: "list view", + kanbanViewButtonAudioLabel: "kanban view", + statusViewButtonAudioLabel: "status grid view", - filterTasksButtonAudioLabel: "filter tasks", - createTaskButtonAudioLabel: "create new task", + filterTasksButtonAudioLabel: "filter tasks", + createTaskButtonAudioLabel: "create new task", - /// + /// - boardSettingsHeadline: "Board Settings", - boardNameInputLabel: "Board name", - deleteBoardButton: "Delete board and all tasks", + boardSettingsHeadline: "Board Settings", + boardNameInputLabel: "Board name", + deleteBoardButton: "Delete board and all tasks", - /// + /// - taskSettingsHeadline: "Edit Task", + taskSettingsHeadline: "Edit Task", - taskNameLabel: "Title", - taskBoardLabel: "Board", + taskNameLabel: "Title", + taskBoardLabel: "Board", - taskCategoryLabel: "Category", - taskStatusLabel: "Status", - taskPriorityLabel: "Priority", + taskCategoryLabel: "Category", + taskStatusLabel: "Status", + taskPriorityLabel: "Priority", - taskDescriptionLabel: "Description", + taskDescriptionLabel: "Description", - taskDateLabel: "Date", - taskTimeLabel: "Time", + taskDateLabel: "Date", + taskTimeLabel: "Time", - deleteTaskButton: "Delete task", + deleteTaskButton: "Delete task", - /// + /// - filterTasksHeadline: "Filter Tasks", + filterTasksHeadline: "Filter Tasks", - /// + /// - renameCategoryInputPlaceholder: "Rename category", - renameStatusInputPlaceholder: "Rename status", - }, + renameCategoryInputPlaceholder: "Rename category", + renameStatusInputPlaceholder: "Rename status", + }, - calendar: { - eventsBoard: "Events", + calendar: { + eventsBoard: "Events", - /// + /// - todayButtonAudioLabel: "go to today", + todayButtonAudioLabel: "go to today", - previousMonthButtonAudioLabel: "previous month", - nextMonthButtonAudioLabel: "next month", + previousMonthButtonAudioLabel: "previous month", + nextMonthButtonAudioLabel: "next month", - yearInputAudioLabel: "year", - monthInputAudioLabel: "month", + yearInputAudioLabel: "year", + monthInputAudioLabel: "month", - yearInputPlaceholder: "2000", - monthInputPlaceholder: "01", + yearInputPlaceholder: "2000", + monthInputPlaceholder: "01", - /// + /// - searchEventsHeadline: "Search Events", + searchEventsHeadline: "Search Events", - /// + /// - events: "Events", - noEvents: "No events", - }, + events: "Events", + noEvents: "No events", + }, }, }; @@ -342,29 +345,29 @@ export const allTranslations: { en: englishTranslations, de: { - updater: { - migrated: "Migriert", - }, + updater: { + migrated: "Migriert", + }, - general: { - deleteItemButtonAudioLabel: "element löschen", - searchButtonAudioLabel: "suchen", - searchButtonClearAudioLabel: "suche zurücksetzen", + general: { + deleteItemButtonAudioLabel: "element löschen", + searchButtonAudioLabel: "suchen", + searchButtonClearAudioLabel: "suche zurücksetzen", - abortButton: "Abbrechen", - applyButton: "Anwenden", - backButton: "Zurück", - cancelButton: "Abbrechen", - closeButton: "Schließen", - deleteButton: "Löschen", - exitButton: "Schließen", - fullscreenButton: "Vollbild", + abortButton: "Abbrechen", + applyButton: "Anwenden", + backButton: "Zurück", + cancelButton: "Abbrechen", + continueButton: "Weiter", + confirmButton: "Bestätigen", + closeButton: "Schließen", + deleteButton: "Löschen", + exitButton: "Schließen", + fullscreenButton: "Vollbild", + refreshButton: "Aktualisieren", + saveButton: "Speichern", + setButton: "OK", - continueButton: "Weiter", - confirmButton: "Bestätigen", - saveButton: "Speichern", - setButton: "OK", - filterOrCreateLabel: "Suchen oder erstellen", createLabel: (query: string) => `"${query}" erstellen`, @@ -413,7 +416,7 @@ export const allTranslations: { settingsButton: "Einstellungen", manageStorageButton: "Daten verwalten", transferDataButton: "Daten übertragen", - + updateButton: (version: string) => `Aktualisieren: ${version}`, scrollToChatButton: "Chats", @@ -502,6 +505,9 @@ export const allTranslations: { notAFile: "(keine Datei)", contentEmpty: "(leer)", + usageLabel: "Speicher", + usageVauleLabel: (used: number, max: number) => `${used} von ${max} MB belegt`, + path: "Pfad", content: "Inhalt", @@ -578,7 +584,7 @@ export const allTranslations: { attentionReaction: "Reaktion: Ausrufezeichen", doubleAttentionReaction: "Reaktion: doppeltes Ausrufezeichen", questionReaction: "Reaktion: Fragezeichen", - + replyPrefixLabel: "Antworten: ", replyHeaderLabel: (message: string) => `Antworten an "${message}"`, }, @@ -662,13 +668,13 @@ export const allTranslations: { applyButton: "Guardar", backButton: "Atrás", cancelButton: "Cancelar", + continueButton: "Continuar", + confirmButton: "Confirmar", closeButton: "Cerrar", deleteButton: "Borrar", exitButton: "Salir", fullscreenButton: "Pantalla completa", - - continueButton: "Continuar", - confirmButton: "Confirmar", + refreshButton: "Actualizar", saveButton: "Guardar", setButton: "OK", @@ -720,7 +726,7 @@ export const allTranslations: { settingsButton: "Ajustes", manageStorageButton: "Gestionar almacenamiento", transferDataButton: "Enviar o exportar archivos", - + updateButton: (version: string) => `Actualizar a ${version}`, scrollToChatButton: "Chats", @@ -808,6 +814,9 @@ export const allTranslations: { notAFile: "(no es un archivo)", contentEmpty: "(vacío)", + usageLabel: "Almacenamiento", + usageVauleLabel: (used: number, max: number) => `${used} de ${max} MB en uso`, + path: "Ruta", content: "Contenido", diff --git a/src/ViewModel/Global/storageViewModel.ts b/src/ViewModel/Global/storageViewModel.ts index 4e31623e..ba31d44d 100644 --- a/src/ViewModel/Global/storageViewModel.ts +++ b/src/ViewModel/Global/storageViewModel.ts @@ -13,6 +13,9 @@ export default class StorageViewModel extends Context { ); didMakeChanges: React.State = new React.State(false); + occupiedSpaceMB: React.State = new React.State(0); + maximumSpaceMB: React.State = new React.State(0); + selectedFileName: React.State; selectedFileContent: React.State; @@ -46,10 +49,17 @@ export default class StorageViewModel extends Context { this.selectedPath.value = PATH_COMPONENT_SEPARATOR; }; + calculateUsage = (): void => { + this.occupiedSpaceMB.value = this.coreViewModel.storageModel.calculateUsage(); + this.maximumSpaceMB.value = this.coreViewModel.storageModel.determineCapacity(); + console.log(this.occupiedSpaceMB.value, this.maximumSpaceMB.value); + } + // view showStorageModal = (): void => { this.coreViewModel.context = this; this.isShowingStorageModal.value = true; + this.calculateUsage(); }; // exit