mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-02-01 23:21:59 +01:00
fun customization for the block title
This commit is contained in:
parent
312ee5af59
commit
8683105f70
13
Taskfile.yml
13
Taskfile.yml
@ -23,12 +23,14 @@ tasks:
|
|||||||
- WAVETERM_DEV=1 yarn dev
|
- WAVETERM_DEV=1 yarn dev
|
||||||
deps:
|
deps:
|
||||||
- build:server
|
- build:server
|
||||||
|
- build:wsh
|
||||||
|
|
||||||
electron:start:
|
electron:start:
|
||||||
cmds:
|
cmds:
|
||||||
- WAVETERM_DEV=1 yarn start
|
- WAVETERM_DEV=1 yarn start
|
||||||
deps:
|
deps:
|
||||||
- build:server
|
- build:server
|
||||||
|
- build:wsh
|
||||||
|
|
||||||
build:server:
|
build:server:
|
||||||
cmds:
|
cmds:
|
||||||
@ -41,6 +43,17 @@ tasks:
|
|||||||
deps:
|
deps:
|
||||||
- go:mod:tidy
|
- go:mod:tidy
|
||||||
|
|
||||||
|
build:wsh:
|
||||||
|
cmds:
|
||||||
|
- go build -o dist/bin/wsh{{exeExt}} cmd/wsh/main-wsh.go
|
||||||
|
sources:
|
||||||
|
- "cmd/wsh/**/*.go"
|
||||||
|
- "pkg/**/*.go"
|
||||||
|
generates:
|
||||||
|
- dist/bin/wsh{{exeExt}}
|
||||||
|
deps:
|
||||||
|
- go:mod:tidy
|
||||||
|
|
||||||
go:mod:tidy:
|
go:mod:tidy:
|
||||||
summary: Runs `go mod tidy`
|
summary: Runs `go mod tidy`
|
||||||
internal: true
|
internal: true
|
||||||
|
@ -10,6 +10,7 @@ import { CenteredDiv } from "@/element/quickelems";
|
|||||||
import { ContextMenuModel } from "@/store/contextmenu";
|
import { ContextMenuModel } from "@/store/contextmenu";
|
||||||
import { atoms, setBlockFocus, useBlockAtom } from "@/store/global";
|
import { atoms, setBlockFocus, useBlockAtom } from "@/store/global";
|
||||||
import * as WOS from "@/store/wos";
|
import * as WOS from "@/store/wos";
|
||||||
|
import * as util from "@/util/util";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import * as jotai from "jotai";
|
import * as jotai from "jotai";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
@ -24,11 +25,79 @@ interface BlockProps {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
dragHandleRef?: React.RefObject<HTMLDivElement>;
|
dragHandleRef?: React.RefObject<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
function processTextString(iconString: string): React.ReactNode {
|
||||||
|
if (iconString == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const tagRegex = /<(\/)?([a-z]+)(?::([#a-z0-9-]+))?>/g;
|
||||||
|
let lastIdx = 0;
|
||||||
|
let match;
|
||||||
|
let partsStack = [[]];
|
||||||
|
while ((match = tagRegex.exec(iconString)) != null) {
|
||||||
|
const lastPart = partsStack[partsStack.length - 1];
|
||||||
|
const before = iconString.substring(lastIdx, match.index);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (!tagParam.match(/^[a-z0-9-]+$/)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lastPart.push(<i key={match.index} className={`fa fa-solid fa-${tagParam}`} />);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tagName == "c" || tagName == "color") {
|
||||||
|
if (tagParam == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isClosing) {
|
||||||
|
if (partsStack.length <= 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
partsStack.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let children = [];
|
||||||
|
const rtag = React.createElement("span", { key: match.index, style: { color: tagParam } }, children);
|
||||||
|
lastPart.push(rtag);
|
||||||
|
partsStack.push(children);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (tagName == "i" || tagName == "b") {
|
||||||
|
if (isClosing) {
|
||||||
|
if (partsStack.length <= 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
partsStack.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let children = [];
|
||||||
|
const rtag = React.createElement(tagName, { key: match.index }, children);
|
||||||
|
lastPart.push(rtag);
|
||||||
|
partsStack.push(children);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
partsStack[partsStack.length - 1].push(iconString.substring(lastIdx));
|
||||||
|
return partsStack[0];
|
||||||
|
}
|
||||||
|
|
||||||
function getBlockHeaderText(blockData: Block): string {
|
function getBlockHeaderText(blockData: Block): React.ReactNode {
|
||||||
if (!blockData) {
|
if (!blockData) {
|
||||||
return "no block data";
|
return "no block data";
|
||||||
}
|
}
|
||||||
|
if (!util.isBlank(blockData?.meta?.title)) {
|
||||||
|
try {
|
||||||
|
return processTextString(blockData.meta.title);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("error processing title", blockData.meta.title, e);
|
||||||
|
return blockData.meta.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
return `${blockData?.view} [${blockData.oid.substring(0, 8)}]`;
|
return `${blockData?.view} [${blockData.oid.substring(0, 8)}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +164,13 @@ const BlockFrame_Tech = ({
|
|||||||
});
|
});
|
||||||
ContextMenuModel.showContextMenu(menu, e);
|
ContextMenuModel.showContextMenu(menu, e);
|
||||||
}
|
}
|
||||||
|
let style: React.CSSProperties = {};
|
||||||
|
if (!isFocused && blockData?.meta?.["frame:bordercolor"]) {
|
||||||
|
style.borderColor = blockData.meta["frame:bordercolor"];
|
||||||
|
}
|
||||||
|
if (isFocused && blockData?.meta?.["frame:bordercolor:focused"]) {
|
||||||
|
style.borderColor = blockData.meta["frame:bordercolor:focused"];
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@ -105,6 +181,7 @@ const BlockFrame_Tech = ({
|
|||||||
)}
|
)}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
ref={blockRef}
|
ref={blockRef}
|
||||||
|
style={style}
|
||||||
>
|
>
|
||||||
<div className="block-frame-tech-header" ref={dragHandleRef} onContextMenu={handleContextMenu}>
|
<div className="block-frame-tech-header" ref={dragHandleRef} onContextMenu={handleContextMenu}>
|
||||||
{getBlockHeaderText(blockData)}
|
{getBlockHeaderText(blockData)}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.block-container {
|
.block-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -60,6 +60,10 @@ const TabContent = ({ tabId }: { tabId: string }) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tabData?.blockids?.length == 0) {
|
||||||
|
return <div className="tabcontent tabcontent-empty"></div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tabcontent">
|
<div className="tabcontent">
|
||||||
<TileLayout
|
<TileLayout
|
||||||
|
@ -164,6 +164,10 @@ func handleWaveFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func handleStreamFile(w http.ResponseWriter, r *http.Request) {
|
func handleStreamFile(w http.ResponseWriter, r *http.Request) {
|
||||||
fileName := r.URL.Query().Get("path")
|
fileName := r.URL.Query().Get("path")
|
||||||
|
if fileName == "" {
|
||||||
|
http.Error(w, "path is required", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
fileName = wavebase.ExpandHomeDir(fileName)
|
fileName = wavebase.ExpandHomeDir(fileName)
|
||||||
http.ServeFile(w, r, fileName)
|
http.ServeFile(w, r, fileName)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user