Skip to content

Repository files navigation

EmberInn · 余烬酒馆

全新原生 Android 酒馆客户端——以 SillyTavern 兼容为核心,参考官方源码翻译重写,不做 WebView 壳,不搬运旧项目代码。

ember(余烬/炉火)+ inn(酒馆):每一个角色都是一炉火,故事在余烬里继续。

为什么重写(决策记录)

  • 放弃 RikkaHub fork 路线:酒馆格式属于“重实现”,与官方行为持续漂移,上游合并代价高,历史包袱重。
  • 否决“官方服务端当引擎”:源码实证——SillyTavern 的兼容内核(世界书扫描、宏展开、斜杠、提示词组装、群聊)全部位于前端 JSpublic/scripts/world-info.jsmacros/engine/slash-commands/script.js),与 DOM 焊死;Node 服务端只是存储 + API 转发层。只保留服务端并不能白拿兼容性。
  • 否决 WebView 壳:要求真原生客户端与全新 UI,不套官方网页。
  • 最终路线:新项目、Kotlin + Compose、参考官方源码翻译 + 重写酒馆逻辑层;官方 Node 服务端仅作为可选的存储/API 辅助进程(无浏览器界面)。

兼容目标(以官方行为为基准,回归测试锁定)

  • 角色卡:PNG V2/V3(tEXt/ccv3)与 JSON 导入导出(对齐官方:官方只导出 PNG/JSON)、CharX/YAML/BYAF 导入、从 URL 导入(对齐官方 content-manager)、V3 assets(icon/background/voice)
  • 世界书:关键词扫描、注入位置(before/after char)、深度、递归、粘性/冷却、分组评分、向量化、全字段(secondary_keys/insertion_order/selective/priority/probability/delay)、三级世界书(全局 / 会话 / 角色)
  • 宏系统{{user}}{{char}}{{random}}{{pick}}{{roll}}{{if}}、变量宏等(对齐 Macros 2.0)
  • 斜杠命令:官方常用命令全量,行为一致
  • 群聊:多角色、多种响应模式
  • 提示词组装:角色字段 + 示例对话 + 世界书 + 作者注释 + 历史消息(与官方 script.js 行为一致)
  • 预设 / 人设 / regex 脚本 / tokenizer / SSE 流式

组件清单见 docs/COMPONENTS.md(有现成/没现成分表)。官方数据格式总表见 docs/FORMATS.md(5 种导入/导出对齐现状)。PNG 卡片内嵌规范见 docs/PNG_FORMAT.md(官方 1:1)。功能覆盖总清单见 docs/FEATURES.md(对照官方 release 8172dcd,含优先级与 UI 映射)。本地官方源码:~/sillytavern-ref(release 分支,供翻译与回归对照)。

人性化操作守则(最高优先级)

做这个 App 的初衷:多数开源项目功能强但操作逻辑反直觉。以下守则对所有界面生效,是验收标准,不是建议。

  1. 打开即聊:导入卡或「直接开始聊天」前,不需要先研究设置;没配模型时给友好引导(“先选一个模型”→ 一键跳转模型页),而不是报错
  2. 一步到位:导入角色卡自动带世界书 / 主题 / 开场白,直接可聊,不需要再手动挂载任何东西
  3. 默认值合理:所有设置默认即可用;高级项默认收起,绝不一上来要求用户配置
  4. 全中文 + 官方术语括号:按钮、设置、报错全中文;官方英文术语保留括号,方便对照社区资料
  5. 人话报错:错误只说人话(“网络不通,请检查地址或 Key”),不抛代码/裸异常;能重试的一键重试
  6. 可撤销、有确认:删除角色 / 聊天 / 世界书条目二次确认;误操作能撤销或恢复
  7. 手势符合直觉:返回手势、长按菜单、滑动切回复、下拉刷新——跟主流 App 的直觉一致,不发明新手势(交互参考 AI 陪伴类标杆:Character.AI 式沉浸对话、微信式返回/长按)
  8. 搜索无处不在:角色、会话、世界书条目、设置项全部可搜索(设置搜索尤其重要)
  9. 状态可见:生成中(流式 + 停止按钮)、导入进度、后台任务通知,每一步都有反馈
  10. 空状态引导:任何空页面都给出“下一步做什么”的按钮,绝不白屏
  11. 数据透明:导出路径中文提示(“已导出到 下载/EmberInn”);备份位置可见;数据默认只存本地
  12. 不做功能陈列馆:默认界面只放高频操作,低频功能收进菜单;新功能不堆按钮

架构

app        Compose UI(角色列表、聊天、设置、主题)
engine     酒馆领域引擎(纯 Kotlin,不依赖 UI)
           ├─ 领域模块(各带官方差分):CardParser / WorldBookScanner / MacroEngine /
           │   SlashParser / RegexEngine / 提供商转换器 / 媒体 / 群聊 / 表情 …
           └─ 编排层(总装入口):PromptPipeline —— 对齐官方 prepareOpenAIMessages,
               一个入口把 世界书扫描 + 人设 + 作者注释 + 示例 + 历史 + 控制提示
               组装成最终 CompletionMessage;只编排不写算法(算法都在领域模块)
data       Room / DataStore / 文件存储
provider   LlmProvider 接口 + 服务商注册表(数据驱动 JSON)
services   TTS / STT / 图像 / 向量 / 翻译 接口
theme      全局主题 + 角色卡驱动主题

关键接口(可插拔,不写死核心)

接口 说明
LlmProvider OpenAI-compatible / Anthropic / Gemini / 自定义,协议实现类很少变
CardParser V2 / V3 / CharX,为未来 V4 留口子
TtsProvider / ImageGenProvider / VectorStoreProvider / TranslatorProvider 后端可插拔
ThemeSource 全局预设 / 角色卡取色
扩展执行层 先做自己的插件 API;ST 前端扩展兼容按三分类分级推进(见下),不承诺全兼容

ST 扩展兼容三分类(对照社区扩展调研后分级)

  1. 纯逻辑类(regex 脚本、宏计算、部分记忆/摘要逻辑,不碰 DOM):QuickJS 沙箱 + ST 全局 API shim(getContext() / eventSource / chat / generateRaw()),目标“自动可跑”
  2. 轻量 UI 类(只在设置抽屉加开关/滑块的插件):逻辑复用 QuickJS,UI 原生重绘,为每个目标插件写设置读写适配层(非自动兼容)
  3. 结构性不兼容(依赖 ST Node 服务端插件、ST-Extras Python 服务、复杂 DOM 交互如拖拽面板/节点编辑器):明确排除,必要时提供原生重实现替代 开发顺序:先对官方及社区扩展做 DOM 依赖/服务端依赖分类统计,按占比定投入优先级。

服务商注册表(数据驱动)

每条记录为数据而非代码:id / display_name / protocol / auth_type / base_url / region_variants / extra_headers / api_version / models_endpoint / default_models / requires_key

注册表现有 22 家(2026-08-07 联网核实 + 官方 chat_completions.js 端点对照): OpenAI(gpt-5.5 / 5.4)、Anthropic(claude-opus-5 / sonnet-5 / haiku-4-5)、 Gemini AI Studio / Vertex(gemini-3.6-flash / 3.5-flash / 3-pro)、DeepSeek(deepseek-v4-flash / pro,官方走 /beta)、 OpenRouter、Groq、Ollama(本地)、Mistral、xAI(grok-4.3)、Moonshot(kimi-k3)、 智谱(glm-5.2)、通义 DashScope(qwen3.7)、硅基流动(国内/国际)、Z.AI(通用/编码)、 MiniMax(国际 minimax.io / 国内 minimaxi.com)、Fireworks、Perplexity(无 /models,走最小对话探测)、 Cloudflare Workers AI(账户 ID + /ai/v1)、Azure OpenAI(deployment + api-version 2024-12-01)、火山方舟(豆包 Seed 2.1)、自定义。 模型列表拉取按官方 /status 逻辑实现:openai data[].id、google models[].name(过滤 generateContent)、 workers result[].name、azure value[].id;拉不到时用 default_models 兜底。

远期:注册表可做成远程可更新(版本号 + 增量拉取),新厂商无需发版。

UI 与主题

设计规范

  • Material 3 Expressive + 动态取色 + 移动优先分层导航
  • 信息架构:底部导航(角色 / 聊天 / 设置)+ 独立二级设置页;不照搬 ST 桌面多面板
  • 大屏自适应:手机单栏底部导航;平板 / 折叠屏双栏(列表 + 聊天)
  • 渲染:Markdown(mikepenz renderer 0.43.0)、LaTeX(huarangmeng/latex)、代码高亮(Highlights)、图片/GIF(Coil3 + coil-gif)、音视频附件(Media3 ExoPlayer 1.10.0)、Mermaid / 复杂 HTML 用局部 WebView 兜底、流式消息增量渲染

主题系统三层结构

第一层 全局主题(用户设置):浅色 / 深色 / 跟随系统 + 预设主题 + 视觉氛围(标准/柔和/清冷/明快/自定义:饱和度、冷暖、光效)+ 字体(系统/衬线/霞鹜文楷下载)/ 圆角 / 密度 / 气泡样式 / 背景模糊开关
第二层 角色卡驱动(核心卖点):每张卡一套观感 —— 配色 / 背景 / 气泡色 / 名字色 / 形状 / 字体
第三层 状态微调:流式生成微光、深水区/夜间可单独锁深色
优先级:角色卡 > 全局预设 > 系统默认

配色流程(角色卡接管主题)

  1. 卡图 → Palette 取色(浅色取 Muted 低饱和色,深色取 Vibrant 高饱和色)
  2. 取到的颜色作为 seed → MaterialKolor 生成整套 M3 配色(light / dark 两套)
  3. 无头像卡 / 未取到色 → 用卡名哈希生成稳定 seed 色(可复现、每卡不同)
  4. 显式主题配方 seed 优先级最高;结果随卡持久化
  5. 切换角色:配色 animateColorAsState 过渡 + 背景 crossfade(200–300ms)

背景系统(敲定)

  • 默认 = 氛围渐变:从卡图取 2–4 个颜色 → 低饱和 Mesh Gradient + 光晕(不是主图,是主图的光),浅色/深色下都干净
    • 实现:官方 androidx.compose.ui.graphics.MeshGradient(已入 Compose UI,无需第三方库);动画版参考 ComposeMeshGradient
  • 可选 = 卡图玻璃背景:主图 + 模糊 + 遮罩(深色叠 60–75% 暗色,浅色叠 25–35% 白/纸色),保证文字可读
  • 未设显式背景时,角色头像自动作为玻璃背景(模糊 + 遮罩);显式背景(会话/主题配方)优先级最高
  • 遮罩可全局设置:头像玻璃开关 / 模糊五档(无/轻/标准/重/极) / 深色遮罩颜色+强度 0-90% / 浅色遮罩颜色+强度 0-60% / 一键恢复默认(外观与主题 → 视觉与质感)
  • 每张卡独立记忆,可随时切换 / 关闭

玻璃表面(2026 液态玻璃方向)

  • 顶栏 / 输入栏 / 浮层 / 对话框:blur + 半透明 + 1px 高光描边 + 轻微内阴影
    • 实现:skydoves/Cloudy(KMP 模糊 + 液态玻璃,GPU 加速 + 旧设备 CPU 降级);备选 Haze(可调降采样)、miuix-blur(自适应降采样)
  • 正文区保持干净,不全屏玻璃(可读性优先)
  • 依据:iOS 26 Liquid Glass 引发全行业跟进,国产安卓 2026 年集体上新玻璃 UI;安卓官方暂不跟进 → 第三方 App 的差异化机会

四维主题配方(颜色 + 形状 + 动效 + 排版)

  • 形状:每张卡可带 圆润 16dp / 方正 4dp / 浑圆 24dp
  • 动效:M3 Expressive spring 弹性动效
  • 字体:中文氛围字体可下载(霞鹜文楷、思源宋体等),默认系统字体
  • 表面染色:背景表面带角色主色 tint(Android 16 / Expressive 方向),纯黑仅作可选

预设主题(按中国人审美)

主题 风格 浅色底 深色底 点缀色
墨韵 水墨风 宣纸白 墨黑 朱砂红
青瓷 雅致 米白 青墨 青绿
夜航 沉稳 雾白 深蓝黑 琥珀
丹砂 热烈 纸白 暖黑 丹红
琉璃 现代玻璃 冰白 玻璃黑 渐变紫蓝
简约纸感 极简 象牙白 石墨 中性灰
酒馆官方 SillyTavern 默认 象牙米白 墨黑 #171717 青绿 + 引用橙
竹青 竹林晨光 米绿 竹墨 青绿
暮紫 黄昏暮色 淡紫白 暮黑 紫 + 暖橙
晨雾 雾蓝清冷 雾白 深蓝灰 雾蓝
樱粉 樱色温柔 粉白 樱黑 粉 + 淡紫

默认偏好(中文用户操作习惯)

  • 默认浅色(暖纸色底,不用纯白 #FFFFFF),深色“跟随系统”可选
  • 消息布局:AI 纯文本流(无气泡,纸面阅读感)+ 用户右侧胶囊(AI 陪伴对话路线,参照 Character.AI);头像 / 名字 / 时间戳左对齐;最后一条 AI 常驻快捷按钮,历史消息长按操作
  • 底部导航 + 返回手势 + 下拉刷新 + 长按菜单(复制 / 编辑 / 删除 / 重新生成 / 滑动切回复)
  • 设置项中文为主,字号调节、夜间模式自动、免打扰
  • 分享 / 导出路径用中文提示(“已导出到…”)

动态色基线

  • 未导入卡 / 未取色时:全局默认跟随系统壁纸动态色(Material You)
  • 角色卡 seed 优先覆盖:显式配方 seed > 头像取色 / 名字哈希 > 全局预设

主题配方可分享

  • 每张卡的完整配方(seed + 背景 + 形状 + 字体)可导出 / 导入 / 分享

主题组件清单(最强现成件)

用途 组件 坐标
主题框架 Material3 基线 1.4.0 稳定版(Expressive 组件在 1.5.0-alpha,等稳定后再启用) androidx.compose.material3:material3
种子色 → M3 配色 MaterialKolor 4.1.x 稳定版(勿用 5.0 alpha) com.jordond.materialkolor:*
氛围渐变 官方 MeshGradient(动画版参考 ComposeMeshGradient) androidx.compose.ui.graphics.MeshGradient
玻璃 / 模糊 skydoves/Cloudy 0.7.1 稳定版(GPU + 旧设备 CPU 降级);备选 Haze、miuix-blur com.github.skydoves:cloudy:0.7.1
卡图取色 Palette / landscapist-palette androidx.palette:palette
图片加载 Coil 3 io.coil-kt.coil3:coil-compose
图标 Phosphor Icons(内置官方路径,见 scripts/gen-phosphor-icons.mjs) app/.../ui/icons/PhosphorIcons.kt
中文字体(可下载) 霞鹜文楷 Screen/Lite、霞鹜新晰黑(OFL 开源) 可下载字体包 / Google Fonts Provider
主题切换动画 animateColorAsState + Crossfade 内置
持久化 Room + DataStore androidx

实现要点与坑

  1. 取色必须在 IO 线程跑一次并缓存,禁止 UI 线程执行
  2. 背景模糊用 1/4 尺寸位图,禁用原图,避免滚动掉帧
  3. 所有背景上的文字必须叠遮罩(浅色卡图 + 白字 = 灾难)
  4. 主题数据(seed / 背景 / 形状 / 字体)跟随角色卡导入导出
  5. 设置页做实时预览(选主题直接看到效果)
  6. MaterialKolor 已移除 Expressive 支持(4.0+):配色走基线 M3,Expressive 只做组件/动效层,两者不冲突
  7. 生产依赖 M3 1.4.0 稳定版;Expressive 组件(1.5.0-alpha)仅在尝鲜分支启用,不进入主线
  8. 中文字体用屏幕版/轻便版(霞鹜文楷 Screen/Lite),完整版体积过大,作可下载项

格调守则(好看、有格调、不花哨)

  1. 配色系统 = 1 个主色 seed(生成整套 M3 色调,约 20+ 色值,和谐由源头统一);背景氛围 = 取 2–4 个低饱和色(负责丰富与辨识度)——界面克制、背景出彩
    • 可选“副 seed”:取卡图第二主色降饱和作 tertiary(第三色),默认关闭,防花哨
  2. 背景氛围渐变一律低饱和(取色后降饱和 30–40%),光晕克制;禁止高饱和霓虹渐变球(2026 已俗)
  3. 玻璃效果只用于浮层 / 输入栏 / 顶栏,正文区永远干净;同屏玻璃元素不超过 2–3 处
  4. 每屏只有一个视觉焦点:角色图或聊天内容,不叠加抢眼
  5. 动效 200–300ms,spring 只用于交互反馈;常驻动画仅限生成微光
  6. 深色默认 tinted 灰(Android 16 方向),纯黑仅作可选
  7. 排版 2–3 档字号、行高 1.5–1.6、对比度达标
  8. 默认配方保持克制;用户自定义“花哨”是用户自由,但不进默认主题
  9. 默认系统字体;氛围字体(霞鹜文楷等)作可下载可选

美学设计原则(2026 调研落盘)

高级感 = 克制(Quiet Luxury,2026 主流方向)

  • 奢侈品设计的信号不是装饰,是留白、清晰层级、有限色彩强调、克制对比——安静界面没有地方藏弱层级
  • “极简做对”的标准:3 色上限、排版当主角、留白是主动设计(不是空白)
  • 每屏一个强调方向(one accent direction at a time),一次只突出一个东西

色彩

  • 界面主色 3 色以内:1 个 seed 生成的主色 + 中性底色 + 背景氛围的低饱和色
  • 低饱和 = 高级;高饱和只做点缀(按钮/链接/名字色),面积越小越好
  • 预设主题对应情绪:墨韵=水墨留白 · 青瓷=雅 · 夜航=沉稳 · 丹砂=热烈但克制 · 琉璃=现代玻璃 · 简约纸感=quiet luxury · 酒馆官方=SillyTavern 1.18 默认(public/style.css :root 核对)· 竹青=清新 · 暮紫=沉静 · 晨雾=清冷 · 樱粉=温柔

中文美学基因(留白/水墨/雅)

  • 中国 UI 设计的传统是“计白当黑、以无胜有”:视觉焦点靠留白引导,不靠装饰堆砌
  • 水墨的用法:黑白灰墨韵打底 + 少量朱砂级点缀,不堆具象元素
  • 聊天页应是大面积留白 + 低饱和氛围光 + 少量角色色强调——这就是“雅”

排版

  • 全 App ≤ 2 种字体(默认 1 种系统黑体 + 可选氛围字体);每屏 ≤ 3 种字重/字号组合
  • 字号、字重、颜色是建立层级的三个杠杆,优先于一切装饰
  • 中文行高 1.5–1.6,正文 16sp,标题 20–24sp,说明 12–13sp

动效与材质

  • 柔和动效(soft motion):200–300ms,一次只动一个东西;spring 仅用于交互反馈
  • 材质诚实:玻璃只做表面(浮层/输入栏/顶栏),正文区永远干净;阴影/光晕克制
  • 生成微光是唯一允许的常驻动画,亮度低、节奏慢

UI 质感提升执行清单(2026-08-09 融合落盘)

来源:EmberInn-UI质感提升方案。问题诊断:功能流畅、M3 规范,但"任何一个 M3 App"的既视感。根本原因:处处用 M3 组件默认值(默认圆角/阴影/字体/算法直出配色),规范只保证"正确",不保证"有态度"。本清单是在规范之上加一层专属的视觉偏好。 验收自查:截图盲测——和任意有质感的 App 并排对比阴影软硬/图标粗细/间距节奏/饱和度。

第一批(纯技术、无设计风险,先做)

  1. 阴影升级新 APIModifier.dropShadow()/innerShadow()(color/radius/spread/offset/brush),阴影色用元素自身颜色深色版而非纯黑;开工前确认 API 在锁定 Compose 版本脱离 experimental,未稳定则用社区 coloredShadow 兜底
  2. 组件走主题强调色:全局检查 SwitchDefaults.colors() 等 M3 组件颜色是否接角色/主题动态色,而非默认
  3. 触觉反馈铺满关键交互LocalHapticFeedback.performHapticFeedback() 按语义匹配(确认用 Confirm、开关用 ToggleOn/Off、删除用 Reject、点选用极轻反馈);覆盖发送/切换角色/删除确认/开关
  4. 骨架屏替换转圈 Loading:自写 shimmerEffect()(rememberInfiniteTransition + 扫光渐变,约 20 行),颜色跟随角色主题色而非灰色默认(现成库灰骨架无法适配动态取色)
  5. 首页角色卡直接用取色结果做底色:取色系统已接(seedColor),卡片底色必须体现"每角色专属氛围",禁止统一灰白底
  6. 声音反馈:已按用户要求移除(2026-08-11,不再实现)

第二批(需设计判断) 7. 字体真正落地:氛围字体(霞鹜文楷/思源宋体)不只"可下载",角色名/旁白优先接入,正文保持清晰无衬线 8. 形状语言区分角色:每卡圆润 16dp / 方正 4dp / 浑圆 24dp 形状真正在跑,禁止全局统一 M3 默认 12dp 9. 六套预设主题各自独立性格:不只换 seed 色——间距节奏/动效速度/形状语言也随性格变(墨韵留白大动效慢、丹砂利落动效快) 10. 算法取色后加统一滤镜:MaterialKolor 输出后统一降饱和一档 + 背景叠专属冷灰/暖灰 tint,让任何 seed 出来的颜色都带统一气质 11. 空状态设计:替换"暂无数据"默认文案/灰图标,用有语气的文案 + 克制的轻动效,覆盖首页无卡、聊天无记录 12. 设置页重新设计:避免"图标+文字+箭头"机械通栏,按语义分组独立卡片区块、组间留白、分组标题样式化

第三批(排版与一致性) 13. 排版层级大胆:标题/正文字号级差、字重跳跃更鲜明(Bold 直跳 Light),层级对比 = 经过设计 14. 图标一致性:全局排查混用 Icons.Default.xxx(Material 内置)与 Phosphor 的情况,统一 Phosphor

执行原则:每次只集中做一到两项深做,做完验证再推进;MeshGradient 与新阴影 API 有版本 churn 风险,接入前先用最小 spike 验证 API 在锁定版本可用。

版本策略(尽量用最新版)

  • 生产依赖一律使用当前最新稳定版;仅有 alpha/beta 才支持的功能放“尝鲜分支”或功能开关,不进主线
  • 2026-08 实测基线:Compose BOM 2026.06.01 · Kotlin 2.4.10 · material3 1.4.0(Expressive 1.5.0-alpha25 仅尝鲜)· MaterialKolor 4.1.x(5.0 为 alpha,不用)· Coil 3.5.0(+coil-gif)· Media3 1.10.0 · DataStore 1.2.1 · activity-compose 1.13.0 · OkHttp 5.4.0 · multiplatform-markdown-renderer 0.43.0 · Palette / Room / Navigation 跟最新稳定版
  • 升级流程:Renovate / Dependabot 每周自动 PR → CI 通过自动合 patch/minor → major 人工看 changelog + 全量回归
  • 小库失活预案:直接把开源源码搬进项目(vendoring),不守死库

首页设计(对照 NativeTavern 优化)

NativeTavern 的问题(源码核实:home_screen.dart):AppBar + 一长串 ListTile 卡片 + 一个 FAB;首页=纯聊天列表,无层级、无氛围、无搜索、角色藏在二级页,默认深色。

EmberInn 首页(余烬美学)

┌──────────────────────────────┐
│  ✦ 余烬酒馆           [导入] │ ← 标题字 + 毛玻璃顶栏
│  🔍 搜索角色 / 会话 / 世界书  │ ← 全局搜索
│ ┌──────────────────────────┐ │
│ │ ✨ AI 对话(玻璃渐变卡)   │ │ ← 置顶:无卡直接聊
│ └──────────────────────────┘ │
│ 最近聊过(横向卡片:头像+名字)│ ← 1 秒续聊
│ ── 我的角色 ──               │
│ ┌────┐ ┌────┐ ┌────┐        │
│ │卡图 │ │卡图 │ │卡图 │        │ ← 双列卡片网格:卡图为主角
│ │名字 │ │名字 │ │名字 │        │    名字 + 最近消息预览
│ └────┘ └────┘ └────┘        │
│              [+ 导入角色卡]   │ ← FAB
└──────────────────────────────┘
    [角色]    [聊天]    [设置]

优化点对照

  1. 首页=角色书架,不是聊天列表;聊天列表移到底部「聊天」Tab
  2. 角色卡是视觉主角:卡图大卡片 + 名字 + 最近消息,主题色点缀,每张卡一眼不同
  3. 搜索置顶且全局(角色/会话/世界书/设置)
  4. 「AI 对话」玻璃渐变卡置顶,空状态双按钮(导入卡 / 直接聊天)
  5. 最近聊过横向滑,兼顾续聊效率
  6. 默认浅色暖纸底 + 氛围渐变 + 毛玻璃顶栏,克制动效
  7. 卡片交互:点卡片=进聊天(主操作);长按=快捷菜单(置顶/新会话/编辑/导出/删除);右上角「⋯」=同一菜单的显式入口——卡片下面不放按钮排,保持卡面干净

启动与首启体验

首次打开(Onboarding)

  • 开场:欢迎页直接淡入(Compose 动画,约 1.6 秒后显示内容);仅首次,之后不再播放
  • 欢迎页:「欢迎来到余烬酒馆」+ 副标题“每个角色都是一炉火,故事在余烬里继续”
  • 两个主选项(玻璃卡片,大按钮,低饱和氛围渐变背景):
    • 「导入角色卡」→ 直接打开文件选择器(PNG / JSON / CharX)
    • 「直接开始聊天」→ 进入「AI 对话」并带一句默认开场(“我是余烬,想聊点什么?”)
  • 底部一行小字:数据仅保存在本地(信任信号)
  • 允许「跳过」→ 进入角色列表空状态

日常打开

  • 启动无黑屏、无图标动画:直接进入角色列表(按用户要求不搞开头动画)
  • 直接进角色列表首页:AI 对话(置顶)→ 最近聊过 → 全部角色
  • 设置可选:「启动时直接进入上次聊天」(默认关)

新建空白聊天

  • 角色列表置顶「AI 对话」:点开即新会话
  • 聊天 Tab:「+」新建对话(默认 AI 对话,可改选角色)
  • 角色内:顶栏菜单「新会话」,每个角色可开多个空白会话
  • 空白聊天 = 无历史的新会话;主题沿用当前角色配方或全局主题

信息架构总图(功能放哪)

角色 Tab(首页)
├─ 搜索:角色 + 会话 + 世界书 + 设置(全局搜)
├─ AI 对话(置顶)
├─ 最近聊过(横向卡片)
├─ 全部角色(长按 = 置顶 / 编辑 / 导出 / 删除)
└─ FAB:导入角色卡

角色详情页(入口:聊天页 ⋮ →「角色详情」,或角色列表长按 →「编辑」)
├─ 基本信息:名字 / 头像 / 标签 / 版本 / 作者
├─ 卡字段(**分字段展示,每字段一行**:标签 + 预览 + 点击展开编辑):
│   描述 / 性格 / 场景 / 开场白(含备选)/ 示例对话 / 系统提示 / PHI / 创作者备注
├─ 扩展字段:extensions / depth_prompt / assets(图标/背景/语音)/ skip 系列
├─ 世界书(该卡)
├─ 正则 / 变量(该卡)
├─ 模型覆盖(可选,默认收起)
├─ 主题配方
└─ 会话列表 / 新会话 / 导出 / 删除

聊天页
├─ 顶栏:返回 + 角色名 + ⋮
├─ 消息流:长按 = 复制 / 编辑 / 重新生成 / 继续生成 / 删除(AI 消息多“冒充”);左右滑 = 切换回复;点选气泡浮现小操作条
│    ├─ **折中交互(默认)**:最后一条 AI 消息下方常驻小按钮(复制 / 重新生成 / 继续 / 删除)——高频操作集中在最后一条;历史消息保持干净
│    └─ **设置开关**:常驻按钮模式(每条都显示,旧项目习惯)/ 沉浸模式(全隐藏)
├─ 输入区:+(附件 / 语音) [输入框] 🎤 ➤(生成中变 ■)
└─ ⋮ 菜单:人设 / 作者注释 / 预设 / 世界书快捷 / 统计 / 主题背景 / 导出聊天

聊天 Tab
├─ 全部会话(按时间;长按 = 置顶 / 删除 / 导出)
└─ +:新建对话 / 新建群聊(勾选已有角色)

设置 Tab
├─ 外观与主题 / 提供商与模型 / 语音 / 服务 / 数据与隐私 / 关于
└─ 顶部设置搜索

统一规则
├─ 任何功能 ≤ 3 步可达;一个功能只有一个“家”(不重复摆放)
├─ 长按承载高频操作;删除统一二次确认
├─ 空状态给“下一步”按钮;报错说人话
└─ 平板 / 折叠屏:双栏 + Navigation Rail,逻辑不变

设置架构(两级:主设置 + 角色设置)

主设置(底部导航「设置」Tab)=所有人的公共环境
├─ 外观与主题:浅/深/跟随、全局预设主题、字体、圆角密度、背景模糊、启动行为
├─ 提供商与模型:连接档案(地址/Key)、全局默认模型、默认采样参数、代理
├─ 语音:TTS 朗读、STT 语音输入
├─ 服务:翻译、图像生成、向量库、搜索
├─ 快捷回复:全局预设 + 槽位(官方 Quick Reply 字段,输入区快捷盘执行)
├─ 数据与隐私:存储位置、备份/导出、清缓存
└─ 关于:版本、许可、开源仓库

角色设置(每张卡单独,从角色详情页进)=只管这一个角色
├─ 角色信息:名字/头像/卡字段(描述、性格、场景、示例对话、系统提示、PHI…)
├─ 世界书:内嵌(导入随卡带入)+ 可挂外置
├─ 正则 / 变量:本角色专用
├─ 模型覆盖(可选,默认收起):连接档案、采样、上下文长度
├─ 主题配方:seed、背景、形状、字体、风格档位、浅/深锁定
└─ 会话:聊天列表、新会话、导出

「AI 对话」=无卡角色,同样有自己的角色设置页(名字/头像/系统提示词/世界书/模型覆盖/主题)

重叠项规则:模型、正则、世界书、预设 = 默认“跟随全局”,角色页可“本角色覆盖”;主题 = 默认跟随全局,角色卡自动生成配方覆盖,可一键恢复;卡字段 = 只属于角色,主设置不出现。

消息操作按钮(官方高频对照 + 图标)

官方源码确认的消息级操作:继续生成(mes_continue)、冒充(mes_impersonate)、停止(mes_stop)、重新生成、删除(二次确认)、书签、编辑、滑动切换、复制、TTS 朗读、token 统计;输入区可选快捷「继续 / 冒充」(power-user quick_continue / quick_impersonate)。

功能 官方出处 图标(Phosphor) 位置
复制 hover 按钮 Copy 最后一条常驻 + 长按菜单
重新生成 option_regenerate ArrowsClockwise 最后一条常驻 + 长按菜单
继续生成 mes_continue / quick_continue CaretDoubleRight 最后一条常驻 + 长按菜单 + 输入区快捷(可选)
删除 option_delete_mes(二次确认) TrashSimple 最后一条常驻 + 长按菜单
编辑 hover 按钮 PencilSimple 长按菜单 / 选中操作条
冒充 mes_impersonate / quick_impersonate MaskHappy 长按菜单(AI 消息)+ 输入区快捷(可选)
滑动切换 swipe 手势左右滑(菜单可加 CaretLeft/CaretRight 手势为主
书签 option_new_bookmark BookmarkSimple 长按菜单
TTS 朗读 hover 按钮 SpeakerHigh 长按菜单
token 统计 option_toggle_logprobs ChartBar 长按菜单
更多 DotsThree 卡片/气泡右上角(显式入口)
停止 mes_stop Square 输入区(生成中)

规则:气泡本身无按钮;最后一条 AI 消息常驻 4 键(复制/重生成/继续/删除);完整操作收长按菜单;图标统一 Phosphor Regular、24dp、onSurfaceVariant(激活 primary)。

渲染与消息排版(高级渲染)

官方对照:核心 = Showdown(Markdown)+ highlight.js(代码高亮)+ DOMPurify(HTML 消毒);LaTeX / Mermaid 官方靠社区扩展,我们原生覆盖。

  • 消息排版主题(可配):引号(blockquote)变色 + 斜体变色——引用块左栏/底色用角色主题色,斜体用柔和 tint;每张卡可带“消息样式”配方(引用色 / 斜体色 / 代码块风格 / 字号 / 行高)
  • Markdown 全量:标题、粗体、斜体、引用、行内代码、代码块(Highlights 高亮)、表格、链接、图片(Coil)、列表、任务列表、删除线
  • 数学公式:LaTeX(huarangmeng/latex)
  • 图表:Mermaid → 局部 WebView 兜底(离线渲染)
  • HTML 消息:可选开关(默认关),开启后用本地 WebView + 消毒渲染,对齐官方 power-user HTML 设置
  • 流式渲染:增量解析 + 增量排版,不逐 token 全量重渲染;长消息 LazyColumn 虚拟化
  • 音视频附件:消息里的 audio/video 用 Media3 ExoPlayer(官方消息 extra.media → 引擎 MediaEngine 判定 → Media3 渲染);图片/GIF 用 Coil3

世界书实时状态(命中指示灯)

  • 入口:输入区「📚」按钮或快捷工具盘展开
  • 面板内容:当前命中 / 注入的世界书条目列表 + 指示灯:
    • 🔵 常驻(Constant,永久注入)
    • 🟢 关键词命中且已注入
    • 🟠 关键词命中但未注入(预算不足 / 优先级被裁)
    • ⚪ 未命中不显示(或置灰收起)
  • 每行显示:条目名、命中关键词、注入位置、占用的 token
  • 引擎要求WorldBookScanner 必须返回完整 match 结果(命中条目 / 命中键 / 注入状态 / 预算占用),状态面板只是它的视图——设计引擎时就要带上

输入区快捷工具盘(可展开)

  • 输入框上方拖拽手柄,上拉展开“快捷工具盘”:世界书状态 · 上下文占比胶囊(圆环进度 + token/上限 + 百分比,绿→黄→橙→红分级,点开详细分解)· 快捷回复 · 常用正则开关 · 图像生成 · 附件 · TTS 朗读
  • 不放进工具盘:群聊成员(属于群聊页管理,官方在群聊界面内管理成员,与输入上下文无关);提供商/模型/主题等环境设置(留在主设置)
  • 竞品对照(NativeTavern):它有上下文占比指示器(输入区可展开菜单)但没有世界书命中亮灯(只有内部 activeWorldInfoIds + 调试日志);默认深色写死。我们的差异点:命中指示灯 + 默认浅色 + 常驻上下文占比
  • 也可收成底部弹层(Bottom Sheet),用完即收,不占聊天空间
  • 主设置页顶部加“常用”折叠区:主题 · 模型 · 语音 · 备份,高频设置一眼可见

图标系统

之前文档里的 📚⚡🖼 只是占位示意,不是最终图标。

  • 主推:Phosphor Icons(1512 个,Regular 字重)——圆头端点、有机现代,最配“余烬/炉火”的温暖美学,撞车少
  • 系统级备选:Material Symbols Rounded(官方 4067 个)——与 M3 原生契合,最稳
  • 内容级备选:Lucide(旧项目已用,1.5px 圆头细线)——简洁现代
  • 规范:24dp 网格 · 统一字重(全 App 只用一种字重档)· 圆角端点 · 默认 onSurfaceVariant,激活 primary,警示 error · 状态图标(命中灯)用小圆点自绘,不用图标代替

社区需求与市场缺口(2026-08 调研)

官方仓库呼声最高的功能(GitHub issue 评论数排序):

  1. 每条消息都能滑动切换回复(不只最后一条)— #1731
  2. 聊天历史分块裁剪,加快 prompt 构建 — #1278
  3. RAG / 知识库完善 — #1671
  4. 快捷回复脚本全屏编辑器 — #2285
  5. 一键生成聊天背景 — #937
  6. 内置网络代理(HTTP/SOCKS,非 AI Agent)— #831
  7. 无障碍 / 读屏支持 — #2694
  8. 世界书负深度 — #3344
  9. 聊天内单独显示角色名 — #4357
  10. 世界书注入改进 / 激活组 / Freeze to History — #5655 / #3762 / #5852
  11. EPIC:把 Persona 并入 Character,模型与参数按角色设置 — #3139(验证了我们的“角色为唯一主体 + 每角色模型覆盖”设计)

社区扩展热度排行(2025-2026): 表情精灵(Character Expressions)> 视觉小说模式(Visual Novel Mode)> TTS > 记忆/总结 > 世界书。

市场缺口(我们的机会):

  • 世界书命中指示灯——官方与 NativeTavern 均无(只有内部数据/调试日志)
  • 移动端真原生 + 中文界面 + 中文美学主题——无一家做全
  • 上下文透明度(占比 + 世界书命中状态)——权力用户刚需,竞品不可视
  • 角色卡驱动主题(每卡一套观感)——无一家做到位
  • 人性化细节(设置搜索 / 空状态引导 / 人话报错 / 可撤销)——开源项目普遍缺失

连接与模型设置(提供商管理)

交互参照命理2(RikkaHub Plus)SettingProviderPage / ProviderConfigure卡片列表 → 详情编辑,不是向导。 底层协议与接口仍按酒馆官方 1:1(见“服务商注册表”),UI 层自由。

  1. 提供商列表:品牌 SVG 头像(assets/icons,参照命理2 AutoAIIcon;无品牌图标的厂商用首字母圆形兜底)+ 名称 + 一句话说明 + 已配置/未配置状态;顶部搜索,已保存连接可快速切换/删除
  2. 详情编辑:名称 / API Key(密码遮罩 + 显示切换,粘贴自动去空格)/ 接口地址(未配置时自动预填厂商默认地址,来自 providers.json)/ 区域(硅基流动、Z.AI、MiniMax)/ Workers 账户 ID / Azure API 版本 / 默认模型(底部弹层 + 搜索选择)
  3. 测试连接:一键验证(复用官方 /status 模型列表逻辑;无模型列表端点的厂商走最小对话探测),成功自动拉取模型列表;拉不到用预填 default_models 兜底

连接档案:可建多个(命名、切换)、全局默认 + 每角色可选覆盖(呼应官方 EPIC #3139);扫码导入导出分享(沿用旧项目概念)

上游跟进与扩展策略

  • 供应商 = 数据 + 协议路由:openai-compatible / anthropic / google / mistral / xai / cohere / ai21,加新厂商只改注册表 JSON,不动协议代码
  • 可扩展接口:LlmProvider / CardParser / WorldBookScanner / MacroEngine / SlashParser / PromptAssembler / TTS / ImageGen / VectorStore / Translator / ThemeSource——新功能按接口插,不侵入核心
  • 上游跟进(我们是重写,不是 git 合并官方):官方发版 → 对照 CHANGELOG + 官方行为回归测试 → 翻译/移植新功能到对应模块 → CI 全量验证;按版本节奏(每月/每大版)例行执行
  • 分层纪律:engine 不依赖 UI;data 不依赖 engine;provider 只做协议;新增功能先落接口再落实现

架构可扩展原则(一切为改 / 合并 / 升级 / 加功能服务)

  1. 单向依赖app → engine / data / provider / services / theme;engine 不依赖 UI,data 不依赖 engine,provider 只做协议——依赖只朝一个方向
  2. 先接口后实现:所有可变点(LlmProvider / CardParser / WorldBookScanner / MacroEngine / SlashParser / PromptAssembler / TTS / ImageGen / VectorStore / Translator / ThemeSource)先定接口再写实现;新增功能 = 新实现 + 注册,不侵入核心
  3. 数据驱动注册表:供应商、主题预设、默认模型 = JSON 数据表;加新条目不改代码
  4. 接口/事件通信:模块之间通过接口与事件通信,不互相 import 具体实现类
  5. 功能开关:新功能一律带 feature flag,可灰度、可回滚
  6. 依赖版本目录:组件版本全部收进 gradle/libs.versions.toml + Renovate 自动 PR
  7. 上游跟进:官方发版 → CHANGELOG + 官方行为回归测试 → 翻译/移植到对应模块 → CI 全量验证(重写项目不是 git 合并)
  8. 回归测试锁行为:每个引擎模块配官方行为对照测试,任何改动不得破坏兼容

社区需求 → 路线图映射

社区需求(官方 issue) 优先级 落点
每条消息滑动切回复 #1731 P1 ✅ 聊天页消息流(滑动 + 计数 + 变体列表弹层)
聊天历史分块裁剪 #1278 P2 引擎:上下文管理 / tokenizer
RAG / 知识库 #1671 P1 ✅ services:向量库(世界书/聊天历史/文件数据银行已接,2026-08-10)
快捷回复全屏编辑器 #2285 P3 快捷回复管理页
一键生成聊天背景 #937 P4 ✅ 主题配方:AI 生成背景(接图像服务)
内置网络代理 #831(HTTP/SOCKS,不是 AI Agent,用于访问国外 API 或中转) P5 services:网络代理
无障碍 / 读屏 #2694 P0 贯穿 图标均有 contentDescription、按钮为文本标签;复杂滑动手势边界登记
世界书负深度 #3344 P2 ✅ 世界书引擎(负深度不注入 + 扫描深度<0 返回空)
聊天内单独显示角色名 #4357 P1 聊天显示
世界书注入改进 / 激活组 / Freeze to History #5655 #3762 #5852 P2 世界书引擎
Persona 并入 Character + 每角色模型 #3139 P0 / P2 ✅ 人设管理 + 角色级模型覆盖
表情精灵 P4 主题 / 消息头像
视觉小说模式 远期
TTS P3 services
记忆 / 总结 P3 services

UI 交互组件与动效(全部现成)

  • 长按菜单:Material3 ModalBottomSheet(底部弹层,手机端操作惯例)+ combinedClickable(onLongClick)——现成组件,无需第三方库
  • 选中操作条AnimatedVisibility 包一行 IconButton(默认隐藏,选中浮现)
  • 下拉菜单 / 弹窗 / 浮层DropdownMenu / Dialog / Popup(Material3 现成)
  • 动效(Compose 内置,全现成):
    • 出现/消失:AnimatedVisibility + fadeIn/Out、slideIn/Out、expand/shrinkVertically
    • 颜色过渡:animateColorAsState(角色主题切换)
    • 背景切换:Crossfade
    • 内容过渡:AnimatedContent;数值/尺寸:animateFloatAsState / animateDpAsState
    • 弹性动效:spring(M3 风格)
  • 需要自己写的只是“编排逻辑”(何时触发/参数/顺序),动画引擎与组件全部现成

技术栈与组件选型

引擎层(1:1 官方):纯 Kotlin,不依赖任何 UI 组件;官方 JS 逻辑全部翻译在 engine(角色卡 / 世界书 / 宏 / 斜杠 / 提示词组装 / 提供商转换器 / 媒体 / 群聊 / 表情)。

App 层(自由选型):Kotlin · Jetpack Compose · Material3(1.4.0 稳定)· Navigation Compose · Room · DataStore 1.2.1 · Coil3 3.5.0 · Media3 1.10.0 · OkHttp 5.4.0 · Koin · kotlinx.serialization

渲染与主题:multiplatform-markdown-renderer 0.43.0 · latex-renderer · Highlights/KodeView · androidx.palette · MaterialKolor · MeshGradient · Cloudy

接线纪律:App 只“调用引擎 + 渲染结果”,逻辑不重写;每个引擎能力对应的官方源码位置和 App 接线点见 docs/HANDOFF.md 4.7。完整组件清单(版本 / 为什么选 / 接入点 / 官方源码位置)见 docs/COMPONENTS.md

路线图

  • P0 骨架:工程、主题系统、导航、角色列表/详情、V2/V3/JSON 导入
  • P1 聊天:消息流、流式渲染、气泡、滑动/长按交互、聊天存储
  • P2 引擎:世界书扫描注入、宏引擎、提示词组装、tokenizer
  • P3 功能:斜杠、群聊、预设、人设、作者注释、regex
  • P4 主题:角色卡取色驱动、模糊背景、毛玻璃、预设主题完成
  • P5 服务:STT、服务商注册表完善(TTS/图像/翻译/向量执行层已接)
  • P6 扩展:自有插件 API + 官方行为回归测试体系

兼容性守则

  1. 核心兼容层与官方 1:1,UI 层自由:数据格式、字段名、注入算法、宏展开、斜杠行为、导入导出文件必须与官方互读互通;界面、交互、主题完全自主。兼容层 1:1 是长期可维护的前提——官方发版时只需对照行为测试,不会伤及 UI。
  2. 每个引擎模块配“官方行为回归测试”:同一输入,官方输出 vs 本项目输出。 1.5. 编排层(PromptPipeline 总装)只做“调用顺序与传参”,业务逻辑必须留在各差分模块;App 只调总装,不在 UI 层重拼提示词。
  3. 核心引擎不依赖 UI 层。
  4. 服务商注册表只改数据,不改协议代码。
  5. 保持小步提交,CI 全量验证后再合入。

许可

AGPL-3.0(参考/翻译 SillyTavern 源码,派生义务;分发必须开源)。

分发渠道:以 GitHub Release APK + F-Droid 为主(App 本身不生成内容,内容由用户自带模型 API 生成;上架 Google Play 前需单独确认 BYOK 角色扮演类客户端政策边界)。

About

EmberInn · 余烬酒馆 — 全新原生 Android SillyTavern 兼容客户端(参考官方源码重写,无 WebView 壳)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages