mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-29 22:51:49 +01:00
dynamic icons for preview, and icons per view
This commit is contained in:
parent
e7550c0a3e
commit
e859847edb
@ -53,7 +53,6 @@ func parseMetaSets(metaSets []string) (map[string]interface{}, error) {
|
||||
meta[fields[0]] = setVal
|
||||
}
|
||||
}
|
||||
meta[fields[0]] = fields[1]
|
||||
}
|
||||
return meta, nil
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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">
|
||||
|
Loading…
Reference in New Issue
Block a user