feat: board thumbnails, inline rename, UX overhaul + zoom/counter fixes

- Auto-generate board thumbnail from canvas content on save (webp, 400px)
- Collection cards show stacked/fanned board thumbnails with random offsets
- Three-dot menu on all cards with Rename, Share, Delete actions
- Inline rename for collections (header + card) and boards
- Collection cards show public/private status and member count
- Share button on collection cards for quick access
- Add updateCollection/updateBoard API functions
- Add thumbnail + object_count columns to boards table with migration
- Fix zoom drift: use element-relative coords (offsetX/Y) not getScenePoint
- Fix thumbnail generation breaking viewport: use finally block for restore
- Fix thumbnail bounds: use scene-space obj coords not screen-space getBoundingRect
- Fix object counter: live count from canvas instead of stale DB images table
- Fix three-dot menu clipping by removing overflow:hidden from card containers
- Status bar shows "objects" instead of "images", updates on add/delete
This commit is contained in:
Hiren
2026-03-09 19:10:25 +05:30
parent 00c3370634
commit 0c9ab32aef
8 changed files with 824 additions and 305 deletions
+10 -2
View File
@@ -54,6 +54,10 @@ export function getCollectionDetail(collectionId: string) {
return api.get(`/api/collections/${collectionId}`);
}
export function updateCollection(collectionId: string, data: { name?: string; description?: string }) {
return api.put(`/api/collections/${collectionId}`, data);
}
export function deleteCollection(collectionId: string) {
return api.delete(`/api/collections/${collectionId}`);
}
@@ -91,12 +95,16 @@ export function getBoard(boardId: string) {
return api.get(`/api/boards/${boardId}`);
}
export function updateBoard(boardId: string, data: { name?: string; description?: string }) {
return api.put(`/api/boards/${boardId}`, data);
}
export function deleteBoard(boardId: string) {
return api.delete(`/api/boards/${boardId}`);
}
export function saveCanvas(boardId: string, canvasState: string) {
return api.post(`/api/boards/${boardId}/save`, { canvas_state: canvasState });
export function saveCanvas(boardId: string, canvasState: string, thumbnail?: string) {
return api.post(`/api/boards/${boardId}/save`, { canvas_state: canvasState, thumbnail });
}
export function uploadImage(boardId: string, file: File) {