feat: 网盘浏览下载 + 远程功能修复 + 连接状态同步 + Linux 图标打包
新增网盘功能 - FileServer 增加 GET /drive/meta|list|download, 每机长期 token 校验 + 目录穿越防护 - 新增 drive.ts 客户端: listDrive / getDriveRoot / downloadDriveFile / collectDriveFiles - ipc 暴露 drive:list|root|download|openFolder|pickDir, DB 增 drive_token 列 + ALTER 迁移 - 新增 DrivePanel.vue, 聊天框加"网盘" tab, 设置页加网盘分区 - 支持整目录递归下载并保持层级 修复远程功能 - 终端: 控制端收到的 output 帧被直接丢弃 (case 'output': return), 导致 xterm 全空白 - ChatServer: ws 构造即 listen, 'listening' 可能早于 start() 挂监听, 导致永久挂起 - USB: serverAttach 自行生成 sessionId 与控制端不一致 (数据帧查表落空); libusb 枚举误用 getDevices() (WebUSB 语义, 只返回已授权设备) 改 loadDevices(); control transfer 传数字 bmRequestType (node-usb v3 要字符串枚举); detachKernelDriver 挪到 selectConfiguration 之前 (否则 EBUSY) - 转发 UI: store 的 onOpened 是 no-op 致对方发起的转发不显示、无轮询致流量/TTL 不刷新、 对方发起的会话关不掉 (新增 closeSession, server 侧关闭需通知对端否则端口泄漏)、 入口/目标补归属标注、方向标签语义统一、监听端口输入框加宽 修复"在线却显示等待重连" - 根因: 启动时主进程先连上对端 (connectTo 早于 createMainWindow), device:wsState 在渲染层订阅前发出去被丢弃; 之后连接一直保持, 再无 open 事件 -> UI 永久停在等待重连 - 改为推全量快照 + 渲染层 mount 时主动拉取 (app:state); 渲染层先注册监听再 await - 通道语义改为 outgoing 或 inbound 任一 WS 活着即可用 (原来只看 outgoing) 修复 Linux 安装后没图标 - linux.icon 指向单张 PNG 时 app-builder 解析不出尺寸 (size=0), 图标被装进 hicolor/0x0/ 非法目录, 桌面环境找不到; 改为指向 resources/icons 目录 (8 个标准尺寸) - StartupWMClass 填的是 productName, 与窗口真实 WM_CLASS (可执行文件名) 对不上, 任务栏找不到启动器; 改为 local-net-msg 其他 - 新增 scripts/selftest 自测框架 (两个虚拟节点 + 真实 ChatServer/ChatClient), 30 条用例全过 - 重写 scripts/make-icon.js 生成多尺寸图标集 (原脚本引用的源图已不存在, sharp 依赖也缺) - 新增 docs/drive.md, docs/connection-status.md
This commit is contained in:
+72
-23
@@ -1,28 +1,77 @@
|
||||
// 把候选 logo 处理成 app icon:
|
||||
// - 转 PNG (白色背景填充为透明)
|
||||
// - 缩放到 1024x1024 (electron-builder 推荐)
|
||||
// - 顺便输出 256x256 给 renderer 用
|
||||
const sharp = require('sharp')
|
||||
// 生成 Linux 多尺寸图标集 -> resources/icons/<size>x<size>.png
|
||||
//
|
||||
// 为什么需要多尺寸: electron-builder 的 Linux 打包会把图标装进
|
||||
// /usr/share/icons/hicolor/<size>x<size>/apps/<executable>.png。
|
||||
// 如果 linux.icon 指向"单张 PNG", app-builder 解析不出尺寸 (返回 size=0),
|
||||
// 图标就被装到 hicolor/0x0/ 这种非法目录里, 桌面环境根本找不到 -> 安装后没图标。
|
||||
// 指向一个"目录 + <size>x<size>.png 命名"才能被正确识别。
|
||||
//
|
||||
// 用法:
|
||||
// node scripts/make-icon.js # 用 resources/icon.png 作为基准图
|
||||
// node scripts/make-icon.js <源图路径> # 用指定图片重新生成基准图 + 全套尺寸
|
||||
//
|
||||
// 依赖: ImageMagick 的 convert (生成结果已提交, 平时不需要跑这个脚本)
|
||||
const { execFileSync } = require('node:child_process')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
const SRC = path.resolve(__dirname, '..', 'resources', 'logo-candidate_004.jpg')
|
||||
const RES = path.resolve(__dirname, '..', 'resources')
|
||||
const OUT_DIR = path.join(RES, 'icons')
|
||||
const BASE = path.join(RES, 'icon.png')
|
||||
// hicolor 标准尺寸: 覆盖所有实际显示场景, 全部从 512 基准图缩小而来 (清晰不糊)
|
||||
const SIZES = [16, 24, 32, 48, 64, 128, 256, 512]
|
||||
|
||||
async function main() {
|
||||
const out1024 = path.resolve(__dirname, '..', 'resources', 'icon.png')
|
||||
const out256 = path.resolve(__dirname, '..', 'resources', 'icon-256.png')
|
||||
|
||||
// 缩放到 1024x1024, JPEG 白色背景保持 (Windows 图标习惯)
|
||||
await sharp(SRC)
|
||||
.resize(1024, 1024, { fit: 'cover', position: 'center' })
|
||||
.png({ quality: 95 })
|
||||
.toFile(out1024)
|
||||
|
||||
await sharp(SRC)
|
||||
.resize(256, 256, { fit: 'cover', position: 'center' })
|
||||
.png()
|
||||
.toFile(out256)
|
||||
|
||||
console.log('Generated:', out1024, out256)
|
||||
function haveConvert() {
|
||||
try {
|
||||
execFileSync('convert', ['-version'], { stdio: 'ignore' })
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(e => { console.error(e); process.exit(1) })
|
||||
function convert(args) {
|
||||
execFileSync('convert', args, { stdio: 'inherit' })
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (!haveConvert()) {
|
||||
console.error('需要 ImageMagick 的 convert 命令。')
|
||||
console.error('Debian/Ubuntu: sudo apt install imagemagick')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const src = process.argv[2]
|
||||
if (src) {
|
||||
// 指定了源图: 先把基准图做成 512x512 (最高精度, 往下缩都清晰)
|
||||
if (!fs.existsSync(src)) {
|
||||
console.error('源图不存在:', src)
|
||||
process.exit(1)
|
||||
}
|
||||
convert([src, '-resize', '512x512', '-background', 'none', '-gravity', 'center', '-extent', '512x512', BASE])
|
||||
console.log('基准图已更新:', BASE)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(BASE)) {
|
||||
console.error('基准图不存在:', BASE)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
fs.mkdirSync(OUT_DIR, { recursive: true })
|
||||
|
||||
for (const s of SIZES) {
|
||||
const out = path.join(OUT_DIR, `${s}x${s}.png`)
|
||||
// <= 基准尺寸的直接从基准图降采样 (只重采样一次, 小图标才清晰);
|
||||
// 超过基准尺寸的才放大, 放到最后单独处理
|
||||
if (s <= 256) {
|
||||
convert([BASE, '-resize', `${s}x${s}`, '-strip', out])
|
||||
} else {
|
||||
convert([BASE, '-resize', '512x512', '-background', 'none', '-gravity', 'center', '-extent', '512x512', out])
|
||||
}
|
||||
console.log('生成', path.relative(process.cwd(), out))
|
||||
}
|
||||
|
||||
console.log('\n完成。打包时用 linux.icon = "resources/icons" 指向这个目录。')
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user