Expand WebCRT SFTP into a fuller file manager.

Add mkdir/rename/delete/chmod, multi-select batch ops, cancelable transfers with retries, per-tab paths, sorting, and safer listing limits.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-02 01:33:37 +08:00
parent d10ffed277
commit 9674de221d
10 changed files with 1146 additions and 153 deletions

View file

@ -1046,14 +1046,39 @@ const en = {
upload: "Upload",
uploaded: "Upload complete",
uploading: "Upload {{done}}/{{total}} · {{name}} {{pct}}",
downloading: "Download {{name}} {{pct}}",
downloading: "Download {{done}}/{{total}} · {{name}} {{pct}}",
downloaded: "Downloaded {{count}} file(s)",
downloadPartial: "Downloaded {{ok}}, failed {{failed}}",
uploadPartial: "Uploaded {{ok}}, failed {{failed}}",
retrying: "Retrying {{name}} ({{attempt}}/{{max}})…",
cancel: "Cancel",
dropHint: "Drop to upload into current folder",
dropEmpty: "No uploadable files found",
mkdir: "New",
mkdirPrompt: "New folder name",
mkdirInvalid: "Invalid folder name (no / or ..)",
mkdirOk: "Folder created",
rename: "Rename",
renamePrompt: "New name",
renameInvalid: "Invalid name (no / or ..)",
renamed: "Renamed",
download: "Download",
chmod: "chmod",
chmodPrompt: "Mode (e.g. 755 or rwxr-xr-x)",
chmodOk: "Permissions updated",
chmodPartial: "chmod ok {{ok}}, failed {{failed}}",
delete: "Delete",
deleteConfirm: "Delete {{name}}?",
deleteRecursiveConfirm: "{{name}} includes folders; non-empty folders will be removed recursively. Continue?",
deletePartial: "Deleted {{ok}}, failed {{failed}}",
deleted: "Deleted",
selectedCount: "{{count}} selected",
empty: "This folder is empty",
listTruncated: "Folder is large; showing first {{count}} entries (limit {{max}})",
dir: "dir",
loading: "Loading…",
enterHint: "Double-click to open folder",
downloadHint: "Click to download",
enterHint: "Click to select; Ctrl/Shift multi-select; double-click to open",
downloadHint: "Click to select; Ctrl/Shift multi-select; double-click to download",
colName: "Name",
colSize: "Size",
colMtime: "Modified",
@ -1091,6 +1116,8 @@ const en = {
sftpNeedPassword: "SFTP needs a saved SSH password (one-shot dialog passwords are not reused for files)",
sftpUnsupported: "This SSH session has no SFTP channel (device may not offer it)",
sftpTooLarge: "File exceeds size limit (default 512MB)",
sftpChmodInvalid: "Invalid mode (use 755 or rwxr-xr-x)",
sftpAborted: "Transfer cancelled",
queueDropped: "Terminal output too fast; about {{count}} chunk(s) dropped — transcript may be incomplete",
websocket: "WebSocket connection failed",
},

View file

@ -1043,14 +1043,39 @@ const zh = {
upload: "上传",
uploaded: "上传成功",
uploading: "上传 {{done}}/{{total}} · {{name}} {{pct}}",
downloading: "下载 {{name}} {{pct}}",
downloading: "下载 {{done}}/{{total}} · {{name}} {{pct}}",
downloaded: "已下载 {{count}} 个文件",
downloadPartial: "下载完成 {{ok}} 个,失败 {{failed}} 个",
uploadPartial: "上传完成 {{ok}} 个,失败 {{failed}} 个",
retrying: "重试 {{name}}({{attempt}}/{{max}})…",
cancel: "取消",
dropHint: "松开以上传到当前目录",
dropEmpty: "未识别到可上传的文件",
mkdir: "新建",
mkdirPrompt: "新建目录名称",
mkdirInvalid: "目录名无效(不要包含 / 或 ..)",
mkdirOk: "目录已创建",
rename: "重命名",
renamePrompt: "新名称",
renameInvalid: "名称无效(不要包含 / 或 ..)",
renamed: "已重命名",
download: "下载",
chmod: "权限",
chmodPrompt: "权限模式(如 755 或 rwxr-xr-x)",
chmodOk: "权限已更新",
chmodPartial: "权限更新 {{ok}} 个,失败 {{failed}} 个",
delete: "删除",
deleteConfirm: "确定删除 {{name}}?",
deleteRecursiveConfirm: "{{name}} 含目录,非空目录将递归删除,是否继续?",
deletePartial: "删除完成 {{ok}} 个,失败 {{failed}} 个",
deleted: "已删除",
selectedCount: "已选 {{count}} 项",
empty: "当前目录为空",
listTruncated: "目录条目过多,仅显示前 {{count}} 项(上限 {{max}})",
dir: "目录",
loading: "正在加载…",
enterHint: "双击进入目录",
downloadHint: "单击下载文件",
enterHint: "单击选中;Ctrl/Shift 多选;双击进入",
downloadHint: "单击选中;Ctrl/Shift 多选;双击下载",
colName: "名称",
colSize: "大小",
colMtime: "修改时间",
@ -1088,6 +1113,8 @@ const zh = {
sftpNeedPassword: "SFTP 需要已保存的 SSH 密码(会话弹窗密码不会用于文件传输)",
sftpUnsupported: "当前 SSH 会话未提供 SFTP(设备可能未开启)",
sftpTooLarge: "文件超过大小限制(默认 512MB)",
sftpChmodInvalid: "权限模式无效(请用 755 或 rwxr-xr-x)",
sftpAborted: "传输已取消",
queueDropped: "终端输出过快,已丢弃约 {{count}} 段,内容可能不完整",
websocket: "WebSocket 连接失败",
},