feat: basic view api

This commit is contained in:
lawvs 2022-07-18 19:09:34 +08:00
parent 6597051e9a
commit 94b7f77f8f
2 changed files with 126 additions and 1 deletions

View File

@ -10,7 +10,15 @@ export enum RecastScene {
Whiteboard = 'whiteboard',
}
export type RecastViewId = string & {
/**
* Type differentiator only.
*/
readonly __isViewId: true;
};
type BaseView = {
id: RecastViewId;
name: string;
// TODO: design this
// order?: string[];
@ -25,4 +33,8 @@ export interface KanbanView extends BaseView {
groupBy: RecastPropertyId;
}
export type RecastView = PageView | KanbanView;
export interface TableView extends BaseView {
type: RecastScene.Kanban;
}
export type RecastView = PageView | KanbanView | TableView;

View File

@ -0,0 +1,113 @@
import { nanoid } from 'nanoid';
import { useCallback } from 'react';
import { useRecastBlock } from './Context';
import { META_VIEWS_KEY, RecastScene, RecastView, RecastViewId } from './types';
/**
* Generate a unique id for a recast view
*/
const genViewId = () => nanoid(16) as RecastViewId; // This is a safe type cast
const DEFAULT_VIEWS: RecastView[] = [
{
id: genViewId(),
name: 'ToDo List',
type: RecastScene.Page,
},
{
id: genViewId(),
name: 'Kanban',
type: RecastScene.Kanban,
},
];
export const useRecastView = () => {
const recastBlock = useRecastBlock();
const recastViews = recastBlock.getProperty(META_VIEWS_KEY) ?? [];
const getView = useCallback(
(id: RecastViewId) => {
const view = recastViews.find(v => v.id === id);
if (!view) {
throw new Error('Failed to find view with id ' + id);
}
return view;
},
[recastViews]
);
const setViews = useCallback(
(views: RecastView[]) => {
return recastBlock.setProperty(META_VIEWS_KEY, views);
},
[recastBlock]
);
const addView = useCallback(
async (newView: Omit<RecastView, 'id'>) => {
await setViews([
...recastViews,
{ ...newView, id: genViewId() } as RecastView,
]);
},
[recastViews, setViews]
);
const updateView = useCallback(
async (newView: RecastView) => {
const idx = recastViews.findIndex(v => v.id === newView.id);
if (!idx) {
throw new Error('Failed to find view with id ' + newView.id);
}
await setViews([
...recastViews.slice(0, idx),
newView,
...recastViews.slice(idx + 1),
]);
},
[recastViews, setViews]
);
const renameView = useCallback(
async (id: RecastViewId, newName: string) => {
const curView = getView(id);
curView.name = newName;
await setViews(recastViews);
},
[getView, recastViews, setViews]
);
const removeView = useCallback(
async (id: RecastViewId) => {
await setViews(recastViews.filter(v => v.id !== id));
},
[recastViews, setViews]
);
/**
* @deprecated Use updateView instead
*/
const changeScene = useCallback(
async (
id: RecastViewId,
newScene: RecastScene.Page | RecastScene.Kanban
) => {
const curView = getView(id);
if (curView.type === newScene) {
return;
}
curView.type = newScene;
await setViews(recastViews);
},
[getView, recastViews, setViews]
);
return {
recastViews,
addView,
updateView,
renameView,
removeView,
// TODO API to reorder views
};
};