From e859847edb5d3f39652927558147834d3c7923d3 Mon Sep 17 00:00:00 2001 From: sawka Date: Fri, 21 Jun 2024 16:01:51 -0700 Subject: [PATCH] dynamic icons for preview, and icons per view --- cmd/wsh/cmd/wshcmd-setmeta.go | 1 - frontend/app/block/block.tsx | 64 ++++++++++++++++++++++++++++------- frontend/app/view/preview.tsx | 18 +++++++++- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/cmd/wsh/cmd/wshcmd-setmeta.go b/cmd/wsh/cmd/wshcmd-setmeta.go index 2058bc2c4..7590256a4 100644 --- a/cmd/wsh/cmd/wshcmd-setmeta.go +++ b/cmd/wsh/cmd/wshcmd-setmeta.go @@ -53,7 +53,6 @@ func parseMetaSets(metaSets []string) (map[string]interface{}, error) { meta[fields[0]] = setVal } } - meta[fields[0]] = fields[1] } return meta, nil } diff --git a/frontend/app/block/block.tsx b/frontend/app/block/block.tsx index b2705bb15..c002d715c 100644 --- a/frontend/app/block/block.tsx +++ b/frontend/app/block/block.tsx @@ -42,7 +42,6 @@ function processTitleString(titleString: string): React.ReactNode[] { lastPart.push(before); lastIdx = match.index + match[0].length; const [_, isClosing, tagName, tagParam] = match; - console.log("match", match); if (tagName == "icon" && !isClosing) { if (tagParam == null) { continue; @@ -92,13 +91,12 @@ function processTitleString(titleString: string): React.ReactNode[] { return partsStack[0]; } -function getBlockHeaderText(blockData: Block): React.ReactNode { +function getBlockHeaderText(blockIcon: string, blockData: Block): React.ReactNode { if (!blockData) { return "no block data"; } - let blockIcon: React.ReactNode = null; - if (!util.isBlank(blockData?.meta?.["icon"])) { - const iconName = blockData.meta.icon; + let blockIconElem: React.ReactNode = null; + if (!util.isBlank(blockIcon)) { let iconColor = blockData.meta["icon:color"]; if (iconColor && !iconColor.match(colorRegex)) { iconColor = null; @@ -107,23 +105,25 @@ function getBlockHeaderText(blockData: Block): React.ReactNode { if (!util.isBlank(iconColor)) { iconStyle = { color: iconColor }; } - if (iconName.match(/^[a-z0-9-]+$/)) { - blockIcon = ; + if (blockIcon.match(/^[a-z0-9-]+$/)) { + blockIconElem = ( + + ); } } if (!util.isBlank(blockData?.meta?.title)) { try { const rtn = processTitleString(blockData.meta.title) ?? []; - if (blockIcon) { - rtn.unshift(blockIcon); + if (blockIconElem) { + rtn.unshift(blockIconElem); } return rtn; } catch (e) { console.error("error processing title", blockData.meta.title, e); - return [blockIcon, blockData.meta.title]; + return [blockIconElem, blockData.meta.title]; } } - return [blockIcon, `${blockData?.view} [${blockData.oid.substring(0, 8)}]`]; + return [blockIconElem, `${blockData?.view} [${blockData.oid.substring(0, 8)}]`]; } interface FramelessBlockHeaderProps { @@ -137,7 +137,7 @@ const FramelessBlockHeader = ({ blockId, onClose, dragHandleRef }: FramelessBloc return (
-
{getBlockHeaderText(blockData)}
+
{getBlockHeaderText(null, blockData)}
{onClose && (
@@ -178,6 +178,8 @@ const BlockFrame_Tech = ({ }); }); let isFocused = jotai.useAtomValue(isFocusedAtom); + const blockIcon = useBlockIcon(blockId); + if (preview) { isFocused = true; } @@ -209,7 +211,7 @@ const BlockFrame_Tech = ({ style={style} >
- {getBlockHeaderText(blockData)} + {getBlockHeaderText(blockIcon, blockData)}
@@ -315,6 +317,42 @@ const BlockFrame = (props: BlockFrameProps) => { return ; }; +function blockViewToIcon(view: string): string { + console.log("blockViewToIcon", view); + if (view == "term") { + return "square-terminal"; + } + if (view == "preview") { + return "file"; + } + return null; +} + +function useBlockIcon(blockId: string): string { + const blockIconOverrideAtom = useBlockAtom(blockId, "blockicon:override", () => { + return jotai.atom(null); + }); + const blockIconAtom = useBlockAtom(blockId, "blockicon", () => { + return jotai.atom((get) => { + console.log("atom-blockicon", blockId); + const blockAtom = WOS.getWaveObjectAtom(WOS.makeORef("block", blockId)); + const blockData = get(blockAtom); + const metaIcon = blockData?.meta?.icon; + if (!util.isBlank(metaIcon)) { + console.log("atom-blockicon-meta", metaIcon); + return metaIcon; + } + const overrideVal = get(blockIconOverrideAtom); + if (overrideVal != null) { + return overrideVal; + } + return blockViewToIcon(blockData?.view); + }); + }); + const blockIcon = jotai.useAtomValue(blockIconAtom); + return blockIcon; +} + const Block = ({ blockId, onClose, dragHandleRef }: BlockProps) => { let blockElem: JSX.Element = null; const focusElemRef = React.useRef(null); diff --git a/frontend/app/view/preview.tsx b/frontend/app/view/preview.tsx index 1b3fdeda3..cd1acb8e2 100644 --- a/frontend/app/view/preview.tsx +++ b/frontend/app/view/preview.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Markdown } from "@/element/markdown"; -import { getBackendHostPort, useBlockAtom, useBlockCache } from "@/store/global"; +import { getBackendHostPort, globalStore, useBlockAtom, useBlockCache } from "@/store/global"; import * as services from "@/store/services"; import * as WOS from "@/store/wos"; import * as util from "@/util/util"; @@ -165,12 +165,16 @@ function PreviewView({ blockId }: { blockId: string }) { // handle streaming files here let specializedView: React.ReactNode; + let blockIcon = "file"; if ( mimeType == "application/pdf" || mimeType.startsWith("video/") || mimeType.startsWith("audio/") || mimeType.startsWith("image/") ) { + if (mimeType.startsWith("image/")) { + blockIcon = "image"; + } specializedView = ; } else if (fileInfo == null) { specializedView = ( @@ -179,14 +183,20 @@ function PreviewView({ blockId }: { blockId: string }) { } else if (fileInfo.size > MaxFileSize) { specializedView = File Too Large to Preview; } else if (mimeType === "text/markdown") { + blockIcon = "file-lines"; specializedView = ; } else if ( mimeType.startsWith("text/") || (mimeType.startsWith("application/") && (mimeType.includes("json") || mimeType.includes("yaml") || mimeType.includes("toml"))) ) { + blockIcon = "file-code"; specializedView = specializedView = ; } else if (mimeType === "directory") { + blockIcon = "folder"; + if (fileName == "~" || fileName == "~/") { + blockIcon = "home"; + } specializedView = ; } else { specializedView = ( @@ -195,6 +205,12 @@ function PreviewView({ blockId }: { blockId: string }) {
); } + setTimeout(() => { + const blockIconOverrideAtom = useBlockAtom(blockId, "blockicon:override", () => { + return jotai.atom(null); + }); + globalStore.set(blockIconOverrideAtom, blockIcon); + }, 10); return (