Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support keyword search #44

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/uuid": "^10.0.0",
"@xterm/addon-canvas": "^0.7.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-search": "^0.15.0",
"@xterm/xterm": "^5.5.0",
"electron": "^31.2.0",
"electron-devtools-installer": "^3.2.0",
Expand Down
1 change: 1 addition & 0 deletions src/renderer/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ body {
background-color: #eeeeee;
}
}

20 changes: 13 additions & 7 deletions src/renderer/header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Button, ControlGroup, InputGroup, MenuItem, Tooltip } from "@blueprintjs/core";
import {
Button,
ControlGroup,
InputGroup,
MenuItem,
Tooltip
} from "@blueprintjs/core";
import { Select } from "@blueprintjs/select";
import { type FC, useState } from "react";
import { useSelector } from "react-redux";
Expand All @@ -15,23 +21,23 @@ export const Header: FC = () => {
style={{
WebkitAppRegion: "drag",
padding: "10px 10px 10px 80px",
display: "flex",
display: "flex"
}}
>
<Select
menuProps={{
style: {
maxHeight: "calc(100vh - 100px)", // TODO:
overflow: "auto",
},
overflow: "auto"
}
}}
filterable
items={Object.values(appState)}
itemPredicate={(query, item) => {
const lq = query.toLowerCase();
return (
item.name.toLowerCase().includes(lq)
|| item.id.toLowerCase().includes(lq)
item.name.toLowerCase().includes(lq) ||
item.id.toLowerCase().includes(lq)
);
}}
itemRenderer={(item, { modifiers, handleClick, handleFocus }) => {
Expand Down Expand Up @@ -73,7 +79,7 @@ export const Header: FC = () => {
textAlign: "center",
display: "flex",
flexFlow: "column",
justifyContent: "center",
justifyContent: "center"
}}
>
Debugtron
Expand Down
41 changes: 27 additions & 14 deletions src/renderer/session.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { Button, Divider, HTMLTable, Pre, Tab, Tabs, Tag } from "@blueprintjs/core";
import {
Button,
Divider,
HTMLTable,
Pre,
Tab,
Tabs,
Tag
} from "@blueprintjs/core";
import { type FC, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { appSlice } from "../reducers/app";
Expand All @@ -19,6 +27,8 @@ export const Session: FC = () => {
}
}, [activeId, sessionStore]);

console.log(666644, appStore, sessionStore);

return (
<Tabs
selectedTabId={activeId}
Expand All @@ -41,7 +51,7 @@ export const Session: FC = () => {
display: "flex",
marginTop: -20,
overflow: "auto",
maxHeight: "calc(100vh - 100px)", // TODO:
maxHeight: "calc(100vh - 100px)" // TODO:
}}
>
<div style={{ marginTop: 5, overflow: "auto", flexShrink: 0 }}>
Expand All @@ -58,11 +68,13 @@ export const Session: FC = () => {
<tr key={id}>
<td>
<Tag
intent={page.type === "node"
? "success"
: page.type === "page"
? "primary"
: "none"}
intent={
page.type === "node"
? "success"
: page.type === "page"
? "primary"
: "none"
}
>
{page.type}
</Tag>
Expand All @@ -71,7 +83,7 @@ export const Session: FC = () => {
style={{
minWidth: 160,
maxWidth: 160,
wordWrap: "break-word",
wordWrap: "break-word"
}}
>
{page.title}
Expand All @@ -84,16 +96,16 @@ export const Session: FC = () => {
const url = page.devtoolsFrontendUrl
.replace(
/^\/devtools/,
"devtools://devtools/bundled",
"devtools://devtools/bundled"
)
.replace(
/^chrome-devtools:\/\//,
"devtools://",
"devtools://"
);

require("electron").ipcRenderer.send(
"open-window",
url,
url
);
}}
>
Expand All @@ -110,14 +122,15 @@ export const Session: FC = () => {
style={{
marginTop: 5,
flexGrow: 1,
overflow: "auto",
overflow: "auto"
}}
>
<Xterm
content={session.log}
options={{
fontFamily: "SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace",
convertEol: true,
fontFamily:
"SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace",
convertEol: true
}}
/>
</div>
Expand Down
37 changes: 37 additions & 0 deletions src/renderer/xterm.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.xterm-search-panel {
position: fixed;
width: 250px;
top: 100px;
right: 30px;
padding: 8px;
background-color: #fff;
z-index: 999;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
}

.xterm-search-panel-input{
display: block;
z-index: 999;
}

.xterm-search-panel-close {
font-size: 18px;
font-weight: 600;
cursor: pointer;
}

.xterm-search-panel-up{
font-size: 18px;
font-weight: 600;
cursor: pointer;
}

.xterm-search-panel-down{
font-size: 18px;
font-weight: 600;
cursor: pointer;
}
100 changes: 96 additions & 4 deletions src/renderer/xterm.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,124 @@
import { type FC, useEffect, useRef, useState } from "react";
import { CanvasAddon } from "@xterm/addon-canvas";
import { FitAddon } from "@xterm/addon-fit";
import { type ITerminalOptions, Terminal } from "@xterm/xterm";
import { SearchAddon } from "@xterm/addon-search";
import { InputGroup } from "@blueprintjs/core";
import "@xterm/xterm/css/xterm.css";
import { type FC, useEffect, useRef } from "react";
import "./xterm.css";

const searchDecorationOptions = {
// 匹配项的背景颜色
matchBackground: "#FFD700", // 金色,明亮且易于识别
// 匹配项的边框颜色
matchBorder: "#FF8C00", // 暗橙色,与背景形成对比
// 匹配项在概览标尺中的颜色
matchOverviewRuler: "#FFD700", // 与背景相同,使其在标尺中突出
// 当前激活匹配项的背景颜色
activeMatchBackground: "#FF4500", // 橙红色,清晰显示当前项
// 当前激活匹配项的边框颜色
activeMatchBorder: "#FF6347", // 西红柿色,进一步强调当前匹配
// 当前激活匹配项在概览标尺中的颜色
activeMatchColorOverviewRuler: "#FF4500" // 与激活背景相同,便于识别
};

export const Xterm: FC<{ content: string; options?: ITerminalOptions }> = ({
content,
options,
options
}) => {
const [visible, setVisible] = useState(false);
const [countDisplay, setCountDisplay] = useState({ count: 0, cur: 0 });

const domRef = useRef<HTMLDivElement>(null);
const termRef = useRef<Terminal>();
const searchAddonRef = useRef<SearchAddon>();
const searchVal = useRef("");

const onFindNext = (val?: string) => {
searchAddonRef.current?.findNext(val || searchVal.current, {
incremental: true,
decorations: searchDecorationOptions
});
};

const onFindPrevious = (val?: string) => {
searchAddonRef.current?.findPrevious(val || searchVal.current, {
incremental: true,
decorations: searchDecorationOptions
});
};

const onSearch = (e) => {
searchVal.current = e.target.value;
onFindNext();
};

const onClose = () => {
setVisible(false);
searchAddonRef.current?.dispose();
};

useEffect(() => {
const term = new Terminal(options);
const term = new Terminal({ ...options, allowProposedApi: true });
searchAddonRef.current = new SearchAddon();
term.loadAddon(new FitAddon());
term.loadAddon(new CanvasAddon());
term.loadAddon(searchAddonRef.current);
term.open(domRef.current!);
termRef.current = term;
term.resize(200, 50);
searchAddonRef.current?.onDidChangeResults(
({ resultIndex, resultCount }) => {
if (resultCount > 0) {
setCountDisplay({ count: resultCount, cur: resultIndex + 1 });
} else {
setCountDisplay({ count: 0, cur: 0 });
}
}
);

return () => {
termRef.current?.dispose();
};
}, []);

useEffect(() => {
window.addEventListener("keydown", (event) => {
if ((event?.metaKey || event.ctrlKey) && event.key === "f") {
!visible && setVisible(true);
}
});
}, []);

useEffect(() => {
termRef.current?.clear();
termRef.current?.writeln(content);
}, [content]);

return <div ref={domRef} />;
return (
<div style={{ position: "relative" }}>
<div ref={domRef} style={{ height: "90vh" }} />
<div
className="xterm-search-panel"
style={{ display: visible ? "flex" : "none" }}
>
<InputGroup placeholder="请输入搜索内容" onChange={onSearch} />
<span>
{countDisplay.cur}/{countDisplay.count}
</span>
<span
className="xterm-search-panel-up"
onClick={() => onFindPrevious()}
>
</span>
<span className="xterm-search-panel-down" onClick={() => onFindNext()}>
</span>
<span className="xterm-search-panel-close" onClick={onClose}>
×
</span>
</div>
</div>
);
};
Loading