aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/web-util/src/hooks/index.ts6
-rw-r--r--packages/web-util/src/hooks/useLocalStorage.ts2
-rw-r--r--packages/web-util/src/hooks/useMemoryStorage.ts75
-rw-r--r--packages/web-util/src/hooks/useNotifications.ts67
4 files changed, 149 insertions, 1 deletions
diff --git a/packages/web-util/src/hooks/index.ts b/packages/web-util/src/hooks/index.ts
index e5cb54e21..ae8872497 100644
--- a/packages/web-util/src/hooks/index.ts
+++ b/packages/web-util/src/hooks/index.ts
@@ -1,5 +1,11 @@
export { useLang } from "./useLang.js";
export { useLocalStorage } from "./useLocalStorage.js";
+export { useMemoryStorage } from "./useMemoryStorage.js";
+export {
+ useNotifications,
+ notifyError,
+ notifyInfo,
+} from "./useNotifications.js";
export {
useAsyncAsHook,
HookError,
diff --git a/packages/web-util/src/hooks/useLocalStorage.ts b/packages/web-util/src/hooks/useLocalStorage.ts
index 495c9b0f8..131825736 100644
--- a/packages/web-util/src/hooks/useLocalStorage.ts
+++ b/packages/web-util/src/hooks/useLocalStorage.ts
@@ -70,7 +70,7 @@ export function useLocalStorage(
}, []);
const setValue = (value?: string): void => {
- if (!value) {
+ if (value === undefined) {
storage.delete(key);
} else {
storage.set(key, value);
diff --git a/packages/web-util/src/hooks/useMemoryStorage.ts b/packages/web-util/src/hooks/useMemoryStorage.ts
new file mode 100644
index 000000000..7160b035e
--- /dev/null
+++ b/packages/web-util/src/hooks/useMemoryStorage.ts
@@ -0,0 +1,75 @@
+/*
+ This file is part of GNU Anastasis
+ (C) 2021-2022 Anastasis SARL
+
+ GNU Anastasis is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useEffect, useState } from "preact/hooks";
+import {
+ ObservableMap,
+ browserStorageMap,
+ localStorageMap,
+ memoryMap,
+} from "../utils/observable.js";
+
+export interface LocalStorageState {
+ value?: string;
+ update: (s: string) => void;
+ reset: () => void;
+}
+
+const storage: ObservableMap<string, string> = memoryMap<string>();
+
+export function useMemoryStorage(
+ key: string,
+ initialValue: string,
+): Required<LocalStorageState>;
+export function useMemoryStorage(key: string): LocalStorageState;
+export function useMemoryStorage(
+ key: string,
+ initialValue?: string,
+): LocalStorageState {
+ const [storedValue, setStoredValue] = useState<string | undefined>(
+ (): string | undefined => {
+ return storage.get(key) ?? initialValue;
+ },
+ );
+
+ useEffect(() => {
+ return storage.onUpdate(key, () => {
+ const newValue = storage.get(key);
+ setStoredValue(newValue ?? initialValue);
+ });
+ }, []);
+
+ const setValue = (value?: string): void => {
+ if (value === undefined) {
+ storage.delete(key);
+ } else {
+ storage.set(key, value);
+ }
+ };
+
+ return {
+ value: storedValue,
+ update: setValue,
+ reset: () => {
+ setValue(initialValue);
+ },
+ };
+}
diff --git a/packages/web-util/src/hooks/useNotifications.ts b/packages/web-util/src/hooks/useNotifications.ts
new file mode 100644
index 000000000..deaa7a7c1
--- /dev/null
+++ b/packages/web-util/src/hooks/useNotifications.ts
@@ -0,0 +1,67 @@
+import { TranslatedString } from "@gnu-taler/taler-util";
+import { StateUpdater, useEffect, useState } from "preact/hooks";
+import { memoryMap } from "../index.browser.js";
+
+export type NotificationMessage = ErrorNotification | InfoNotification;
+
+interface ErrorNotification {
+ type: "error";
+ title: TranslatedString;
+ description?: TranslatedString;
+ debug?: string;
+}
+interface InfoNotification {
+ type: "info";
+ title: TranslatedString;
+}
+
+const storage = memoryMap<NotificationMessage[]>();
+const NOTIFICATION_KEY = "notification";
+
+export function notifyError(
+ title: TranslatedString,
+ description: TranslatedString | undefined,
+ debug?: any,
+) {
+ const currentState: NotificationMessage[] =
+ storage.get(NOTIFICATION_KEY) ?? [];
+ const newState = currentState.concat({
+ type: "error",
+ title,
+ description,
+ debug,
+ });
+ storage.set(NOTIFICATION_KEY, newState);
+}
+export function notifyInfo(title: TranslatedString) {
+ const currentState: NotificationMessage[] =
+ storage.get(NOTIFICATION_KEY) ?? [];
+ const newState = currentState.concat({ type: "info", title });
+ storage.set(NOTIFICATION_KEY, newState);
+}
+
+type Notification = {
+ message: NotificationMessage;
+ remove: () => void;
+};
+
+export function useNotifications(): Notification[] {
+ const [value, setter] = useState<NotificationMessage[]>([]);
+ useEffect(() => {
+ return storage.onUpdate(NOTIFICATION_KEY, () => {
+ const mem = storage.get(NOTIFICATION_KEY) ?? [];
+ setter(mem);
+ });
+ });
+ return value.map((message, idx) => {
+ return {
+ message,
+ remove: () => {
+ const mem = storage.get(NOTIFICATION_KEY) ?? [];
+ const newState = Array.from(mem);
+ newState.splice(idx, 1);
+ storage.set(NOTIFICATION_KEY, newState);
+ },
+ };
+ });
+}