v0.1.6 — 多上游配置 + Star 弹窗 + 批量生图修复 + Android APK
v0.1.6 — 多上游配置 + Star 邀请弹窗 + 批量生图严重 bug 修复 + Android APK
这一版主要做了三件事:把上游配置从「Responses / Images 二选一」升级到「保存多个 profile 自由切换」,修了一组影响批量生图的严重 bug,以及首次发布 Android Phone / Pad 的 APK 产物。
下载
| 平台 | 产物 | 大小 |
|---|---|---|
| Windows x64 | image-studio-windows-amd64.exe |
~29 MB |
| macOS universal | image-studio-macos-universal.zip |
~15 MB |
| Linux x64 | image-studio-linux-amd64.tar.gz |
~15 MB |
| Android Phone(未签名) | image-studio-android-phone-unsigned.apk |
~21 MB |
| Android Pad(未签名) | image-studio-android-pad-unsigned.apk |
~21 MB |
Android APK 为 release-unsigned,首次安装需要在系统设置里允许「安装来自未知来源的应用」。后续会出签名版。
🎯 多上游配置(profiles)
以前只能存一份 Responses + 一份 Images,二选一切换。现在用户可以建任意多个 profile,每个完整保存 name / apiMode / baseURL / textModelID / imageModelID / concurrencyLimit + API Key(走系统凭据存储)。
- UpstreamConfigModal 双栏布局:左侧 profile 列表(新建 / 复制 / 删除 / 设为激活),右侧编辑表单
- HistoryRail 顶部 dropdown 快速切 active profile
- BASE_URL 输入框提示:只填站点根地址,应用自动拼接
/v1/responses//v1/images/generations//v1/images/edits,不要把 endpoint 路径手动贴进来 - 老用户透明迁移:启动时自动从老的
gptcodex.{responses,images}.*localStorage 键 + 老 keyring 项合成 1-2 个 profile,清理老格式 - 每个 profile 删除时,顺手清掉对应 keyring 凭据项,不留孤儿
🐛 批量生图严重 bug 修复
症状:一次生成 9 张时,历史栏点击 9 张里的不同项,canvas 总是只显示其中一张(常是最后一个 job 写盘的那张)。
根因:三层 bug 叠加:
- 后端文件名碰撞(真凶):timestamp 精度只到秒,9 个 job 同秒完成 → 9 个 savedPath 完全一样 →
os.WriteFile互相覆盖。9 个历史项的savedPath都指向同一个物理文件,前端无论点哪张读到的都是磁盘上幸存的那张。同样的碰撞也波及 raw SSE / Images API JSON 日志文件。修法:timestamp 后追加 6 字符 jobID 后缀 - 前端 CanvasStage useEffect deps 漏 blob:
[b64]改[blob, b64],blob-first 路线下两次切换 imageBlob 引用变了但 b64 字段不变,effect 不重跑画板就卡住 - HistoryRail 点击没退出批量结果 grid:刚生成完 9 张,grid overlay 罩着画板,在历史栏怎么点都只是切高亮项;现在点历史 = 显式单图选择,自动
closeResultGrid
老 batch 数据(v0.1.6 之前生成的):磁盘上前 8 张已经被最后一个 job 写覆盖丢失,无法恢复。新批量从此安全。
⭐ Star 邀请弹窗
- 首次成功生图后自动弹一次礼貌邀请(localStorage 标志防重弹)
- AppHeader 右上 GitHub 和 Settings 之间加 ★ 按钮,任何时候手动呼起
- 弹窗 UI 按 OS 分:macOS 渐变圆环 + 液态玻璃,Windows Fluent 紧凑卡片,Linux 通用 dashed accent
- 自动弹时标题「第一张图诞生了 🎉」,手动呼起时标题「支持一下 Image Studio」
🖼 历史栏图像加载修复
- 缩略图
loading="lazy"→"eager":Chromium native lazy 在滚动侧栏 +aspect-square容器里 IntersectionObserver 经常判错可见性,导致「鼠标 hover 才加载」 useBlobURL总传 imageB64 当 fallback(不只在 previewOnly 时):避免落到大 data URL 解析路径loadAllHistorycursor 走 createdAt 索引(之前是默认 primary key uuid → 反向遍历等于乱序),JS sort 兜底 —— 修历史侧栏顺序「抽象」的问题- BatchGridTile 用
imageBlob全分辨率优先(之前用 192px previewBlob,放大到 400+ px 糊得明显) - 快速连点历史项的 async 竞态:加 epoch ref 守卫,慢的 ReadImageAsBase64 resolve 后只在 epoch 没变时才提交
📥 导入图不再污染历史
拖入 / 粘贴的图生图源图之前会被当作 HistoryItem 存进历史栏,污染画廊也让「今日已生图」计数算高。改成跟旋转/翻转一样的 transient 操作:只更新 canvas + sources,不入历史。
🔧 上游错误友好翻译 + 查看日志
SSE / Images API 失败时,后端识别常见 OpenAI 错误码并转中文友好提示:moderation_blocked / content_policy_violation / rate_limit_exceeded / invalid_api_key / model_not_found 等。错误条幅加「查看日志」按钮直接打开本地原始响应 dump。
📁 macOS / Linux 默认输出目录
之前不管什么 OS 都走 os.UserConfigDir(),macOS 落到 ~/Library/Application Support/ 被 Finder 隐藏,Linux 落到 ~/.config/ 非日常路径。现在按平台分:
- Windows:
%APPDATA%\image-studio\(不变) - macOS:
~/Pictures/Image Studio/ - Linux:
~/Pictures/Image Studio/
OpenOutputDir 在调系统命令前先 MkdirAll,目录不存在时也能直接打开。
Android 首次发布
新增 Android Phone 和 Android Pad 两个 APK 产物(release-unsigned)。前端复用 macOS / Apple 视觉风格,适合平板大屏直接接入。
完整变更见 v0.1.5...v0.1.6 commit log。