dynamic icons for preview, and icons per view

This commit is contained in:
sawka 2024-06-21 16:01:51 -07:00
parent e7550c0a3e
commit e859847edb
3 changed files with 68 additions and 15 deletions

View File

@ -53,7 +53,6 @@ func parseMetaSets(metaSets []string) (map[string]interface{}, error) {
meta[fields[0]] = setVal
}
}
meta[fields[0]] = fields[1]
}
return meta, nil
}

View File

@ -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 = <i style={iconStyle} className={`block-frame-icon fa fa-solid fa-${blockData.meta.icon}`} />;
if (blockIcon.match(/^[a-z0-9-]+$/)) {
blockIconElem = (
<i key="icon" style={iconStyle} className={`block-frame-icon fa fa-solid fa-${blockIcon}`} />
);
}
}
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 (
<div key="header" className="block-header" ref={dragHandleRef}>
<div className="block-header-text text-fixed">{getBlockHeaderText(blockData)}</div>
<div className="block-header-text text-fixed">{getBlockHeaderText(null, blockData)}</div>
{onClose && (
<div className="close-button" onClick={onClose}>
<i className="fa fa-solid fa-xmark-large" />
@ -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}
>
<div className="block-frame-tech-header" ref={dragHandleRef} onContextMenu={handleContextMenu}>
{getBlockHeaderText(blockData)}
{getBlockHeaderText(blockIcon, blockData)}
</div>
<div className={clsx("block-frame-tech-close")} onClick={onClose}>
<i className="fa fa-solid fa-xmark fa-fw" />
@ -315,6 +317,42 @@ const BlockFrame = (props: BlockFrameProps) => {
return <FrameElem {...props} />;
};
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<string>(blockId, "blockicon:override", () => {
return jotai.atom<string>(null);
});
const blockIconAtom = useBlockAtom<string>(blockId, "blockicon", () => {
return jotai.atom((get) => {
console.log("atom-blockicon", blockId);
const blockAtom = WOS.getWaveObjectAtom<Block>(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<HTMLInputElement>(null);

View File

@ -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 = <StreamingPreview fileInfo={fileInfo} />;
} else if (fileInfo == null) {
specializedView = (
@ -179,14 +183,20 @@ function PreviewView({ blockId }: { blockId: string }) {
} else if (fileInfo.size > MaxFileSize) {
specializedView = <CenteredDiv>File Too Large to Preview</CenteredDiv>;
} else if (mimeType === "text/markdown") {
blockIcon = "file-lines";
specializedView = <MarkdownPreview contentAtom={fileContentAtom} />;
} else if (
mimeType.startsWith("text/") ||
(mimeType.startsWith("application/") &&
(mimeType.includes("json") || mimeType.includes("yaml") || mimeType.includes("toml")))
) {
blockIcon = "file-code";
specializedView = specializedView = <CodeEdit readonly={true} text={fileContent} filename={fileName} />;
} else if (mimeType === "directory") {
blockIcon = "folder";
if (fileName == "~" || fileName == "~/") {
blockIcon = "home";
}
specializedView = <DirectoryPreview contentAtom={fileContentAtom} fileNameAtom={fileNameAtom} />;
} else {
specializedView = (
@ -195,6 +205,12 @@ function PreviewView({ blockId }: { blockId: string }) {
</div>
);
}
setTimeout(() => {
const blockIconOverrideAtom = useBlockAtom<string>(blockId, "blockicon:override", () => {
return jotai.atom<string>(null);
});
globalStore.set(blockIconOverrideAtom, blockIcon);
}, 10);
return (
<div className="full-preview">