feat: add webdav support

This commit is contained in:
Yidadaa
2023-09-13 02:51:02 +08:00
parent 89bc98d26b
commit 6f83fbd212
16 changed files with 751 additions and 104 deletions

View File

@@ -1,15 +1,18 @@
import { Updater } from "../typing";
import { StoreKey } from "../constant";
import { ApiPath, 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;
@@ -17,22 +20,43 @@ export interface WebDavConfig {
password: string;
}
export type SyncStore = GetStoreState<typeof useSyncStore>;
export const useSyncStore = createPersistStore(
{
webDavConfig: {
server: "",
provider: ProviderType.WebDAV,
useProxy: true,
proxyUrl: corsPath(ApiPath.Cors),
webdav: {
endpoint: "",
username: "",
password: "",
},
upstash: {
endpoint: "",
username: "",
apiKey: "",
},
lastSyncTime: 0,
lastProvider: "",
},
(set, get) => ({
coundSync() {
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 fileName = `Backup-${new Date().toLocaleString()}.json`;
downloadAs(JSON.stringify(state), fileName);
set({ lastSyncTime: Date.now() });
},
async import() {
@@ -50,47 +74,36 @@ export const useSyncStore = createPersistStore(
}
},
async check() {
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 res = await fetch(this.path(""), {
method: "PROFIND",
headers: this.headers(),
});
const sanitizedRes = {
status: res.status,
statusText: res.statusText,
headers: res.headers,
};
console.log(sanitizedRes);
return res.status === 207;
const remoteState = JSON.parse(
await client.get(config.username),
) as AppState;
mergeAppState(localState, remoteState);
setLocalAppState(localState);
} catch (e) {
console.error("[Sync] ", e);
return false;
console.log("[Sync] failed to get remoate state", e);
}
await client.set(config.username, JSON.stringify(localState));
this.markSyncTime();
},
path(path: string) {
let url = get().webDavConfig.server;
if (!url.endsWith("/")) {
url += "/";
}
if (path.startsWith("/")) {
path = path.slice(1);
}
return url + path;
},
headers() {
const auth = btoa(
[get().webDavConfig.username, get().webDavConfig.password].join(":"),
);
return {
Authorization: `Basic ${auth}`,
};
async check() {
const client = this.getClient();
return await client.check();
},
}),
{