diff --git a/packages/editor/src/editor/Canvas.tsx b/packages/editor/src/editor/Canvas.tsx index fbe2b98..cc33eb0 100644 --- a/packages/editor/src/editor/Canvas.tsx +++ b/packages/editor/src/editor/Canvas.tsx @@ -142,13 +142,14 @@ export function Canvas(props: CanvasProps) { const additive = (e as React.MouseEvent).ctrlKey || (e as React.MouseEvent).metaKey || (e as React.MouseEvent).shiftKey; - const nextSelectionIds = targetId + const nextSelectionIdsRaw = targetId ? props.selectionIds.includes(targetId) ? props.selectionIds : additive ? [...props.selectionIds, targetId] : [targetId] : props.selectionIds; + const nextSelectionIds = Array.from(new Set(nextSelectionIdsRaw)); const selectionKey = selectionKeyOf(nextSelectionIds); if (targetId) { diff --git a/packages/editor/src/editor/EditorApp.tsx b/packages/editor/src/editor/EditorApp.tsx index 18f6a35..9ef9a5c 100644 --- a/packages/editor/src/editor/EditorApp.tsx +++ b/packages/editor/src/editor/EditorApp.tsx @@ -582,11 +582,12 @@ export function EditorApp() { e.preventDefault(); e.stopPropagation(); const additive = e.ctrlKey || e.metaKey || e.shiftKey; - const nextSelectionIds = state.selection.ids.includes(node.id) + const nextSelectionIdsRaw = state.selection.ids.includes(node.id) ? state.selection.ids : additive ? [...state.selection.ids, node.id] : [node.id]; + const nextSelectionIds = Array.from(new Set(nextSelectionIdsRaw)); const selectionKey = selectionKeyOf(nextSelectionIds); if (!state.selection.ids.includes(node.id)) { if (additive) { diff --git a/packages/editor/src/editor/samples/goviewSamples.ts b/packages/editor/src/editor/samples/goviewSamples.ts index 4b0fedb..fd52c8c 100644 --- a/packages/editor/src/editor/samples/goviewSamples.ts +++ b/packages/editor/src/editor/samples/goviewSamples.ts @@ -100,4 +100,32 @@ export const goViewSamples: GoViewSample[] = [ ], }), }, + { + id: 'goview-video-type-hint', + title: 'Video (type hint)', + subtitle: 'Media / mediaType + playbackUrl', + description: 'Type hint fields + playbackUrl for video detection.', + focusId: 'video_2', + json: prettyJson({ + editCanvasConfig: { projectName: 'Sample: video type hint', width: 1920, height: 1080, background: '#0b1220' }, + componentList: [ + { + id: 'video_2', + chartConfig: { key: 'EmbedCommon' }, + attr: { x: 260, y: 140, w: 960, h: 540 }, + option: { + mediaType: 'video', + playbackUrl: 'https://www.w3schools.com/html/mov_bbb.mp4', + controls: true, + }, + }, + { + id: 'text_2', + chartConfig: { key: 'TextCommon' }, + attr: { x: 260, y: 60, w: 760, h: 60 }, + option: { text: 'goView Sample: video via type hint + playbackUrl' }, + }, + ], + }), + }, ]; diff --git a/packages/sdk/src/core/widgets/iframe.ts b/packages/sdk/src/core/widgets/iframe.ts index a1cd53d..843fdd4 100644 --- a/packages/sdk/src/core/widgets/iframe.ts +++ b/packages/sdk/src/core/widgets/iframe.ts @@ -13,10 +13,20 @@ export interface GoViewIframeOption { // common alternative shapes iframeUrl?: unknown; iframeSrc?: unknown; + iframe?: unknown; embedUrl?: unknown; + embedSrc?: unknown; frameUrl?: unknown; frameSrc?: unknown; webUrl?: unknown; + websiteUrl?: unknown; + siteUrl?: unknown; + openUrl?: unknown; + openURL?: unknown; + linkUrl?: unknown; + linkURL?: unknown; + targetUrl?: unknown; + targetURL?: unknown; webpageUrl?: unknown; pageUrl?: unknown; h5Url?: unknown; @@ -188,6 +198,7 @@ function pickHtmlString(option: GoViewIframeOption): string | undefined { obj.html ?? obj.htmlContent ?? obj.htmlString ?? + obj.iframe ?? obj.embed ?? obj.embedHtml ?? obj.iframeHtml ?? @@ -209,10 +220,20 @@ function pickSrc(option: GoViewIframeOption): string { pickUrlLike({ iframeUrl: option.iframeUrl, iframeSrc: option.iframeSrc, + iframe: option.iframe, embedUrl: option.embedUrl, + embedSrc: option.embedSrc, frameUrl: option.frameUrl, frameSrc: option.frameSrc, webUrl: option.webUrl, + websiteUrl: option.websiteUrl, + siteUrl: option.siteUrl, + openUrl: option.openUrl, + openURL: option.openURL, + linkUrl: option.linkUrl, + linkURL: option.linkURL, + targetUrl: option.targetUrl, + targetURL: option.targetURL, webpageUrl: option.webpageUrl, pageUrl: option.pageUrl, h5Url: option.h5Url, diff --git a/packages/sdk/src/core/widgets/urlLike.ts b/packages/sdk/src/core/widgets/urlLike.ts index 4eff40e..d1fac61 100644 --- a/packages/sdk/src/core/widgets/urlLike.ts +++ b/packages/sdk/src/core/widgets/urlLike.ts @@ -96,6 +96,18 @@ function pickUrlLikeInner(input: unknown, depth: number): string { 'path', 'source', 'address', + 'embedSrc', + 'mediaUrl', + 'mediaSrc', + 'playbackUrl', + 'playbackSrc', + 'websiteUrl', + 'siteUrl', + 'openUrl', + 'openURL', + 'linkURL', + 'targetUrl', + 'targetURL', // snake_case aliases seen in some exporters 'src_url', @@ -110,6 +122,7 @@ function pickUrlLikeInner(input: unknown, depth: number): string { 'pageUrl', 'pageSrc', 'page', + 'webpageUrl', 'documentUrl', // iframe-ish HTML-in-URL fields (handled by iframe widget converter) diff --git a/packages/sdk/src/core/widgets/video.ts b/packages/sdk/src/core/widgets/video.ts index 814207f..f1847b4 100644 --- a/packages/sdk/src/core/widgets/video.ts +++ b/packages/sdk/src/core/widgets/video.ts @@ -13,6 +13,10 @@ export interface GoViewVideoOption { // seen in some forks srcUrl?: unknown; sourceUrl?: unknown; + mediaUrl?: unknown; + mediaSrc?: unknown; + playbackUrl?: unknown; + playbackSrc?: unknown; // streaming-ish aliases webrtcUrl?: unknown; @@ -29,6 +33,11 @@ export interface GoViewVideoOption { playList?: unknown; playlist?: unknown; + mediaType?: unknown; + contentType?: unknown; + playerType?: unknown; + streamType?: unknown; + autoplay?: boolean; autoPlay?: boolean; isAutoPlay?: boolean; @@ -222,6 +231,10 @@ function pickFirstUrlFromList(input: unknown): string { 'cameraUrl', 'cctvUrl', 'monitorUrl', + 'mediaUrl', + 'mediaSrc', + 'playbackUrl', + 'playbackSrc', 'src', 'url', 'value', @@ -273,14 +286,18 @@ function pickSrc(option: GoViewVideoOption): string { // streaming/camera keys 'rtsp', 'rtmp', - 'stream', - 'streamUrl', - // generic fallbacks - 'src', - 'url', - 'srcUrl', - 'sourceUrl', - 'value', + 'stream', + 'streamUrl', + // generic fallbacks + 'src', + 'url', + 'mediaUrl', + 'mediaSrc', + 'playbackUrl', + 'playbackSrc', + 'srcUrl', + 'sourceUrl', + 'value', // sometimes low-code exports store