ruban 1 tahun lalu
induk
melakukan
7b61d05e88
1 mengubah file dengan 160 tambahan dan 4 penghapusan
  1. 160 4
      app/store/sync.ts

+ 160 - 4
app/store/sync.ts

@@ -99,24 +99,22 @@ export const useSyncStore = createPersistStore(
       try {
         const remoteState = await client.get(config.username);
         if (!remoteState || remoteState === "") {
+          await client.set(config.username, JSON.stringify(localState));
           console.log("[Sync] Remote state is empty, using local state instead.");
           return
         } else {
           const parsedRemoteState = JSON.parse(
             await client.get(config.username),
           ) as AppState;
-
           mergeAppState(localState, parsedRemoteState);
           setLocalAppState(localState);
-        }
-        
+       } 
       } catch (e) {
         console.log("[Sync] failed to get remote state", e);
         throw e;
       }
     
       await client.set(config.username, JSON.stringify(localState));
-      console.log("client set", localState);
       this.markSyncTime();
     },    
 
@@ -149,3 +147,161 @@ export const useSyncStore = createPersistStore(
     },
   },
 );
+
+```
+
+**Output:**
+<!-- prettier-ignore -->
+```tsx
+import { getClientConfig } from "../config/client";
+import { Updater } from "../typing";
+import { ApiPath, STORAGE_KEY, StoreKey } from "../constant";
+import { createPersistStore } from "../utils/store";
+import {
+  AppState,
+  getLocalAppState,
+  GetStoreState,
+  mergeAppState,
+  setLocalAppState,
+} from "../utils/sync";
+import { downloadAs, readFromFile } from "../utils";
+import { showToast } from "../components/ui-lib";
+import Locale from "../locales";
+import { createSyncClient, ProviderType } from "../utils/cloud";
+import { corsPath } from "../utils/cors";
+
+export interface WebDavConfig {
+  server: string;
+  username: string;
+  password: string;
+}
+
+const isApp = !!getClientConfig()?.isApp;
+export type SyncStore = GetStoreState<typeof useSyncStore>;
+
+const DEFAULT_SYNC_STATE = {
+  provider: ProviderType.WebDAV,
+  useProxy: true,
+  proxyUrl: corsPath(ApiPath.Cors),
+
+  webdav: {
+    endpoint: "",
+    username: "",
+    password: "",
+  },
+
+  upstash: {
+    endpoint: "",
+    username: STORAGE_KEY,
+    apiKey: "",
+  },
+
+  lastSyncTime: 0,
+  lastProvider: "",
+};
+
+export const useSyncStore = createPersistStore(
+  DEFAULT_SYNC_STATE,
+  (set, get) => ({
+    cloudSync() {
+      const config = get()[get().provider];
+      return Object.values(config).every((c) => c.toString().length > 0);
+    },
+
+    markSyncTime() {
+      set({ lastSyncTime: Date.now(), lastProvider: get().provider });
+    },
+
+    export() {
+      const state = getLocalAppState();
+      const datePart = isApp
+        ? `${new Date().toLocaleDateString().replace(/\//g, "_")} ${new Date()
+            .toLocaleTimeString()
+            .replace(/:/g, "_")}`
+        : new Date().toLocaleString();
+
+      const fileName = `Backup-${datePart}.json`;
+      downloadAs(JSON.stringify(state), fileName);
+    },
+
+    async import() {
+      const rawContent = await readFromFile();
+
+      try {
+        const remoteState = JSON.parse(rawContent) as AppState;
+        const localState = getLocalAppState();
+        mergeAppState(localState, remoteState);
+        setLocalAppState(localState);
+        location.reload();
+      } catch (e) {
+        console.error("[Import]", e);
+        showToast(Locale.Settings.Sync.ImportFailed);
+      }
+    },
+
+    getClient() {
+      const provider = get().provider;
+      const client = createSyncClient(provider, get());
+      return client;
+    },
+
+    async sync() {
+      const localState = getLocalAppState();
+      const provider = get().provider;
+      const config = get()[provider];
+      const client = this.getClient();
+
+      try {
+        const remoteState = await client.get(config.username);
+        if (!remoteState || remoteState === "") {
+          console.log(
+            "[Sync] Remote state is empty, using local state instead.",
+          );
+          return;
+        } else {
+          const parsedRemoteState = JSON.parse(
+            await client.get(config.username),
+          ) as AppState;
+
+          mergeAppState(localState, parsedRemoteState);
+          setLocalAppState(localState);
+        }
+      } catch (e) {
+        console.log("[Sync] failed to get remote state", e);
+        throw e;
+      }
+
+      await client.set(config.username, JSON.stringify(localState));
+      console.log("client set", localState);
+      this.markSyncTime();
+    },
+
+    async check() {
+      const client = this.getClient();
+      return await client.check();
+    },
+  }),
+  {
+    name: StoreKey.Sync,
+    version: 1.2,
+
+    migrate(persistedState, version) {
+      const newState = persistedState as typeof DEFAULT_SYNC_STATE;
+
+      if (version < 1.1) {
+        newState.upstash.username = STORAGE_KEY;
+      }
+
+      if (version < 1.2) {
+        if (
+          (persistedState as typeof DEFAULT_SYNC_STATE).proxyUrl ===
+          "/api/cors/"
+        ) {
+          newState.proxyUrl = "";
+        }
+      }
+
+      return newState as any;
+    },
+  },
+);