-
Notifications
You must be signed in to change notification settings - Fork 4
[ENG-1287] On canvas load, update key image #938
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
f372c86
cc64ec7
9f99bcb
9515eba
7c541cd
e4c8a02
2063b42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,9 @@ | ||
| import type { Editor } from "tldraw"; | ||
| import type { OnloadArgs } from "roamjs-components/types"; | ||
| import type { DiscourseNodeShape } from "~/components/canvas/DiscourseNodeUtil"; | ||
| import calcCanvasNodeSizeAndImg, { | ||
| getCanvasNodeKeyImageUrl, | ||
| } from "./calcCanvasNodeSizeAndImg"; | ||
|
|
||
| /** | ||
| * Query Roam for current :node/title or :block/string for each uid. | ||
|
|
@@ -56,11 +60,37 @@ const deleteNodeShapeAndRelations = ( | |
| * - Updates shapes whose title changed | ||
| * - Removes shapes whose uid no longer exists in the graph | ||
| */ | ||
| export const syncCanvasNodesOnLoad = async ({ | ||
| editor, | ||
| nodeTypeIds, | ||
| relationShapeTypeIds, | ||
| extensionAPI, | ||
| }: { | ||
| editor: Editor; | ||
| nodeTypeIds: string[]; | ||
| relationShapeTypeIds: string[]; | ||
| extensionAPI: OnloadArgs["extensionAPI"]; | ||
| }): Promise<void> => { | ||
| const { discourseNodeShapes, uidToTitle } = await syncCanvasNodeTitlesOnLoad( | ||
| editor, | ||
| nodeTypeIds, | ||
| relationShapeTypeIds, | ||
| ); | ||
| await syncCanvasKeyImagesOnLoad({ | ||
| editor, | ||
| discourseNodeShapes, | ||
| uidToTitle, | ||
| extensionAPI, | ||
| }); | ||
| }; | ||
| export const syncCanvasNodeTitlesOnLoad = async ( | ||
| editor: Editor, | ||
| nodeTypeIds: string[], | ||
| relationShapeTypeIds: string[], | ||
| ): Promise<void> => { | ||
| ): Promise<{ | ||
| discourseNodeShapes: DiscourseNodeShape[]; | ||
| uidToTitle: Map<string, string>; | ||
| }> => { | ||
| const nodeTypeSet = new Set(nodeTypeIds); | ||
| const relationIds = new Set(relationShapeTypeIds); | ||
| const allRecords = editor.store.allRecords(); | ||
|
|
@@ -72,7 +102,8 @@ export const syncCanvasNodeTitlesOnLoad = async ( | |
| ) as DiscourseNodeShape[]; | ||
|
|
||
| const uids = [...new Set(discourseNodeShapes.map((s) => s.props.uid))]; | ||
| if (uids.length === 0) return; | ||
| if (uids.length === 0) | ||
| return { discourseNodeShapes: [], uidToTitle: new Map() }; | ||
|
|
||
| const uidToTitle = await queryTitlesByUids(uids); | ||
|
|
||
|
|
@@ -104,4 +135,66 @@ export const syncCanvasNodeTitlesOnLoad = async ( | |
| })), | ||
| ); | ||
| } | ||
|
|
||
| return { discourseNodeShapes, uidToTitle }; | ||
| }; | ||
|
|
||
| const syncCanvasKeyImagesOnLoad = async ({ | ||
| editor, | ||
| discourseNodeShapes, | ||
| uidToTitle, | ||
| extensionAPI, | ||
| }: { | ||
| editor: Editor; | ||
| discourseNodeShapes: DiscourseNodeShape[]; | ||
| uidToTitle: Map<string, string>; | ||
| extensionAPI: OnloadArgs["extensionAPI"]; | ||
| }): Promise<void> => { | ||
| const survivingShapes = discourseNodeShapes.filter((s) => | ||
| uidToTitle.has(s.props.uid), | ||
| ); | ||
| const imageUpdates: { | ||
| id: DiscourseNodeShape["id"]; | ||
| type: string; | ||
| props: { imageUrl: string; w: number; h: number }; | ||
| }[] = []; | ||
|
|
||
| // First pass: cheaply fetch imageUrls (no image loading) to find which shapes changed. | ||
| const urlResults = await Promise.all( | ||
| survivingShapes.map(async (shape) => { | ||
| const title = uidToTitle.get(shape.props.uid) ?? shape.props.title ?? ""; | ||
| const imageUrl = await getCanvasNodeKeyImageUrl({ | ||
|
trangdoan982 marked this conversation as resolved.
Outdated
|
||
| nodeText: title, | ||
| uid: shape.props.uid, | ||
| nodeType: shape.type, | ||
| extensionAPI, | ||
| }); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also running an individual query for each shape. This could be hundreds of queries. We'll have to write a custom query for any nodes that have the |
||
| return { shape, title, imageUrl }; | ||
| }), | ||
| ); | ||
|
|
||
| const changedShapes = urlResults.filter( | ||
| ({ shape, imageUrl }) => (shape.props.imageUrl ?? "") !== imageUrl, | ||
| ); | ||
|
|
||
| // Second pass: load images only for shapes whose URL changed, to compute new dimensions. | ||
| await Promise.all( | ||
| changedShapes.map(async ({ shape, title }) => { | ||
| const { w, h, imageUrl } = await calcCanvasNodeSizeAndImg({ | ||
|
trangdoan982 marked this conversation as resolved.
Outdated
trangdoan982 marked this conversation as resolved.
Outdated
|
||
| nodeText: title, | ||
|
trangdoan982 marked this conversation as resolved.
Outdated
|
||
| uid: shape.props.uid, | ||
| nodeType: shape.type, | ||
| extensionAPI, | ||
| }); | ||
| imageUpdates.push({ | ||
| id: shape.id, | ||
| type: shape.type, | ||
| props: { imageUrl, w, h }, | ||
| }); | ||
| }), | ||
| ); | ||
|
trangdoan982 marked this conversation as resolved.
Outdated
|
||
|
|
||
| if (imageUpdates.length > 0) { | ||
| editor.updateShapes(imageUpdates); | ||
| } | ||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.