gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: restore and save session


From: gnunet
Subject: [taler-wallet-core] branch master updated: restore and save session
Date: Wed, 24 Nov 2021 21:39:09 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new f49df12b restore and save session
f49df12b is described below

commit f49df12b441a2bd06520df42ddd41fc42f639147
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed Nov 24 17:38:39 2021 -0300

    restore and save session
---
 .../anastasis-webui/src/components/FlieButton.tsx  | 57 ++++++++++++++++++++++
 .../src/components/menu/SideBar.tsx                | 28 +++++++++++
 .../src/hooks/use-anastasis-reducer.ts             | 22 +++++++--
 .../anastasis-webui/src/pages/home/StartScreen.tsx | 11 +++++
 4 files changed, 114 insertions(+), 4 deletions(-)

diff --git a/packages/anastasis-webui/src/components/FlieButton.tsx 
b/packages/anastasis-webui/src/components/FlieButton.tsx
new file mode 100644
index 00000000..aab0b617
--- /dev/null
+++ b/packages/anastasis-webui/src/components/FlieButton.tsx
@@ -0,0 +1,57 @@
+import { h, VNode } from "preact";
+import { useRef, useState } from "preact/hooks";
+
+const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024;
+
+export interface FileTypeContent {
+  content: string;
+  type: string;
+  name: string;
+}
+
+interface Props {
+  label: string;
+  onChange: (v: FileTypeContent | undefined) => void;
+}
+export function FileButton(props: Props): VNode {
+  const fileInputRef = useRef<HTMLInputElement>(null);
+  const [sizeError, setSizeError] = useState(false);
+  return (
+    <div>
+      <button class="button" onClick={(e) => fileInputRef.current?.click()}>
+        <span>{props.label}</span>
+      </button>
+      <input
+        ref={fileInputRef}
+        style={{ display: "none" }}
+        type="file"
+        onChange={(e) => {
+          const f: FileList | null = e.currentTarget.files;
+          if (!f || f.length != 1) {
+            return props.onChange(undefined);
+          }
+          console.log(f);
+          if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
+            setSizeError(true);
+            return props.onChange(undefined);
+          }
+          setSizeError(false);
+          return f[0].arrayBuffer().then((b) => {
+            const content = new Uint8Array(b).reduce(
+              (data, byte) => data + String.fromCharCode(byte),
+              "",
+            );
+            return props.onChange({
+              content,
+              name: f[0].name,
+              type: f[0].type,
+            });
+          });
+        }}
+      />
+      {sizeError && (
+        <p class="help is-danger">File should be smaller than 1 MB</p>
+      )}
+    </div>
+  );
+}
diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx 
b/packages/anastasis-webui/src/components/menu/SideBar.tsx
index c73369dd..6c8189fb 100644
--- a/packages/anastasis-webui/src/components/menu/SideBar.tsx
+++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx
@@ -36,6 +36,14 @@ export function Sidebar({ mobile }: Props): VNode {
   const process = { env: { __VERSION__: "0.0.0" } };
   const reducer = useAnastasisContext()!;
 
+  function saveSession(): void {
+    const state = reducer.exportState();
+    const link = document.createElement("a");
+    link.download = "anastasis.json";
+    link.href = `data:text/plain,${state}`;
+    link.click();
+  }
+
   return (
     <aside class="aside is-placed-left is-expanded">
       {/* {mobile && <div class="footer" onClick={(e) => { return 
e.stopImmediatePropagation() }}>
@@ -171,6 +179,16 @@ export function Sidebar({ mobile }: Props): VNode {
                 <span class="menu-item-label"><Translate>Truth 
Paying</Translate></span>
               </div>
             </li> */}
+              <li>
+                <div class="buttons ml-4">
+                  <button
+                    class="button is-primary is-right"
+                    onClick={saveSession}
+                  >
+                    Save backup session
+                  </button>
+                </div>
+              </li>
             </Fragment>
           ) : (
             reducer.currentReducerState &&
@@ -250,6 +268,16 @@ export function Sidebar({ mobile }: Props): VNode {
                     </span>
                   </div>
                 </li>
+                <li>
+                  <div class="buttons ml-4">
+                    <button
+                      class="button is-primary is-right"
+                      onClick={saveSession}
+                    >
+                      Save recovery session
+                    </button>
+                  </div>
+                </li>
               </Fragment>
             )
           )}
diff --git a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts 
b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
index 1ef28a16..7b101baa 100644
--- a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
+++ b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
@@ -107,6 +107,8 @@ export interface AnastasisReducerApi {
   reset: () => void;
   back: () => Promise<void>;
   transition(action: string, args: any): Promise<void>;
+  exportState: () => string;
+  importState: (s: string) => void;
   /**
    * Run multiple reducer steps in a transaction without
    * affecting the UI-visible transition state in-between.
@@ -129,7 +131,7 @@ function storageSet(key: string, value: any): void {
   }
 }
 
-function restoreState(): any {
+function getStateFromStorage(): any {
   let state: any;
   try {
     const s = storageGet("anastasisReducerState");
@@ -148,7 +150,7 @@ function restoreState(): any {
 export function useAnastasisReducer(): AnastasisReducerApi {
   const [anastasisState, setAnastasisStateInternal] = useState<AnastasisState>(
     () => ({
-      reducerState: restoreState(),
+      reducerState: getStateFromStorage(),
       currentError: undefined,
     }),
   );
@@ -165,7 +167,7 @@ export function useAnastasisReducer(): AnastasisReducerApi {
     setAnastasisStateInternal(newState);
   };
 
-  async function doTransition(action: string, args: any) {
+  async function doTransition(action: string, args: any): Promise<void> {
     console.log("reducing with", action, args);
     let s: ReducerState;
     if (remoteReducer) {
@@ -210,6 +212,18 @@ export function useAnastasisReducer(): AnastasisReducerApi 
{
         });
       }
     },
+    exportState() {
+      const state = getStateFromStorage()
+      return JSON.stringify(state)
+    },
+    importState(s: string) {
+      try {
+        const state = JSON.parse(s)
+        setAnastasisState({ reducerState: state, currentError: undefined })
+      } catch (e) {
+        throw Error('could not restore the state')
+      }
+    },
     async startRecover() {
       let s: ReducerState;
       if (remoteReducer) {
@@ -287,7 +301,7 @@ export function useAnastasisReducer(): AnastasisReducerApi {
 }
 
 class ReducerTxImpl implements ReducerTransactionHandle {
-  constructor(public transactionState: ReducerState) {}
+  constructor(public transactionState: ReducerState) { }
   async transition(action: string, args: any): Promise<ReducerState> {
     let s: ReducerState;
     if (remoteReducer) {
diff --git a/packages/anastasis-webui/src/pages/home/StartScreen.tsx 
b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
index 8b24ef68..628ae4a3 100644
--- a/packages/anastasis-webui/src/pages/home/StartScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
@@ -1,4 +1,6 @@
 import { h, VNode } from "preact";
+import { FileInput } from "../../components/fields/FileInput";
+import { FileButton } from "../../components/FlieButton";
 import { useAnastasisContext } from "../../context/anastasis";
 import { AnastasisClientFrame } from "./index";
 
@@ -34,6 +36,15 @@ export function StartScreen(): VNode {
               <span>Recover a secret</span>
             </button>
 
+            <FileButton
+              label="Restore a session"
+              onChange={(content) => {
+                if (content?.type === "application/json") {
+                  reducer.importState(content.content);
+                }
+              }}
+            />
+
             {/* <button class="button">
               <div class="icon"><i class="mdi mdi-file" /></div>
               <span>Restore a session</span>

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]