4.0 KiB
| name | description | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| bricks-terminal-and-popup | Use when Wterm/.xterm terminal or PopupWindow resize breaks. |
|
Bricks 终端后端 + 弹窗 resize 踩坑
.xterm 终端后端(Wterm 控件 → SSH 远程命令/vi 编辑)
机制
.xterm文件是 Python 脚本(同.dspy语法),经 XtermProcessor 执行,返回 DictObject:{host, username, password/client_keys, cmdargs, noinput}。- Wterm 前端
new WebSocket(ws_url);ws_url用entire_url('/wss/<module>/xxx.xterm')(浏览器 WebSocket 构造函数自动把 https→wss,无需websocket_url)。 - nginx
location /wss/做 WebSocket 升级 + proxy 到 app 端口(proxy_set_header X-Forwarded-Path 'wss')。 - 后端 XtermProcessor → SSHServer → asyncssh
create_process(cmdargs)跑命令(如vi <文件>)。
asyncssh create_process 单 command bug(CRITICAL)
新版 asyncssh 的 create_process(command, *, ...) 只接受单个 command 位置参数,内部 create_session(session_factory, command, *, ...) 只有 2 个位置参数。
xtermProcessor.py 用 create_process(*login_info.cmdargs, ...) 展开列表,cmdargs=['vi', path] 两个元素 → TypeError: SSHClientConnection.create_session() takes from 2 to 3 positional arguments but 4 ...。
修复:.xterm 里 cmdargs 改成单个字符串:r.cmdargs = ['vi ' + shlex.quote(full_path)](不要 ['vi', path])。单命令无参(如 ['~/bin/sagelog'])不受影响。
config.json processors
website.processors 必须含 [".xterm","xterm"] 和 [".ws","ws"](及 .wss),否则 .xterm 端点在新环境 404 或当静态文件处理。提交进仓库 config.json 模板,不要手改生产机。
本地 SSH 编辑
.xterm 返回 host='localhost', username=<app 用户>, cmdargs=['vi <abs_path>'],依赖服务器 ~/.ssh 免密(authorized_keys)。验证:ssh localhost 'which vi'。
PopupWindow 右下角 resize 两个 bug
PopupWindow 构造器已强制 opts.resizable = true(popup.js),无需在 .dspy 显式设置。拖拽失效是另外两个 bug:
bug 1: resizing() 的 e.target 检查
resizing(e){
ele = this.resizable_w.dom_element;
if (ele != e.target && !ele.contains(e.target)){ // ❌ mousemove 的 e.target 随鼠标移动变化,拖出 30x30 resizebox 就 stop
this.stop_resizing(); return;
}
...
}
修复:删掉这段检查。resize_start_pos(mousedown)已用 contains(e.target) 保证起点在 resizebox 上,mousemove 期间不应再检查 e.target。
bug 2: resizebox z-index 被内容覆盖
.resizebox 默认 z-index: auto,而 Wterm/xterm 的 canvas/cursor-layer 在 DOM 靠后覆盖它 → mousedown 点不到 resizebox(document.elementFromPoint 命中 xterm-cursor-layer)。
修复:bricks.css .resizebox 加 z-index: 9999。
Wterm 光标
xterm.js cursorBlink 默认 false(光标静态 block 不闪烁,视觉上不明显)。Wterm 的 term_options 加 "cursorBlink": true 让光标闪烁可见。xterm 用 canvas renderer(rendererType:"canvas"),光标画在 canvas 上而非 .xterm-cursor DOM 元素——.xterm-cursor 为空是正常的。
DSPY 返回文件(下载/媒体流)
web.FileResponse 是 StreamResponse 子类,DSPY 的 handle() 里 isinstance(content, StreamResponse) 会直接返回它。所以 .dspy 可 return FileResponse(path, headers={'Content-Disposition': 'attachment; filename="..."'}) 直接提供文件下载/媒体流,无需 register function(如 idfile)。
验证方法
- resize:CDP
Input.dispatchMouseEvent模拟 mousedown→mousemove→mouseup,对比 popupgetBoundingClientRect尺寸变化。 - 命中元素:
document.elementFromPoint(x,y)确认点击点命中的是 resizebox 还是被内容覆盖。 - 终端连接:浏览器 console 看
ws msg=数据流 + vi 的 VIM 控制序列(\u001b[2;2R光标定位、\u001b[>0;276;0c设备属性、\u001b]10;...颜色查询)。