feat: support offline mode for affine workspace (#1322)
This commit is contained in:
@@ -26,9 +26,36 @@ const schema = z.object({
|
|||||||
type: z.number(),
|
type: z.number(),
|
||||||
public: z.boolean(),
|
public: z.boolean(),
|
||||||
permission: z.number(),
|
permission: z.number(),
|
||||||
create_at: z.number(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getPersistenceAllWorkspace = () => {
|
||||||
|
const items = storage.getItem(kAffineLocal);
|
||||||
|
const allWorkspaces: AffineWorkspace[] = [];
|
||||||
|
if (
|
||||||
|
Array.isArray(items) &&
|
||||||
|
items.every(item => schema.safeParse(item).success)
|
||||||
|
) {
|
||||||
|
allWorkspaces.push(
|
||||||
|
...items.map((item: z.infer<typeof schema>) => {
|
||||||
|
const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace(
|
||||||
|
item.id,
|
||||||
|
(k: string) =>
|
||||||
|
// fixme: token could be expired
|
||||||
|
({ api: '/api/workspace', token: apis.auth.token }[k])
|
||||||
|
);
|
||||||
|
const affineWorkspace: AffineWorkspace = {
|
||||||
|
...item,
|
||||||
|
flavour: RemWorkspaceFlavour.AFFINE,
|
||||||
|
blockSuiteWorkspace,
|
||||||
|
providers: [...createAffineProviders(blockSuiteWorkspace)],
|
||||||
|
};
|
||||||
|
return affineWorkspace;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return allWorkspaces;
|
||||||
|
};
|
||||||
|
|
||||||
export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
|
export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
|
||||||
flavour: RemWorkspaceFlavour.AFFINE,
|
flavour: RemWorkspaceFlavour.AFFINE,
|
||||||
loadPriority: LoadPriority.HIGH,
|
loadPriority: LoadPriority.HIGH,
|
||||||
@@ -38,57 +65,117 @@ export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
|
|||||||
blockSuiteWorkspace.doc
|
blockSuiteWorkspace.doc
|
||||||
);
|
);
|
||||||
const { id } = await apis.createWorkspace(new Blob([binary.buffer]));
|
const { id } = await apis.createWorkspace(new Blob([binary.buffer]));
|
||||||
|
// refresh the local storage
|
||||||
|
await AffinePlugin.CRUD.list();
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
delete: async workspace => {
|
delete: async workspace => {
|
||||||
|
const items = storage.getItem(kAffineLocal);
|
||||||
|
if (
|
||||||
|
Array.isArray(items) &&
|
||||||
|
items.every(item => schema.safeParse(item).success)
|
||||||
|
) {
|
||||||
|
storage.setItem(
|
||||||
|
kAffineLocal,
|
||||||
|
items.filter(item => item.id !== workspace.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
await apis.deleteWorkspace({
|
await apis.deleteWorkspace({
|
||||||
id: workspace.id,
|
id: workspace.id,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
get: async workspaceId => {
|
get: async workspaceId => {
|
||||||
const workspaces: AffineWorkspace[] = await preload(
|
try {
|
||||||
QueryKey.getWorkspaces,
|
if (!apis.auth.isLogin) {
|
||||||
fetcher
|
const workspaces = getPersistenceAllWorkspace();
|
||||||
);
|
return (
|
||||||
|
workspaces.find(workspace => workspace.id === workspaceId) ?? null
|
||||||
const workspace = workspaces.find(
|
);
|
||||||
workspace => workspace.id === workspaceId
|
}
|
||||||
);
|
const workspaces: AffineWorkspace[] = await preload(
|
||||||
const dump = workspaces.map(workspace => {
|
QueryKey.getWorkspaces,
|
||||||
return {
|
fetcher
|
||||||
id: workspace.id,
|
);
|
||||||
type: workspace.type,
|
return (
|
||||||
public: workspace.public,
|
workspaces.find(workspace => workspace.id === workspaceId) ?? null
|
||||||
permission: workspace.permission,
|
);
|
||||||
create_at: workspace.create_at,
|
} catch (e) {
|
||||||
} satisfies z.infer<typeof schema>;
|
const workspaces = getPersistenceAllWorkspace();
|
||||||
});
|
return (
|
||||||
storage.setItem(kAffineLocal, dump);
|
workspaces.find(workspace => workspace.id === workspaceId) ?? null
|
||||||
if (!workspace) {
|
);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return workspace;
|
|
||||||
},
|
},
|
||||||
list: async () => {
|
list: async () => {
|
||||||
// fixme: refactor auth check
|
const allWorkspaces = getPersistenceAllWorkspace();
|
||||||
if (!apis.auth.isLogin) return [];
|
try {
|
||||||
return await apis.getWorkspaces().then(workspaces => {
|
if (apis.auth.isLogin) {
|
||||||
return workspaces.map(workspace => {
|
const workspaces = await apis.getWorkspaces().then(workspaces => {
|
||||||
const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace(
|
return workspaces.map(workspace => {
|
||||||
workspace.id,
|
const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace(
|
||||||
(k: string) =>
|
workspace.id,
|
||||||
// fixme: token could be expired
|
(k: string) =>
|
||||||
({ api: '/api/workspace', token: apis.auth.token }[k])
|
// fixme: token could be expired
|
||||||
);
|
({ api: '/api/workspace', token: apis.auth.token }[k])
|
||||||
const affineWorkspace: AffineWorkspace = {
|
);
|
||||||
...workspace,
|
const dump = workspaces.map(workspace => {
|
||||||
flavour: RemWorkspaceFlavour.AFFINE,
|
return {
|
||||||
blockSuiteWorkspace,
|
id: workspace.id,
|
||||||
providers: [...createAffineProviders(blockSuiteWorkspace)],
|
type: workspace.type,
|
||||||
};
|
public: workspace.public,
|
||||||
return affineWorkspace;
|
permission: workspace.permission,
|
||||||
});
|
} satisfies z.infer<typeof schema>;
|
||||||
});
|
});
|
||||||
|
const old = storage.getItem(kAffineLocal);
|
||||||
|
if (
|
||||||
|
Array.isArray(old) &&
|
||||||
|
old.every(item => schema.safeParse(item).success)
|
||||||
|
) {
|
||||||
|
const data = [...dump];
|
||||||
|
old.forEach((item: z.infer<typeof schema>) => {
|
||||||
|
const has = dump.find(dump => dump.id === item.id);
|
||||||
|
if (!has) {
|
||||||
|
data.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
storage.setItem(kAffineLocal, [...data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const affineWorkspace: AffineWorkspace = {
|
||||||
|
...workspace,
|
||||||
|
flavour: RemWorkspaceFlavour.AFFINE,
|
||||||
|
blockSuiteWorkspace,
|
||||||
|
providers: [...createAffineProviders(blockSuiteWorkspace)],
|
||||||
|
};
|
||||||
|
return affineWorkspace;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
workspaces.forEach(workspace => {
|
||||||
|
const idx = allWorkspaces.findIndex(
|
||||||
|
({ id }) => id === workspace.id
|
||||||
|
);
|
||||||
|
if (idx !== -1) {
|
||||||
|
allWorkspaces.splice(idx, 1, workspace);
|
||||||
|
} else {
|
||||||
|
allWorkspaces.push(workspace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// only save data when login in
|
||||||
|
const dump = allWorkspaces.map(workspace => {
|
||||||
|
return {
|
||||||
|
id: workspace.id,
|
||||||
|
type: workspace.type,
|
||||||
|
public: workspace.public,
|
||||||
|
permission: workspace.permission,
|
||||||
|
} satisfies z.infer<typeof schema>;
|
||||||
|
});
|
||||||
|
storage.setItem(kAffineLocal, [...dump]);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('fetch affine workspaces failed', e);
|
||||||
|
}
|
||||||
|
return [...allWorkspaces];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PageDetail: ({ currentWorkspace, currentPageId }) => {
|
PageDetail: ({ currentWorkspace, currentPageId }) => {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export interface Workspace {
|
|||||||
type: WorkspaceType;
|
type: WorkspaceType;
|
||||||
public: boolean;
|
public: boolean;
|
||||||
permission: PermissionType;
|
permission: PermissionType;
|
||||||
create_at: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkspaceDetail extends Workspace {
|
export interface WorkspaceDetail extends Workspace {
|
||||||
|
|||||||
Reference in New Issue
Block a user