feat(webdav): add WebDAV synchronization configuration and functionality
This commit is contained in:
@@ -28,10 +28,12 @@ type AssetBase<T extends AssetKind> = {
|
||||
};
|
||||
|
||||
type AssetStore = {
|
||||
hydrated: boolean;
|
||||
assets: Asset[];
|
||||
addAsset: (asset: Omit<Asset, "id" | "createdAt" | "updatedAt">) => string;
|
||||
updateAsset: (id: string, patch: Partial<Omit<Asset, "id" | "createdAt">>) => void;
|
||||
removeAsset: (id: string) => void;
|
||||
replaceAssets: (assets: Asset[]) => void;
|
||||
cleanupImages: (extra?: unknown) => void;
|
||||
};
|
||||
|
||||
@@ -66,6 +68,7 @@ const assetStorage: PersistStorage<AssetStore> = {
|
||||
export const useAssetStore = create<AssetStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
hydrated: false,
|
||||
assets: [],
|
||||
addAsset: (asset) => {
|
||||
const now = new Date().toISOString();
|
||||
@@ -83,6 +86,7 @@ export const useAssetStore = create<AssetStore>()(
|
||||
get().cleanupImages({ assets });
|
||||
return { assets };
|
||||
}),
|
||||
replaceAssets: (assets) => set({ assets }),
|
||||
cleanupImages: (extra) => {
|
||||
window.setTimeout(async () => {
|
||||
const { useCanvasStore } = await import("@/app/(user)/canvas/stores/use-canvas-store");
|
||||
@@ -95,6 +99,9 @@ export const useAssetStore = create<AssetStore>()(
|
||||
name: ASSET_STORE_KEY,
|
||||
storage: assetStorage,
|
||||
partialize: (state) => ({ assets: state.assets }) as StorageValue<AssetStore>["state"],
|
||||
onRehydrateStorage: () => () => {
|
||||
useAssetStore.setState({ hydrated: true });
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -36,6 +36,15 @@ export type AiConfig = {
|
||||
canvasImageCount: string;
|
||||
};
|
||||
|
||||
export type WebdavSyncConfig = {
|
||||
proxyMode: "direct" | "nextjs";
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
directory: string;
|
||||
lastSyncedAt: string;
|
||||
};
|
||||
|
||||
export const CONFIG_STORE_KEY = "infinite-canvas:ai_config_store";
|
||||
export type ModelCapability = "image" | "video" | "text" | "audio";
|
||||
|
||||
@@ -68,13 +77,24 @@ export const defaultConfig: AiConfig = {
|
||||
canvasImageCount: "3",
|
||||
};
|
||||
|
||||
export const defaultWebdavSyncConfig: WebdavSyncConfig = {
|
||||
proxyMode: "direct",
|
||||
url: "",
|
||||
username: "",
|
||||
password: "",
|
||||
directory: "infinite-canvas",
|
||||
lastSyncedAt: "",
|
||||
};
|
||||
|
||||
type ConfigStore = {
|
||||
config: AiConfig;
|
||||
webdav: WebdavSyncConfig;
|
||||
publicSettings: AdminPublicSettings | null;
|
||||
isPublicSettingsLoading: boolean;
|
||||
isConfigOpen: boolean;
|
||||
shouldPromptContinue: boolean;
|
||||
updateConfig: <K extends keyof AiConfig>(key: K, value: AiConfig[K]) => void;
|
||||
updateWebdavConfig: <K extends keyof WebdavSyncConfig>(key: K, value: WebdavSyncConfig[K]) => void;
|
||||
loadPublicSettings: () => Promise<void>;
|
||||
isAiConfigReady: (config: AiConfig, model: string) => boolean;
|
||||
openConfigDialog: (shouldPromptContinue?: boolean) => void;
|
||||
@@ -168,6 +188,7 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
config: defaultConfig,
|
||||
webdav: defaultWebdavSyncConfig,
|
||||
publicSettings: null,
|
||||
isPublicSettingsLoading: false,
|
||||
isConfigOpen: false,
|
||||
@@ -179,6 +200,13 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
[key]: value,
|
||||
},
|
||||
})),
|
||||
updateWebdavConfig: (key, value) =>
|
||||
set((state) => ({
|
||||
webdav: {
|
||||
...state.webdav,
|
||||
[key]: value,
|
||||
},
|
||||
})),
|
||||
loadPublicSettings: async () => {
|
||||
if (get().isPublicSettingsLoading) return;
|
||||
set({ isPublicSettingsLoading: true });
|
||||
@@ -195,12 +223,15 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
}),
|
||||
{
|
||||
name: CONFIG_STORE_KEY,
|
||||
partialize: (state) => ({ config: state.config }),
|
||||
partialize: (state) => ({ config: state.config, webdav: state.webdav }),
|
||||
merge: (persisted, current) => {
|
||||
const persistedConfig = ((persisted as Partial<ConfigStore>).config || {}) as Partial<AiConfig>;
|
||||
const persistedState = (persisted || {}) as Partial<ConfigStore>;
|
||||
const persistedConfig = (persistedState.config || {}) as Partial<AiConfig>;
|
||||
const persistedWebdav = (persistedState.webdav || {}) as Partial<WebdavSyncConfig>;
|
||||
const config = { ...defaultConfig, ...persistedConfig };
|
||||
return {
|
||||
...current,
|
||||
webdav: { ...defaultWebdavSyncConfig, ...persistedWebdav },
|
||||
config: {
|
||||
...config,
|
||||
channelMode: config.channelMode || "remote",
|
||||
|
||||
Reference in New Issue
Block a user