-
-
Notifications
You must be signed in to change notification settings - Fork 199
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c1021fe
commit 3420261
Showing
37 changed files
with
856 additions
and
1,386 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
207 changes: 207 additions & 0 deletions
207
src/components/editors/EntityEditor/EntityTree/useEntityTree.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
'use client' | ||
|
||
import { create } from 'zustand' | ||
import { ClapEntity, UUID } from '@aitube/clap' | ||
import { | ||
LibraryTreeNode, | ||
TreeNodeItem, | ||
LibraryNodeType, | ||
} from '@/components/tree-browsers/types' | ||
import { icons } from '@/components/icons' | ||
import { getAppropriateIcon } from '@/components/icons/getAppropriateIcon' | ||
import { | ||
collectionClassName, | ||
libraryClassName, | ||
} from '@/components/tree-browsers/style/treeNodeStyles' | ||
|
||
export const useEntityTree = create<{ | ||
// project entities stored in the .clap | ||
projectLibraryTreeNodeId: string | ||
|
||
// in the future, we are going to put | ||
// <placeholder> | ||
|
||
// entities stored on the public database (Hugging Face datasets, tagged) | ||
communityLibraryTreeNodeId: string | ||
|
||
libraryTreeRoot: LibraryTreeNode[] | ||
init: () => void | ||
|
||
/** | ||
* Load entity collections (characters, locations..) from the clap project into the tree | ||
* | ||
* @param collections | ||
* @returns | ||
*/ | ||
// setProjectLibrary: (collections: ProjectEntityCollection[]) => void | ||
|
||
/** | ||
* Load entity collections (characters, locations..) from the Clapper community into the tree | ||
* | ||
* @param collections | ||
* @returns | ||
*/ | ||
// setCommunityLibrary: (collections: CommunityEntityCollection[]) => void | ||
|
||
// we support those all selection modes for convenience - please keep them! | ||
selectedNodeItem?: TreeNodeItem | ||
selectedNodeType?: LibraryNodeType | ||
selectTreeNode: ( | ||
treeNodeId?: string | null, | ||
nodeType?: LibraryNodeType, | ||
nodeItem?: TreeNodeItem | ||
) => void | ||
selectedTreeNodeId: string | null | ||
}>((set, get) => ({ | ||
// project entities stored in the .clap | ||
projectLibraryTreeNodeId: '', | ||
|
||
// in the future, we are going to put | ||
// <placeholder> | ||
|
||
// entities stored on the public database (Hugging Face datasets, tagged) | ||
communityLibraryTreeNodeId: '', | ||
libraryTreeRoot: [], | ||
init: () => { | ||
const projectLibrary: LibraryTreeNode = { | ||
id: UUID(), | ||
nodeType: 'TREE_ROOT_PROJECT', | ||
label: 'Project entities', | ||
icon: icons.project, | ||
className: libraryClassName, | ||
isExpanded: true, | ||
children: [ | ||
{ | ||
id: UUID(), | ||
nodeType: 'DEFAULT_TREE_NODE_EMPTY', | ||
label: 'Empty', | ||
icon: icons.project, | ||
className: collectionClassName, | ||
}, | ||
], | ||
} | ||
|
||
const communityLibrary: LibraryTreeNode = { | ||
id: UUID(), | ||
nodeType: 'TREE_ROOT_COMMUNITY', | ||
label: 'Community entities', | ||
icon: icons.community, | ||
className: libraryClassName, | ||
children: [ | ||
{ | ||
id: UUID(), | ||
nodeType: 'DEFAULT_TREE_NODE_EMPTY', | ||
label: 'Empty', | ||
icon: icons.community, | ||
className: collectionClassName, | ||
}, | ||
], | ||
} | ||
|
||
const libraryTreeRoot = [projectLibrary, communityLibrary] | ||
|
||
set({ | ||
projectLibraryTreeNodeId: projectLibrary.id, | ||
communityLibraryTreeNodeId: communityLibrary.id, | ||
libraryTreeRoot, | ||
selectedNodeItem: undefined, | ||
selectedTreeNodeId: null, | ||
}) | ||
}, | ||
|
||
/* | ||
setProjectEntities: async (entities: ClapEntity[]) => { | ||
const characters: LibraryTreeNode = { | ||
id: UUID(), | ||
nodeType: 'LIB_NODE_GENERIC_COLLECTION', | ||
data: undefined, | ||
label: 'Characters', | ||
icon: icons.characters, | ||
className: collectionClassName, | ||
isExpanded: true, // This node is expanded by default | ||
children: [], | ||
} | ||
const locations: LibraryTreeNode = { | ||
id: UUID(), | ||
nodeType: 'LIB_NODE_GENERIC_COLLECTION', | ||
data: undefined, | ||
label: 'Locations', | ||
icon: icons.location, | ||
className: collectionClassName, | ||
isExpanded: false, // This node is expanded by default | ||
children: [], | ||
} | ||
const misc: LibraryTreeNode = { | ||
id: UUID(), | ||
nodeType: 'LIB_NODE_GENERIC_COLLECTION', | ||
data: undefined, | ||
label: 'Misc', | ||
icon: icons.misc, | ||
className: collectionClassName, | ||
isExpanded: false, // This node is expanded by default | ||
children: [], | ||
} | ||
entities.forEach((entity) => { | ||
const node: LibraryTreeNode = { | ||
nodeType: TreeNodeEntityItem, | ||
id: entity.id, | ||
data: entity, | ||
label: entity.label, | ||
icon: icons.misc, | ||
className: itemClassName, | ||
} | ||
if (entity.category === ClapSegmentCategory.CHARACTER) { | ||
node.icon = icons.character | ||
characters.children!.push(node) | ||
} else if (entity.category === ClapSegmentCategory.LOCATION) { | ||
node.icon = icons.location | ||
locations.children!.push(node) | ||
} else { | ||
misc.children!.push(node) | ||
} | ||
}) | ||
}, | ||
setCommunityCollections: (collections: CommunityEntityCollection[]) => { | ||
// TODO: implement this | ||
}, | ||
*/ | ||
|
||
selectedNodeItem: undefined, | ||
selectEntity: (entity?: ClapEntity) => { | ||
if (entity) { | ||
console.log( | ||
'TODO julian: change this code to search in the entity collections' | ||
) | ||
const selectedTreeNode = get().libraryTreeRoot.find( | ||
(node) => node.data?.id === entity.id | ||
) | ||
|
||
// set({ selectedTreeNode }) | ||
set({ selectedTreeNodeId: selectedTreeNode?.id || null }) | ||
set({ selectedNodeItem: entity }) | ||
} else { | ||
// set({ selectedTreeNode: undefined }) | ||
set({ selectedTreeNodeId: null }) | ||
set({ selectedNodeItem: undefined }) | ||
} | ||
}, | ||
|
||
// selectedTreeNode: undefined, | ||
selectedTreeNodeId: null, | ||
selectTreeNode: ( | ||
treeNodeId?: string | null, | ||
nodeType?: LibraryNodeType, | ||
nodeItem?: TreeNodeItem | ||
) => { | ||
set({ selectedTreeNodeId: treeNodeId ? treeNodeId : undefined }) | ||
set({ selectedNodeType: nodeType ? nodeType : undefined }) | ||
set({ selectedNodeItem: nodeItem ? nodeItem : undefined }) | ||
}, | ||
})) | ||
|
||
useEntityTree.getState().init() |
65 changes: 65 additions & 0 deletions
65
src/components/editors/EntityEditor/EntityViewer/EntityList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { ClapEntity, ClapSegmentCategory, newEntity } from '@aitube/clap' | ||
import { useTimeline } from '@aitube/timeline' | ||
|
||
import { Button } from '@/components/ui/button' | ||
import { useEntityEditor, useIO } from '@/services' | ||
|
||
export function EntityList({ | ||
onSelectEntity, | ||
}: { | ||
onSelectEntity: (entityId: string) => void | ||
}) { | ||
const entities = useTimeline((s) => s.entities) | ||
const setCurrent = useEntityEditor((s) => s.setCurrent) | ||
const addEntity = useEntityEditor((s) => s.addEntity) | ||
const removeEntity = useEntityEditor((s) => s.removeEntity) | ||
|
||
const handleAddEntity = () => { | ||
const entity: ClapEntity = newEntity({ | ||
id: Date.now().toString(), | ||
label: 'NEW_ENTITY', | ||
category: ClapSegmentCategory.CHARACTER, | ||
description: '', | ||
appearance: '', | ||
}) // ignoring some fields for now | ||
addEntity(entity) | ||
} | ||
|
||
return ( | ||
<div className="pt-4"> | ||
<div className="mb-2"> | ||
<h1 className="mb-4 inline px-4 text-xl font-bold">Entities</h1> | ||
<Button | ||
onClick={handleAddEntity} | ||
className="absolute right-2 top-2" | ||
variant="secondary" | ||
> | ||
New + | ||
</Button> | ||
</div> | ||
<ul> | ||
{entities.map((entity: ClapEntity) => ( | ||
<li key={entity.id} className={`flex px-2 py-1`}> | ||
<Button | ||
onClick={() => { | ||
setCurrent(entity) | ||
onSelectEntity(entity.id) | ||
}} | ||
variant="ghost" | ||
> | ||
{entity.label} ({entity.category}) | ||
</Button> | ||
<Button | ||
onClick={() => removeEntity(entity.id)} | ||
className={`ml-2 ml-auto`} | ||
variant="destructive" | ||
size="sm" | ||
> | ||
Remove | ||
</Button> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.