Skip to content

Commit

Permalink
feat: 代码暂存,等待mac/linux终端接入
Browse files Browse the repository at this point in the history
  • Loading branch information
youngster-yj committed Jul 4, 2024
1 parent 7d57c3a commit 9b2cffc
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 147 deletions.
15 changes: 14 additions & 1 deletion app/main/handlers/manageYakScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,20 @@ module.exports = (win, getClient) => {
})
})

// 读取本地文件内容
// 读取本地文件大小
ipcMain.handle("read-file-size", async (e,filePath) => {
return new Promise((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (err) {
reject(err);
} else {
resolve(stats.size); // 文件大小以字节为单位
}
});
})
})

// 读取本地文件内容(同时校验其文件大小是否读取本地文件10M,大于则不读取)
ipcMain.handle("read-file-content", async (e,params) => {
console.log("read-file-content",params);
return new Promise((resolve, reject) => {
Expand Down
129 changes: 63 additions & 66 deletions app/main/handlers/yakRunnerTerminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,70 @@ const {ipcMain, clipboard} = require("electron");

module.exports = (win, getClient) => {

// let streams = {};
// const getStreamByPort = (addr) => {
// return streams[addr];
// }
// const removeStreamPort = (addr) => {
// const stream = streams[addr];
// if (stream) {
// stream.cancel();
// delete streams[addr];
// }
// };
let streams = {};
const getStreamByPort = (path) => {
return streams[path];
}
const removeStreamPort = (path) => {
// const stream = streams[path];
// if (stream) {
// stream.cancel();
// delete streams[path];
// }
};

// ipcMain.handle("runner-terminal-query-addrs", () => {
// return Object.keys(streams).map(i => `${i}`)
// });
// ipcMain.handle("runner-terminal-input", async (e, addr, data) => {
// const stream = getStreamByPort(addr);
// if (stream) {
// stream.write({
// raw: Buffer.from(data, "utf8")
// })
// }
// })
// ipcMain.handle("runner-terminal-cancel", async (e, addr) => {
// removeStreamPort(addr)
// });
// ipcMain.handle("runner-terminal-port", async (e, host, port) => {
// const addr = `${host}:${port}`
// if (getStreamByPort(addr)) {
// throw Error("listened port");
// }
// stream = getClient().YaklangTerminal();
// // 如果有问题,重置
// stream.on("error", (e) => {
// removeStreamPort(addr)
// })
ipcMain.handle("runner-terminal-query-addrs", () => {
return Object.keys(streams).map(i => `${i}`)
});
ipcMain.handle("runner-terminal-input", async (e, path, data) => {
const stream = getStreamByPort(path);
if (stream) {
stream.write({
raw: Buffer.from(data, "utf8")
})
}
})
ipcMain.handle("runner-terminal-cancel", async (e, path) => {
removeStreamPort(path)
});
ipcMain.handle("runner-terminal", async (e, params) => {
const {path} = params
if (getStreamByPort(path)) {
throw Error("listened terminal");
}
stream = getClient().YaklangTerminal();
// 如果有问题,重置
stream.on("error", (e) => {
console.log("error---",e);
removeStreamPort(path)
})

// // 发送回数据
// stream.on("data", data => {
// if (data.control) {
// if (win && data.waiting) {
// win.webContents.send(`client-listening-port-success-${addr}`)
// }
// if (win && data.closed) {
// removeStreamPort(addr)
// }
// return
// }
// 发送回数据
stream.on("data", data => {
console.log("data---",e);
if (data.control) {
if (win && data.waiting) {
win.webContents.send(`client-listening-terminal-success-${path}`)
}
if (win && data.closed) {
removeStreamPort(path)
}
return
}

// if (win) {
// win.webContents.send(`client-listening-port-data-${addr}`, data)
// }
// })
// stream.on("end", () => {
// removeStreamPort(addr)
// if (win) {
// win.webContents.send("client-listening-port-end", addr);
// }
// })
// stream.write({
// host, port,
// })
// streams[addr] = stream;
// })


// ipcMain.handle("copy-clipboard", (e, text) => {
// clipboard.writeText(text);
// });
if (win) {
win.webContents.send(`client-listening-terminal-data-${path}`, data)
}
})
stream.on("end", () => {
console.log("end---",e);
removeStreamPort(path)
if (win) {
win.webContents.send("client-listening-terminal-end", path);
}
})
console.log("start---",params);
stream.write(params)
streams[path] = stream;
})
}
3 changes: 3 additions & 0 deletions app/protos/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ service Yak {

// 开启端口
rpc OpenPort(stream Input) returns (stream Output);
// editor terminal 交互
rpc YaklangTerminal(stream Input) returns (stream Output);

// Exec
rpc Exec(ExecRequest) returns (stream ExecResult);
Expand Down Expand Up @@ -4859,6 +4861,7 @@ message Input {

string host = 2;
uint32 port = 3;
string path = 4;
}

message Output {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,21 @@ import {defaultXTermOptions} from "@/components/baseConsole/BaseConsole"
import {XTerm} from "xterm-for-react"
import {YakitSystem} from "@/yakitGVDefine"
import {TerminalBox} from "./TerminalBox/TerminalBox"
import {System, SystemInfo, handleFetchSystem} from "@/constants/hardware"
const {ipcRenderer} = window.require("electron")

// 编辑器区域 展示详情(输出/语法检查/终端/帮助信息)

export const BottomEditorDetails: React.FC<BottomEditorDetailsProps> = (props) => {
const {setEditorDetails, showItem, setShowItem} = props

const systemRef = useRef<System | undefined>(SystemInfo.system)
useEffect(() => {
if (!systemRef.current) {
handleFetchSystem(() => (systemRef.current = SystemInfo.system))
}
}, [])

const {activeFile} = useStore()
// 不再重新加载的元素
const [showType, setShowType] = useState<ShowItemType[]>([])
Expand Down Expand Up @@ -181,7 +190,11 @@ export const BottomEditorDetails: React.FC<BottomEditorDetailsProps> = (props) =
[styles["render-show"]]: showItem === "terminal"
})}
>
<TerminalBox />
{systemRef.current === "Windows_NT" ? (
<div className={styles["no-syntax-check"]}>终端监修中</div>
) : (
<TerminalBox isShow={showItem === "terminal"} />
)}
</div>
)}
{/* 帮助信息只有yak有 */}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.terminal-box{
width: 100%;
height: 100%;
padding: 12px 0px 0px 12px;
background-color: rgb(49, 52, 63);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useEffect, useRef, useState} from "react"
import {} from "antd"
import React, {useEffect, useMemo, useRef, useState} from "react"
import {Modal} from "antd"
import {} from "@ant-design/icons"
import {useGetState, useMemoizedFn} from "ahooks"
import {NetWorkApi} from "@/services/fetch"
Expand All @@ -10,36 +10,121 @@ import classNames from "classnames"
import ReactResizeDetector from "react-resize-detector"
import {writeXTerm, xtermClear, xtermFit} from "@/utils/xtermUtils"
import {TERMINAL_INPUT_KEY, YakitCVXterm} from "@/components/yakitUI/YakitCVXterm/YakitCVXterm"
import useStore from "../../hooks/useStore"
import {YakitHint} from "@/components/yakitUI/YakitHint/YakitHint"

const {ipcRenderer} = window.require("electron")

export interface TerminalBoxProps {}
export interface TerminalBoxProps {
isShow: boolean
}
export const TerminalBox: React.FC<TerminalBoxProps> = (props) => {
const {isShow} = props
const {fileTree} = useStore()
const xtermRef = useRef<any>(null)
const [inputValue, setInputValue] = useState<string>("")
const [defaultXterm, setDefaultXterm] = useState<string>("")
// 是否允许输入及不允许输入的原因
const [allowInput, setAllowInput] = useState<boolean>(true)
const [failResult, setFailResult] = useState<string>("")
const [showModal, setShowModal] = useState<boolean>(false)

// 终端path为文件树根路径
const folderPath = useMemo(() => {
if (fileTree.length > 0) {
return fileTree[0].path
} else {
return ""
}
}, [fileTree])

// 写入
const commandExec = useMemoizedFn((cmd) => {
if (!xtermRef || !xtermRef.current) {
return
}
if (cmd.startsWith(defaultXterm)) {
cmd = cmd.replace(defaultXterm, "")
}
console.log("写入", cmd)

// const str = s.charCodeAt(0) === TERMINAL_INPUT_KEY.ENTER ? String.fromCharCode(10) : s
ipcRenderer.invoke("runner-terminal-input", folderPath, cmd)
})

useEffect(() => {
if (!xtermRef) {
return
}
const params = {}
setAllowInput(true)
setFailResult("")
// 启动
ipcRenderer
.invoke("runner-terminal-port", params)
.invoke("runner-terminal", {
path: folderPath
})
.then(() => {
success("终端监听成功")
if (folderPath.length) {
setDefaultXterm(`${folderPath}>`)
setInputValue(`${folderPath}>`)
writeXTerm(xtermRef, `${folderPath}>`)
}
})
.catch((e: any) => {
failed(`ERROR: ${JSON.stringify(e)}`)
})
.finally(() => {})
}, [xtermRef])

// 接收
const key = `client-listening-terminal-data-${folderPath}`
ipcRenderer.on(key, (e, data) => {
console.log("data---", data)

if (data.control) {
return
}

// if (data?.raw && xtermRef?.current && xtermRef.current?.terminal) {
// // let str = String.fromCharCode.apply(null, data.raw);
// xtermRef.current.terminal.write(data.raw)
// setHaveConnIn(true)
// }

// 先生成结果行 换行后 更改缓存新增输入行(结果行可能cd路径变化 需更改)
// writeXTerm(xtermRef, "result")
// writeXTerm(xtermRef, "\n")

// setDefaultXterm(folderPath + ">")
// setInputValue(folderPath + ">")
// writeXTerm(xtermRef, folderPath + ">")
})

const successKey = `client-listening-terminal-success-${folderPath}`
ipcRenderer.on(successKey, (e: any) => {
console.log("client-listening-terminal-success---")
})

// grpc通知关闭
const errorKey = "client-listening-terminal-end"
ipcRenderer.on(errorKey, (e: any, data: any) => {
setAllowInput(false)
setFailResult(data)
isShow&&setShowModal(true)
})
return () => {
// 移除
ipcRenderer.removeAllListeners(key)
ipcRenderer.removeAllListeners(successKey)
ipcRenderer.removeAllListeners(errorKey)
// 清空
xtermClear(xtermRef)
}
}, [xtermRef, folderPath])

// xtermClear(xtermRef)
// writeXTerm(xtermRef, defaultXterm)

const commandExec = useMemoizedFn((cmd: string) => {})

return (
<div className={styles["terminal-box"]}>
<ReactResizeDetector
Expand Down Expand Up @@ -89,8 +174,12 @@ export const TerminalBox: React.FC<TerminalBoxProps> = (props) => {
brightWhite: "#f6f7ec"
}
}}
isWrite={false}
// isWrite={false}
onData={(data) => {
if (!allowInput) {
setShowModal(true)
return
}
if (data.replace(/[\x7F]/g, "").length > 0) {
writeXTerm(xtermRef, data)
// 处理用户输入的数据
Expand Down Expand Up @@ -121,6 +210,17 @@ export const TerminalBox: React.FC<TerminalBoxProps> = (props) => {
}
}}
/>
{/* 终端关闭提示框 */}
<YakitHint
visible={showModal}
title='终端警告'
content={`终端 ${failResult} 被关闭`}
cancelButtonProps={{style: {display: "none"}}}
onOk={() => {
setShowModal(false)
}}
okButtonText={"知道了"}
/>
</div>
)
}
Loading

0 comments on commit 9b2cffc

Please sign in to comment.