sync.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { Updater } from "../typing";
  2. import { ApiPath, StoreKey } from "../constant";
  3. import { createPersistStore } from "../utils/store";
  4. import {
  5. AppState,
  6. getLocalAppState,
  7. GetStoreState,
  8. mergeAppState,
  9. setLocalAppState,
  10. } from "../utils/sync";
  11. import { downloadAs, readFromFile } from "../utils";
  12. import { showToast } from "../components/ui-lib";
  13. import Locale from "../locales";
  14. import { createSyncClient, ProviderType } from "../utils/cloud";
  15. import { corsPath } from "../utils/cors";
  16. export interface WebDavConfig {
  17. server: string;
  18. username: string;
  19. password: string;
  20. }
  21. export type SyncStore = GetStoreState<typeof useSyncStore>;
  22. export const useSyncStore = createPersistStore(
  23. {
  24. provider: ProviderType.WebDAV,
  25. useProxy: true,
  26. proxyUrl: corsPath(ApiPath.Cors),
  27. webdav: {
  28. endpoint: "",
  29. username: "",
  30. password: "",
  31. },
  32. upstash: {
  33. endpoint: "",
  34. username: "",
  35. apiKey: "",
  36. },
  37. lastSyncTime: 0,
  38. lastProvider: "",
  39. },
  40. (set, get) => ({
  41. coundSync() {
  42. const config = get()[get().provider];
  43. return Object.values(config).every((c) => c.toString().length > 0);
  44. },
  45. markSyncTime() {
  46. set({ lastSyncTime: Date.now(), lastProvider: get().provider });
  47. },
  48. export() {
  49. const state = getLocalAppState();
  50. const fileName = `Backup-${new Date().toLocaleString()}.json`;
  51. downloadAs(JSON.stringify(state), fileName);
  52. },
  53. async import() {
  54. const rawContent = await readFromFile();
  55. try {
  56. const remoteState = JSON.parse(rawContent) as AppState;
  57. const localState = getLocalAppState();
  58. mergeAppState(localState, remoteState);
  59. setLocalAppState(localState);
  60. location.reload();
  61. } catch (e) {
  62. console.error("[Import]", e);
  63. showToast(Locale.Settings.Sync.ImportFailed);
  64. }
  65. },
  66. getClient() {
  67. const provider = get().provider;
  68. const client = createSyncClient(provider, get());
  69. return client;
  70. },
  71. async sync() {
  72. const localState = getLocalAppState();
  73. const provider = get().provider;
  74. const config = get()[provider];
  75. const client = this.getClient();
  76. try {
  77. const remoteState = JSON.parse(
  78. await client.get(config.username),
  79. ) as AppState;
  80. mergeAppState(localState, remoteState);
  81. setLocalAppState(localState);
  82. } catch (e) {
  83. console.log("[Sync] failed to get remoate state", e);
  84. }
  85. await client.set(config.username, JSON.stringify(localState));
  86. this.markSyncTime();
  87. },
  88. async check() {
  89. const client = this.getClient();
  90. return await client.check();
  91. },
  92. }),
  93. {
  94. name: StoreKey.Sync,
  95. version: 1,
  96. },
  97. );