Skip to content

Releases: Solar-CV/AscentApp

v0.21.1

Choose a tag to compare

@github-actions github-actions released this 30 Oct 11:10

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.21.1 要点

修:非中文界面下技能书是空的

切到简体 / 繁体以外的语言(日、德、英…),技能书页头还写着「35 篇」,下面的列表却是「没有符合条件的文章」。35 篇一篇都点不到,等于整个技能书打不开。

原因是筛选条「全部」这个选项把界面文案当成了判定值:切语言后,状态里留着上一个语言的「全部」,它既不等于新语言的「全部」,也不等于文章的中文分类名,两个条件同时不成立,列表被过滤成空。也就是说这不是内容缺失,数据一直都在,只是被筛掉了。

顺带一提,这和上一版包体从 40 MB 降到 30 MB 没有关系 —— 那是 R8 与资源压缩,内容与十种语言都完好。

改法:判定值换成与语言无关的常量,显示文案单独映射。附带一个正面的副作用 —— 选中某个分类后再切语言,筛选会保留并跟着翻译(原来是重置回「全部」)。

已在日文、德文、简体中文三套环境各验证一遍:35 篇全在,分类筛选与跨语言切换都正常。

修:法语 / 西语下底部「训练」标签被切掉

法语 Entraînement、西语 Entrenamiento 比其他语言长,在 360dp 宽的窄屏上会顶出选中态的绿色形状,边角被裁掉;西语那项看起来还比别的更高。

两处一起改:选中态圆角从 26dp 收到 16dp(原来的圆角在 54dp 高里几乎成了正圆,文字所在的水平高度上宽度只剩 53dp,13 个字符放不下),标签改成单行且按最宽的一项整排自适应字号,五个标签共用同一个字号,最窄的屏也不会溢出或截断。

360dp 与 411dp 两种宽度、法语与西语两种语言都实测过。

修:选中最左 / 最右项时边角被外框吃掉

把选中态换成圆角块之后,外框还是胶囊形。胶囊在内容的竖直范围内几乎没有直边,所以选第一项或最后一项时,块的上下两个角会伸出弧形边界,被外框裁掉。

外框圆角收到 22dp(内距 6dp + 内块圆角 16dp),三者同心,任何一项都不会被削。首、中、末三项在 360dp 与 411dp 下都验过。

v0.21.0

Choose a tag to compare

@github-actions github-actions released this 30 Oct 09:43

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.21.0 要点

整个界面换成黏土质感

这一版把「我的 / 我的主页 / 复习 / 训练 / 技能书」五页的视觉语言统一换掉:不再是白描边卡片 + 渐变,而是压实的黏土块——柔和的影、极短的高光、平涂的色。

为什么不是普通的 shadow:Modifier.blur() 要 API 31,本工程最低 26;Modifier.shadow() 只能给正下方一层、颜色不可控,也做不出「左上亮、右下暗」的双向感。所以影是用 BlurMaskFilter 离屏画出来再缓存的(按尺寸 / 圆角 / 偏移 / 模糊 / 颜色,LRU 24 条),绘制时只多一次 drawBitmap。

每块卡四层:外投影 → 贴边光 → 顶部一截高光 → 内底压暗。彩色卡(墨黑 hero、训练蓝、警示黄)走同一套阴影,只是换填充色。

三轮收敛出来的三条规则

第一版做完真机一看,每块都在发光:卡片像半透明,边缘反而找不到。逐像素量过才发现是三件事叠在一起——高光铺满上半块(85% 白)、外光斑 70% 白晕在四周、描边写的是 1f 即 1 物理像素(2.75 倍屏上只有 0.36dp)。而底色与卡面只差 9 个色阶,高光一撤就同色,所以边界必须靠描边 + 接触影撑,不能靠高光。

于是有了这三条,后续所有页面都按它改:

  1. 高光只做贴唇:顶部 20dp 内 30%→0,高度封顶,卡片变高唇不变厚
  2. 描边用 dp:1.dp.toPx(),颜色压到 #D8DEE8;1 物理像素在高分屏上等于没有
  3. 影分两层:远的一层做体积,近的一层(0.3e / 0.5e、alpha 40%)做接触影。只有一层时怎么调都发虚

颜色:从渐变糖块到平涂

  • 技能书按分类上色:装备钢蓝、绳索青、冰雪靛、医学红、判断琥珀、行前绿、领导力品红,与图标用同一套前缀匹配,图标和颜色永远指向同一类。顺序有讲究——绳索与冰雪都含「技术」二字,先判绳索再判冰雪,「技术」只作兜底,否则半列都是青块
  • 色块改平涂:原来 ClayChip 画垂直渐变 + 18% 白唇,读起来像塑料糖块;现在只剩一块实色 + 同色投影,不画渐变、不画唇光
  • 顶部大色块平涂:复习排队卡、训练今日推荐、我的海拔 hero 三处从渐变改成实色,加一个 heroFlat 中间调;体积感交给同色投影与描边
  • 详情页封面跟着分类走:原来是写死的品牌蓝,现在是分类色平涂 + 同色系胶囊

顺带修的

  • 连续解锁多条成就时的叠影:同一个调用点换参数不会重建 AndroidView,上一条的 3D 渲染器还在画,新成就的定稿图又叠上去。改成按成就 id 打 key 重建;弹窗之间的遮罩改为常亮,不再闪一帧没遮暗的主界面
  • 英文 1 days → plurals(10 语言,俄语补 one/few/many/other)
  • 技能书摘要硬切在半个词上,补 TextOverflow.Ellipsis
  • rev_all_done 里的弯引号被回退字体撑成 Today' s,改回 ASCII 撇号

还没做的

  • 详情页正文仍是旧的白描边卡片,没换成黏土——这一页信息密度高,担心柔影吃掉对比,留待单独评估
  • 训练页顶部「Today · TODAY」文案重复,是更早留下的问题
  • 只跑了模拟器(Pixel 6 / android-34):实体机上的三层投影开销、OLED 灰阶过渡、深色模式逐项配色都还没校

本次一并发布的版本(此前未单独发版,只列要点)

  • v0.20.21 — 技能书按分类上色,色块改平涂
  • v0.20.20 — 高光收成贴唇,投影拆成体积影 + 接触影
  • v0.20.19 — 黏土材质落地:四页改造

v0.20.18

Choose a tag to compare

@github-actions github-actions released this 30 Oct 07:20

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.18 要点

攀登大满贯换新模型

full_route 重新导出(3.35 MB,30,160 三角面,高度 26.20 → 26.70 mm)。这一版主要在打磨细节:

  • 经幡旗片从 0.20 mm 放大到 0.42 × 0.26 mm(约占长边 1%)——原来那个尺寸在手机上必须放到最大才看得见
  • 绳端改成两层叠石托高,绳沿程逐点钳到「地形 + 0.09 mm」,旗片逐片做离地校验,不再一半埋进雪里、也不会和山体面闪烁
  • 小尺度部件不再用 SCENE.ray_cast 找地面(射线会先打中刚建的绳、桩、旗),改用 FR_Terrain.ray_cast

图标按新的 hero 渲染重出(灰底、容差 12 抠图)。姿态与取景逻辑没动——仍是 POSE_OVERRIDE 里那条:跳过徽章的 X+90°,绕 Y +90° 让铭牌朝镜头,取景拉远 1.35 倍。

本次一并发布的版本(此前未单独发版,只列要点)

  • v0.20.17 — 修:双指缩放/平移之后,模型会突然高速转一下
  • v0.20.16 — 真机看不清小字:缩放上限从 1.25× 提到 5.5×
  • v0.20.15 — 40 枚成就,40 个模型

v0.20.14

Choose a tag to compare

@github-actions github-actions released this 28 Oct 10:37

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.14 要点

修:徒步毕业的图标还是占位图

trail_finish 的模型早就接进去了,但图标映射一直指着手绘占位图(badge_placeholder_agi),所以徽章墙上它和另一枚共用同一张图。模型渲染的图标其实一直躺在资源目录里,只是没人指过去。现在改正。

顺带发现那张占位图是一张真人照片(蓝西装、噤声手势),two_tracks 还在用它当成就图标。已换成程序生成的中性占位图(深蓝珐琅盘 + 黄铜外框 + 两条汇到峰顶的虚线),照片从包里删掉。等 two_tracks 的模型到位再替换。

3D 徽章不再只在开发者测试区能看

之前只有「设置 → 开发者模式 → 成就测试区」能点开 3D,普通用户拿不到入口。现在:

  • 我的 → 头像 → 已解锁徽章:点任意一枚直接全屏看 3D
  • 全部徽章墙:已解锁的都能点开(未解锁的仍是灰度预览,不给入口,隐藏成就更不给)

3D 展示页是从最外层覆盖上去的,不是替换页面,所以返回时回到你进来的那一页(主页或徽章墙),列表位置也不丢;底部导航栏同时被盖住,不会压在徽章上。

本次一并发布的版本(此前未单独发版,只列要点)

  • v0.20.13 — 徽章模型 28 → 34 枚
  • v0.20.12 — 成就文案排查:两处翻译整整落后了一个版本

v0.20.11

Choose a tag to compare

@github-actions github-actions released this 28 Oct 09:11

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.11 要点

3D 徽章:多方向布光,外加一版合成波落日背景

布光从两盏变五盏。 之前只有一盏主光加一盏轮廓光,金属只有一道弧面高光,正面浮雕贴平、顶面与底缘没有交代,转到侧面时整枚徽章会塌成一块深色。现在按职责分开:

光 方向 作用
主光 左上偏前,暖白 高光与金属感
顶光 正上方 顶面梯度,边缘立起来
面光 正前方,中性微冷 抬亮浮雕与珐琅正面
轮廓光 右后,冷蓝 把外框从背景里挑出来
反弹光 下方,暖 模拟台面反弹,底缘不死黑

总照度 90,500 lux,与原来的 92,000 基本持平——只换分布,不加曝光,所以层次多了但不会整体发白。

暗色背景:合成波落日

新增一张 1080×1920 的模糊背景:深靛天顶 → 品红层 → 橙红地平线,一轮暖橙落日压在六成高度,三层山脊沉到底部,40px 高斯模糊后只剩色场。

展示页右上角多了一个胶囊,在亮底 / 暗底之间切换。默认跟随系统明暗,手动切过之后会记住;只影响这一个页面,App 主题不变。状态栏与导航栏也跟着背景走,深色底不会顶出一条浅灰带。

顺带把这页剩下的四处硬编码中文换成了多语言文案(新增 5 条键 × 10 语言),并修掉档案页「技能概览」里 7000 米两个单元在非中文界面显示中文名的问题。

本次一并发布的版本(此前未单独发版,只列要点)

  • v0.20.10 — 名言改成原文,不翻译
  • v0.20.9 — 系统开屏不再「先闪一下」
  • v0.20.8 — 开屏换成黏土拟态,还带一句登山名言
  • v0.20.7 — 3D 徽章加上 4x MSAA
  • v0.20.6 — 3D 徽章默认跑最高画质

v0.20.5

Choose a tag to compare

@github-actions github-actions released this 28 Oct 03:26

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.5 要点

成就弹窗的边框区域,第一次点击只「上膛」

弹窗是整屏遮罩,点卡片以外的任何地方都会关掉。问题是弹窗常常紧跟在一次点击之后出现(点完课程、点完复习题),手指可能还没离开屏幕,一次误触就把刚解锁的徽章弹窗关掉了。

现在遮罩第一次点击不关闭,只在底部淡入一行「再点一次关闭」;第二次点击才真的关。计数按成就 id 记住,弹窗队列换到下一条时自动复位。卡片正中的「收下」按钮和系统返回键行为不变 —— 这两个是明确的操作意图,不需要再确认一次。


v0.20.4 要点

成就测试区返回后不再跳回顶部

上一版修了设置页 → 语言页这类路径,漏了成就测试区里的两处:

  • 成就测试区内部点进 3D 展示页,返回时列表弹回顶部(状态没提到提前返回之前)
  • 设置页 → 成就测试区 → 返回,设置页的列表位置丢了(设置页整棵离开组合,内部状态被丢弃)

前者按「设置页 → 语言页」的老办法把 LazyListState 提到 stageId 提前返回之前;后者把设置、成就测试、反馈这几个分支各自套一个状态槽,来回切换都停在原处。

开发者模式入口对普通用户隐藏

没解锁时,设置页的「开发者模式」整块(标题 + 卡片)不再渲染,连「未开启 · 连点版本号 7 次」这类说明也一并去掉。

版本号上连点 7 次仍然有效,只是不再显示「再点 N 次解锁」的倒计时提示 —— 提示本身就把隐藏入口写给所有人看了。对应的 4 条文案(set_dev_locked / set_dev_hint / set_dev_tap_hint / dev_tap_hint)已从十种语言里全部移除。


v0.20.3 要点

从二级页返回后,列表不再弹回顶部

滑到列表中间 → 进设置 / 语言 / 技能书详情 / 某门课 → 返回,原来会直接跳回顶部。原因是这些页面的滚动位置存在列表自己身上,一旦切到二级页,列表整棵子树就离开组合,状态跟着被丢掉。

修法按页面结构分两种:

  • 列表与二级页是同一层互斥分支(我的页、技能书)→ 用 SaveableStateProvider 给每个分支一个状态槽,返回时原样恢复。我的页的「个人主页 ↔ 全部徽章墙」也一并处理。
  • 列表里有提前返回的二级页(设置页 → 语言页)→ 把 LazyListState 提到提前返回之前,状态不跟着列表走。

顺带修的三处:

  • 切 tab、或从课程页退回来时,四个 tab 的列表位置也保住了(根组件按 tab 分槽)
  • 技能书的搜索词与分类筛选现在也会保留,返回列表时不用重新输入
  • 路径页从课程返回不再强制跳回第一页 —— 只在真的切换大类时才回第一页

v0.20.2 要点

模型库扩到 28 枚,成就图标改由模型生成

新增 11 枚(连击 3/7/14/30 天、完美 1/5/15/30、复习首次/20/清空、撤离明智、徒步毕业),另有冰爪出师、好奇开发者、完美系列等重新导出,合计 28 枚成就有了实时 3D 模型。

关键变化:这 28 枚的成就图标不再用 AI 插画,直接取模型的正面渲染图。渲染图是纯黑背景,用四邻域 flood fill 只吃掉与画布边缘连通的黑色(徽章内部的深色区域不会被打孔),羽化后输出 256 px 透明 WebP。这样徽章墙、解锁弹窗、3D 视图看到的是同一个物件,视觉上不再有两套风格。

剩下 12 枚还没有模型(海拔、全勤、满贯、毕业这类里程碑),继续用手绘图标,点开走透视卡片。

顺带

  • 泛光强度降到 0.05
  • 聚光灯增益收敛到 5×。模型自带的聚光朝向徽章内部(实测光束方向 y 分量为负、灯位在正面之下 2 mm),放大多少都照不到正面,需要回 Blender 源文件修灯位与朝向
  • 包体 21 → 38 MB;27.5 MB 模型打包后只占 8 MB(新导出压缩率明显更好)

v0.20.1 要点

修复:模型自带的光效不显示

三个原因叠在一起,导致高原病守门人的灯笼、目标锁定的聚光灯在 APK 里完全看不出来:

一、光源实体没进场景。 glTF 的 KHR_lights_punctual 光不会被 getEntities() 带出来(实测 entities=25 / lights=1 / renderables=24),必须单独把 lightEntities 加进 Scene。之前那盏聚光灯压根没被渲染。

二、自发光强度被丢弃。 模型用 KHR_materials_emissive_strength 把灯笼设到 6×、镜片设到 8×,但 gltfio 对这一扩展支持不稳定,退化成一个普通亮色块。现在构建期把它直接乘进 emissiveFactor(glTF 允许 > 1),不再依赖运行时扩展支持。

三、光强与场景曝光不匹配。 聚光灯是 54 cd,而场景主光是 66000 lux,同一场景里差几个数量级,就算加进场景也等于没开。现在对 glTF 自带的点/聚光灯统一乘 20 倍增益。

另外开启了泛光(bloom),自发光才会真正「溢出」成光晕,而不是一块白斑。泛光参数压到最低档(3 层、180px、LOW)。低端机自动降级:帧时间连续两次超过 28ms 就自动关掉泛光,不会为了光晕把帧率拖到 30 以下。

顺带

  • 主光与环境光略微回收(IBL 46000 → 38000、主光 74000 → 66000),给自发光留出对比空间,避免整体过曝。
  • 包体不变,仍是 39 MB。

v0.20.0 要点

成就徽章从「图」换成「实物」

接入 Filament 实时渲染,17 枚已出模型的成就改为真 3D:可拖动旋转、双指缩放、静止后正面小幅摆动。模型来自 Blender 模型库,金属与珐琅按 PBR 材质渲染,光照用一张程序生成的棚拍环境贴图(128 KB KTX)。

未出模型的 23 枚仍用定稿图做透视角度的「假 3D」,观感是收藏卡片,接口与真 3D 一致,后续补模型即可自动切换。

解锁弹窗与预览弹窗也用上 3D

AchievementUnlockOverlay 现在渲染 3D 徽章(首帧到达前用定稿图占位,避免空白)。开发者测试区的「预览」与真实解锁走同一个弹窗,因此两处一致。

弹窗卡片是深色,金属模型透明底直接贴上去会糊成黑块,所以真 3D 徽章下面加了一块浅色圆盘底座;图片假 3D 自带深色底,不套底座。

解锁时两侧喷彩带

从屏幕左右两侧向内喷射 56 条彩带,受重力下坠并自转,2.8 秒淡出。颜色取当前稀有度色 + 金 + 白。尊重系统「移除动画」设置(关闭动效时不喷)。

展示页改为亮色背景

详情页背景换成重模糊的风景(天空渐变 + 四层山脊 + 雾带,程序生成 27 KB),徽章用透明 TextureView 叠在上面。同时把环境光强度从 30000 提到 46000、主光提到 74000,解决之前偏暗的问题。

手势方向反转

左右拖动与上下俯仰都反向,符合「拖着徽章转」的直觉;惯性方向同步。

三枚徒步成就补上形象

trail_first / trail_camp / trail_high 已有模型,徽章墙缩略图取自模型渲染图。trail_finish 与 two_tracks 仍是占位图,等模型。

包体

debug APK 29 MB → 39 MB。20.4 MB 模型资源是主要增量(最大一枚雪崩之眼 5.1 MB / 9.2 万三角面)。若后续觉得太大,可以把模型改成按需下载。


v0.19.31 要点

五枚徒步成就的文案补齐九种语言

v0.19.27 新增的 5 枚徒步成就当时只有中文原文,非中文界面会回退显示中文。这一版补齐:

  • 5 条标题 + 5 条描述 × 九种翻译语言(英 / 繁中 / 日 / 俄 / 德 / 西 / 法 / 瑞典 / 意)
  • 每种语言的键集合与英文逐条对齐,10,544 → 10,554,缺 0、重复 0、孤儿键 0

译名各自贴本地说法:英文 First Trail Steps / Trekking Graduate,日文「トレイルの第一歩」/「トレッキング卒業」,德文 Erste Schritte am Weg/Trekking-Abschluss,瑞典文 Första stegen på leden/Vandringsexamen;繁中用「踏出第一步」/「徒步畢業」,与既有徽章命名习惯一致。

README 通读修正

英文与中文两份都过了一遍,改掉与代码脱节的地方:当前版本号、安装体积、权限说明(现在也用于提交反馈)、徽章数 35 → 40、键数 10,544 → 10,554、「九种语言各拆三支」的说法,并补上反馈页说明与 v0.19.25–30 的变更记录。


v0.19.30 要点

反馈改成一点即发

上一版把反馈交给系统邮件应用,用户还得在邮件里再点一次发送,中间多一道。现在直接 POST 到 Formspree(https://formspree.io/f/mrppzwqp),点「发送反馈」就完成提交,不经过邮箱。

  • 请求是 JSON,Accept: application/json,成功收 {"ok":true}
  • 字段:type(问题/建议/纠错)、message、email(留了才带)、app(版本号)、diagnostics(勾选才带)
  • 三次状态:发送中 / 已收到(绿色)/ 发送失败(红色,并出现「改用邮件发送」退路)

用 HttpURLConnection + org.json 手写,没引入 OkHttp/Retrofit —— 这个工程一直只依赖 Compose,为一次 POST 加两个库不划算。

联网权限:仍然不需要新增。INTERNET 是题库更新时就已经有的。

退路:网络不通时点「改用邮件发送」,走 ACTION_SENDTO + mailto:;连邮件应用都没有,正文会自动进剪贴板,一个字都不会丢。

诊断信息

跟着请求一起提交,默认关闭、必须手动勾选。内容包括版本、系统、机型、界面语言、题库版本、当前大类、完成课数、徽章数,以及最近一次崩溃堆栈;不含课程内容、做题记录、账号。

需要留意:反馈内容会经过 Formspree(第三方服务)转发到表单绑定的邮箱,免费额度每月 50 条。


v0.19.29 要点

反馈入口与反馈页

「我的」页账号下方新增「反馈与建议」(位置在风险声明之上)。页面里有三样东西:

  • 类型:问题反馈 / 功能建议 / 内容纠错
  • 描述 + 联系邮箱(选填)
  • 附带诊断信息:默认关闭,必须自己打开

发送走系统邮件应用(ACTION_SENDTO + mailto:),收件人预填、标题正文都已写好,用户确认后点发送。没有在 App 里直连 SMTP 或表单接口 —— SMTP 得把账号密码打进 APK,谁都能扒出来;表单接口需要一个后端。等有了固定收件邮箱,改 FeedbackScreen.kt 顶部那一个常量即可。没有邮件应用时,内容自动复制到剪贴板,不会丢。

联网权限:不需要新增。发邮件是邮件应用联网,跟本 App 无关;App 里已有的 INTERNET 权限只用于题库更新。

诊断信息包含:应用版本、Android 版本、机型、界面语言、题库版本、当前大类、完成课数与徽章数,以及最近一次崩溃的堆栈。不含课程内容、做题记录、账号与任何用户输入 —— 这句口径也写在界面上,用户勾选前看得见。

崩溃记录

新增 Diagnostics:装一个兜底的未捕获异常处理器,把堆栈写进应用私有目录(最多留 5 条),然后原样交还给系统 —— 只记录、不拦截,不会因为加了日志把崩溃吞掉。

顶部胶囊加图标

主界面的「高山攀登 / 徒步」胶囊前面加了 14dp 图标,与弹层里那两枚同源。


v0.19.28 要点

开屏 logo 缩小 40%

开屏中央的雪山标记按中心等比缩到原来的 60%,图形高度从 188/288 降到约 113/288。留白更足,小屏设备上不再显得笨重。桌面图标没动。

课程大类切换图标重画

底部弹层里两个大类原来用的是文本字符:攀登是「▲」、徒步是「≡」——三条横杠完全看不出和徒步的关系。现在换成两枚实心卡通图标:

  • 高山攀登:三角山体 + 一条锯齿雪线(挖空),比纯三角多一层「雪山」的信息
  • 徒步:登山靴——鞋帮、带齿鞋底、两道鞋带。44dp 下轮廓清楚,也不会和雪山混淆

图标是 24 网格的实心剪影,evenodd 挖孔,仍然用 Icon(tint = ...) 整体着色,所以选中态(绿底白图标)与未选中态(灰底灰图标)共用同一份路径,不额外增加资源。

另外在画布上放了一版「顶部胶囊加 14dp 图标」的预览,如果那个方向也想要,说一声我就加。


v0.19.27 要点

成就系统与 89 课新题库对齐

成就定义写于「66 课、只有攀登一条线」的时代,题库铺到 89 课(攀登 68 / 徒步 21)之后有两条判定脱节了:

  • full_route 理论大满贯:目标写死 66 课,实际攀登已有 68 课;更要紧的是判定写的是「当前轨道所有单元都完成」,于是徒步走完 21 课就能拿到「理论大满贯」。
  • five_zones 五区足迹:按「任意 5 个单元各完成 ≥1 课」计数,攀登现在有 6 个单元、徒步只有 4 个 —— 徒步线上永远拿不到。

两条都改成显式点名单元:full_route → 攀登大满贯(68 课),five_zones → 六区足迹(攀登 6 个单元各完成 ≥1 课)。

徒步线补上 5 枚成就

徒步 21 课此前一枚成就都没有,走完整条线没有任何反馈。按攀登那套节奏补齐:

成就 条件 稀有度
走出第一步 完成 t01(线路难度与自我定位) 普通
扎营一夜 徒步单元 t2(多日与露营)全部 8 课 稀有
高原行走 徒步单元 t3(高原徒步)全部 5 课 稀有
徒步毕业 徒步全部 21 课 史诗
双线并进 攀登 ≥10 课且徒步 ≥10 课 史诗

成就总数 35 → 40。五枚新徽章暂时共用一张占位图(badge_placeholder_agi),等专属徽章画好逐个替换即可,业务定义不用动。

顺手修的判定口径

成就的单元/轨道进度过去按当前选中轨道统计。这在单线时代没问题,双线之后就错了:切到徒步轨道时攀登进度会变成 0,full_route 这类成就会反而更容易命中。现在统一按全部轨道统计(新增 AchievementStats.trackProgress),与「已完成课程 id」这套全局进度一致。

开发者测试区的条件校验也改成拿全轨道的课程/单元 id 比对,否则徒步的 t01、t1–t4 在攀登轨道上会被误报成「引用了不存在的课程」。

同源问题还修了一处显示 bug:个人主页与「我的」页的路线进度,分子数是两条轨道的完成总数、分母却是当前轨道的课数,攀登学完切到徒步会显示「68 / 21 课」。现在分子只数当前轨道。

已知待办:五枚新成就的文案目前只有中文原文,其余九种语言会回退显示中文。下一批 i18n 会把 10 个新键一次性加进十语言对齐。


v0.19.26 要点

简体中文系统上装完却是繁体

这是 Android 资源匹配的经典坑:values/(默认桶)装的是简体,但它没有语言限定符;繁体装在 values-zh-rTW 里,有限定符。系统语言是 zh-CN 时,框架先找 zh-rCN(不存在),再找「同语言变体」,于是命中了繁体桶 —— 整个界面变繁体。

手动去语言页选一次「简体中文」会恢复正常,因为手动选择时框架给请求带上了脚本子标签,请求变精确才绕开繁体桶。这正好解释了「自动检测是简体、界面却是繁体、手动切一下才对」。

修法是给简体补一个精确桶:构建时把 res/values/strings.xml 复制成 values-zh-rCN/strings.xml(Gradle 任务 genZhCnRes,在 preBuild 之前生成)。精确匹配永远赢过「同语言变体」,简体系统从此稳定走简体桶。单一事实来源仍然是 res/values/strings.xml,生成目录不要手改。

顺带修了一处同类判定:简体繁体过去只看地区,于是「港澳台地区用简体」(zh-Hans-HK / zh-Hans-MO / zh-Hans-TW)会被误判成繁体。现在脚本优先于地区 —— 显式 Hans 一律简体,显式 Hant 一律繁体,没有脚本时才看地区。界面语言与内容层(课程名、题库)两处的归一规则已同步。


v0.19.25 要点

一个纯修问题的版本,两处都是老毛病。

开屏中央不再有黑色底

开屏(Android 12 及以上的系统启动画面)中央那块一直是个深色圆盘,因为系统默认拿桌面图标来画,而桌面图标是自适应图标——深色底 #0B1522 上叠了一座雪山,在浅色启动背景上就露出了黑底。

现在给启动画面单独挂了一幅透明底的雪山矢量(ic_splash_mark),只画山体、雪帽、旗杆和旗面,不带任何底板:

  • 浅色模式启动背景 #F1F6FA、深色模式 #070D16,都与进入后的页面底色一致,图标切换过去不会跳色
  • 图标内容落在中央 192dp 安全区内,各屏幕密度下都不会被裁切
  • 桌面上的图标本身没动,仍是原来的黑底雪山

Android 11 及以下没有系统启动画面图标,不受影响。

修好「开发者模式 → 成就测试」点不进去

设置页里那个「成就测试」按钮点了没反应,界面纹丝不动。原因是分支判断顺序:成就测试页是从设置页里打开的,showSettings 一直是 true,而判断链里 showSettings 排在 showAchievements 前面,于是永远先命中设置页。

把 showAchievements 提到 showSettings 之前即可。现在点进去是成就测试页,返回回到设置页,与直觉一致。成就解锁弹窗本身一直是正常的,这次没碰。


v0.19.24 要点

从 v0.19.11 算起,这一系列版本只做了一件事:把内容层铺到十种语言。v0.19.24 是收官——最后一种语言(Italiano)四层全量,十种界面语言全部有内容支撑,运行时不再回退。

语言:十种界面语言,九种翻译语言四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Italiano 补到全量:

  • Italiano:9,422 条题库 + 443 条要点 + 全部课名、单元名、山峰与技能书 h32–h35。题干与解析用 tu,要点用无人称句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español / Français / Svenska,九种翻译语言与英文键集合逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。简体中文作为原文语言,内容层本身就是它——十种界面语言至此全部落地。

顺带清了最后一批历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,其余语言在逐语补齐的过程中陆续跟上。十种语言现在都没有孤儿键。

如果某一项在所选语言里意外缺失,回退顺序是「当前语言 → 英文 → 中文原文」。这条路径现在只是兜底,正常不会再触发。

三种数字写法,刻意分开

同一套内容,各语言按本地习惯写数字。三种口径在译文和术语表里都标住了,不会混:

  • 英文、中文、日文:6.5 °C、5,000 m
  • 德文、西文、意文:6,5 °C、1.000 m(小数逗号、千位点)
  • 法文、瑞典文:6,5 °C、5 000 m(小数逗号、千位空格)

人称也各自不同:德文无人称 man-Form、西文 tú、法文 vous、瑞典文与意文 du / tu,而课程要点在所有语言里都是无人称句。

术语一致性

各语言沿用自己登山圈既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken
  • 西文:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、cinta transportadora de nieve
  • 法文:nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke、kort fast rep、expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla
  • 意文:corda fissa、corrimano、attrezzamento della via、rinvio intermedio (re-belay)、guasto in serie、bloccante per mano / pettorale、nastro trasportatore di neve、seppellimento critico、sacca d'aria

医学与救援的硬数字一律照技能书原值,不取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带...

Read more

v0.20.3

Choose a tag to compare

@github-actions github-actions released this 27 Oct 10:03

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.3 要点

从二级页返回后,列表不再弹回顶部

滑到列表中间 → 进设置 / 语言 / 技能书详情 / 某门课 → 返回,原来会直接跳回顶部。原因是这些页面的滚动位置存在列表自己身上,一旦切到二级页,列表整棵子树就离开组合,状态跟着被丢掉。

修法按页面结构分两种:

  • 列表与二级页是同一层互斥分支(我的页、技能书)→ 用 SaveableStateProvider 给每个分支一个状态槽,返回时原样恢复。我的页的「个人主页 ↔ 全部徽章墙」也一并处理。
  • 列表里有提前返回的二级页(设置页 → 语言页)→ 把 LazyListState 提到提前返回之前,状态不跟着列表走。

顺带修的三处:

  • 切 tab、或从课程页退回来时,四个 tab 的列表位置也保住了(根组件按 tab 分槽)
  • 技能书的搜索词与分类筛选现在也会保留,返回列表时不用重新输入
  • 路径页从课程返回不再强制跳回第一页 —— 只在真的切换大类时才回第一页

v0.20.2 要点

模型库扩到 28 枚,成就图标改由模型生成

新增 11 枚(连击 3/7/14/30 天、完美 1/5/15/30、复习首次/20/清空、撤离明智、徒步毕业),另有冰爪出师、好奇开发者、完美系列等重新导出,合计 28 枚成就有了实时 3D 模型。

关键变化:这 28 枚的成就图标不再用 AI 插画,直接取模型的正面渲染图。渲染图是纯黑背景,用四邻域 flood fill 只吃掉与画布边缘连通的黑色(徽章内部的深色区域不会被打孔),羽化后输出 256 px 透明 WebP。这样徽章墙、解锁弹窗、3D 视图看到的是同一个物件,视觉上不再有两套风格。

剩下 12 枚还没有模型(海拔、全勤、满贯、毕业这类里程碑),继续用手绘图标,点开走透视卡片。

顺带

  • 泛光强度降到 0.05
  • 聚光灯增益收敛到 5×。模型自带的聚光朝向徽章内部(实测光束方向 y 分量为负、灯位在正面之下 2 mm),放大多少都照不到正面,需要回 Blender 源文件修灯位与朝向
  • 包体 21 → 38 MB;27.5 MB 模型打包后只占 8 MB(新导出压缩率明显更好)

v0.20.1 要点

修复:模型自带的光效不显示

三个原因叠在一起,导致高原病守门人的灯笼、目标锁定的聚光灯在 APK 里完全看不出来:

一、光源实体没进场景。 glTF 的 KHR_lights_punctual 光不会被 getEntities() 带出来(实测 entities=25 / lights=1 / renderables=24),必须单独把 lightEntities 加进 Scene。之前那盏聚光灯压根没被渲染。

二、自发光强度被丢弃。 模型用 KHR_materials_emissive_strength 把灯笼设到 6×、镜片设到 8×,但 gltfio 对这一扩展支持不稳定,退化成一个普通亮色块。现在构建期把它直接乘进 emissiveFactor(glTF 允许 > 1),不再依赖运行时扩展支持。

三、光强与场景曝光不匹配。 聚光灯是 54 cd,而场景主光是 66000 lux,同一场景里差几个数量级,就算加进场景也等于没开。现在对 glTF 自带的点/聚光灯统一乘 20 倍增益。

另外开启了泛光(bloom),自发光才会真正「溢出」成光晕,而不是一块白斑。泛光参数压到最低档(3 层、180px、LOW)。低端机自动降级:帧时间连续两次超过 28ms 就自动关掉泛光,不会为了光晕把帧率拖到 30 以下。

顺带

  • 主光与环境光略微回收(IBL 46000 → 38000、主光 74000 → 66000),给自发光留出对比空间,避免整体过曝。
  • 包体不变,仍是 39 MB。

v0.20.0 要点

成就徽章从「图」换成「实物」

接入 Filament 实时渲染,17 枚已出模型的成就改为真 3D:可拖动旋转、双指缩放、静止后正面小幅摆动。模型来自 Blender 模型库,金属与珐琅按 PBR 材质渲染,光照用一张程序生成的棚拍环境贴图(128 KB KTX)。

未出模型的 23 枚仍用定稿图做透视角度的「假 3D」,观感是收藏卡片,接口与真 3D 一致,后续补模型即可自动切换。

解锁弹窗与预览弹窗也用上 3D

AchievementUnlockOverlay 现在渲染 3D 徽章(首帧到达前用定稿图占位,避免空白)。开发者测试区的「预览」与真实解锁走同一个弹窗,因此两处一致。

弹窗卡片是深色,金属模型透明底直接贴上去会糊成黑块,所以真 3D 徽章下面加了一块浅色圆盘底座;图片假 3D 自带深色底,不套底座。

解锁时两侧喷彩带

从屏幕左右两侧向内喷射 56 条彩带,受重力下坠并自转,2.8 秒淡出。颜色取当前稀有度色 + 金 + 白。尊重系统「移除动画」设置(关闭动效时不喷)。

展示页改为亮色背景

详情页背景换成重模糊的风景(天空渐变 + 四层山脊 + 雾带,程序生成 27 KB),徽章用透明 TextureView 叠在上面。同时把环境光强度从 30000 提到 46000、主光提到 74000,解决之前偏暗的问题。

手势方向反转

左右拖动与上下俯仰都反向,符合「拖着徽章转」的直觉;惯性方向同步。

三枚徒步成就补上形象

trail_first / trail_camp / trail_high 已有模型,徽章墙缩略图取自模型渲染图。trail_finish 与 two_tracks 仍是占位图,等模型。

包体

debug APK 29 MB → 39 MB。20.4 MB 模型资源是主要增量(最大一枚雪崩之眼 5.1 MB / 9.2 万三角面)。若后续觉得太大,可以把模型改成按需下载。


v0.19.31 要点

五枚徒步成就的文案补齐九种语言

v0.19.27 新增的 5 枚徒步成就当时只有中文原文,非中文界面会回退显示中文。这一版补齐:

  • 5 条标题 + 5 条描述 × 九种翻译语言(英 / 繁中 / 日 / 俄 / 德 / 西 / 法 / 瑞典 / 意)
  • 每种语言的键集合与英文逐条对齐,10,544 → 10,554,缺 0、重复 0、孤儿键 0

译名各自贴本地说法:英文 First Trail Steps / Trekking Graduate,日文「トレイルの第一歩」/「トレッキング卒業」,德文 Erste Schritte am Weg/Trekking-Abschluss,瑞典文 Första stegen på leden/Vandringsexamen;繁中用「踏出第一步」/「徒步畢業」,与既有徽章命名习惯一致。

README 通读修正

英文与中文两份都过了一遍,改掉与代码脱节的地方:当前版本号、安装体积、权限说明(现在也用于提交反馈)、徽章数 35 → 40、键数 10,544 → 10,554、「九种语言各拆三支」的说法,并补上反馈页说明与 v0.19.25–30 的变更记录。


v0.19.30 要点

反馈改成一点即发

上一版把反馈交给系统邮件应用,用户还得在邮件里再点一次发送,中间多一道。现在直接 POST 到 Formspree(https://formspree.io/f/mrppzwqp),点「发送反馈」就完成提交,不经过邮箱。

  • 请求是 JSON,Accept: application/json,成功收 {"ok":true}
  • 字段:type(问题/建议/纠错)、message、email(留了才带)、app(版本号)、diagnostics(勾选才带)
  • 三次状态:发送中 / 已收到(绿色)/ 发送失败(红色,并出现「改用邮件发送」退路)

用 HttpURLConnection + org.json 手写,没引入 OkHttp/Retrofit —— 这个工程一直只依赖 Compose,为一次 POST 加两个库不划算。

联网权限:仍然不需要新增。INTERNET 是题库更新时就已经有的。

退路:网络不通时点「改用邮件发送」,走 ACTION_SENDTO + mailto:;连邮件应用都没有,正文会自动进剪贴板,一个字都不会丢。

诊断信息

跟着请求一起提交,默认关闭、必须手动勾选。内容包括版本、系统、机型、界面语言、题库版本、当前大类、完成课数、徽章数,以及最近一次崩溃堆栈;不含课程内容、做题记录、账号。

需要留意:反馈内容会经过 Formspree(第三方服务)转发到表单绑定的邮箱,免费额度每月 50 条。


v0.19.29 要点

反馈入口与反馈页

「我的」页账号下方新增「反馈与建议」(位置在风险声明之上)。页面里有三样东西:

  • 类型:问题反馈 / 功能建议 / 内容纠错
  • 描述 + 联系邮箱(选填)
  • 附带诊断信息:默认关闭,必须自己打开

发送走系统邮件应用(ACTION_SENDTO + mailto:),收件人预填、标题正文都已写好,用户确认后点发送。没有在 App 里直连 SMTP 或表单接口 —— SMTP 得把账号密码打进 APK,谁都能扒出来;表单接口需要一个后端。等有了固定收件邮箱,改 FeedbackScreen.kt 顶部那一个常量即可。没有邮件应用时,内容自动复制到剪贴板,不会丢。

联网权限:不需要新增。发邮件是邮件应用联网,跟本 App 无关;App 里已有的 INTERNET 权限只用于题库更新。

诊断信息包含:应用版本、Android 版本、机型、界面语言、题库版本、当前大类、完成课数与徽章数,以及最近一次崩溃的堆栈。不含课程内容、做题记录、账号与任何用户输入 —— 这句口径也写在界面上,用户勾选前看得见。

崩溃记录

新增 Diagnostics:装一个兜底的未捕获异常处理器,把堆栈写进应用私有目录(最多留 5 条),然后原样交还给系统 —— 只记录、不拦截,不会因为加了日志把崩溃吞掉。

顶部胶囊加图标

主界面的「高山攀登 / 徒步」胶囊前面加了 14dp 图标,与弹层里那两枚同源。


v0.19.28 要点

开屏 logo 缩小 40%

开屏中央的雪山标记按中心等比缩到原来的 60%,图形高度从 188/288 降到约 113/288。留白更足,小屏设备上不再显得笨重。桌面图标没动。

课程大类切换图标重画

底部弹层里两个大类原来用的是文本字符:攀登是「▲」、徒步是「≡」——三条横杠完全看不出和徒步的关系。现在换成两枚实心卡通图标:

  • 高山攀登:三角山体 + 一条锯齿雪线(挖空),比纯三角多一层「雪山」的信息
  • 徒步:登山靴——鞋帮、带齿鞋底、两道鞋带。44dp 下轮廓清楚,也不会和雪山混淆

图标是 24 网格的实心剪影,evenodd 挖孔,仍然用 Icon(tint = ...) 整体着色,所以选中态(绿底白图标)与未选中态(灰底灰图标)共用同一份路径,不额外增加资源。

另外在画布上放了一版「顶部胶囊加 14dp 图标」的预览,如果那个方向也想要,说一声我就加。


v0.19.27 要点

成就系统与 89 课新题库对齐

成就定义写于「66 课、只有攀登一条线」的时代,题库铺到 89 课(攀登 68 / 徒步 21)之后有两条判定脱节了:

  • full_route 理论大满贯:目标写死 66 课,实际攀登已有 68 课;更要紧的是判定写的是「当前轨道所有单元都完成」,于是徒步走完 21 课就能拿到「理论大满贯」。
  • five_zones 五区足迹:按「任意 5 个单元各完成 ≥1 课」计数,攀登现在有 6 个单元、徒步只有 4 个 —— 徒步线上永远拿不到。

两条都改成显式点名单元:full_route → 攀登大满贯(68 课),five_zones → 六区足迹(攀登 6 个单元各完成 ≥1 课)。

徒步线补上 5 枚成就

徒步 21 课此前一枚成就都没有,走完整条线没有任何反馈。按攀登那套节奏补齐:

成就 条件 稀有度
走出第一步 完成 t01(线路难度与自我定位) 普通
扎营一夜 徒步单元 t2(多日与露营)全部 8 课 稀有
高原行走 徒步单元 t3(高原徒步)全部 5 课 稀有
徒步毕业 徒步全部 21 课 史诗
双线并进 攀登 ≥10 课且徒步 ≥10 课 史诗

成就总数 35 → 40。五枚新徽章暂时共用一张占位图(badge_placeholder_agi),等专属徽章画好逐个替换即可,业务定义不用动。

顺手修的判定口径

成就的单元/轨道进度过去按当前选中轨道统计。这在单线时代没问题,双线之后就错了:切到徒步轨道时攀登进度会变成 0,full_route 这类成就会反而更容易命中。现在统一按全部轨道统计(新增 AchievementStats.trackProgress),与「已完成课程 id」这套全局进度一致。

开发者测试区的条件校验也改成拿全轨道的课程/单元 id 比对,否则徒步的 t01、t1–t4 在攀登轨道上会被误报成「引用了不存在的课程」。

同源问题还修了一处显示 bug:个人主页与「我的」页的路线进度,分子数是两条轨道的完成总数、分母却是当前轨道的课数,攀登学完切到徒步会显示「68 / 21 课」。现在分子只数当前轨道。

已知待办:五枚新成就的文案目前只有中文原文,其余九种语言会回退显示中文。下一批 i18n 会把 10 个新键一次性加进十语言对齐。


v0.19.26 要点

简体中文系统上装完却是繁体

这是 Android 资源匹配的经典坑:values/(默认桶)装的是简体,但它没有语言限定符;繁体装在 values-zh-rTW 里,有限定符。系统语言是 zh-CN 时,框架先找 zh-rCN(不存在),再找「同语言变体」,于是命中了繁体桶 —— 整个界面变繁体。

手动去语言页选一次「简体中文」会恢复正常,因为手动选择时框架给请求带上了脚本子标签,请求变精确才绕开繁体桶。这正好解释了「自动检测是简体、界面却是繁体、手动切一下才对」。

修法是给简体补一个精确桶:构建时把 res/values/strings.xml 复制成 values-zh-rCN/strings.xml(Gradle 任务 genZhCnRes,在 preBuild 之前生成)。精确匹配永远赢过「同语言变体」,简体系统从此稳定走简体桶。单一事实来源仍然是 res/values/strings.xml,生成目录不要手改。

顺带修了一处同类判定:简体繁体过去只看地区,于是「港澳台地区用简体」(zh-Hans-HK / zh-Hans-MO / zh-Hans-TW)会被误判成繁体。现在脚本优先于地区 —— 显式 Hans 一律简体,显式 Hant 一律繁体,没有脚本时才看地区。界面语言与内容层(课程名、题库)两处的归一规则已同步。


v0.19.25 要点

一个纯修问题的版本,两处都是老毛病。

开屏中央不再有黑色底

开屏(Android 12 及以上的系统启动画面)中央那块一直是个深色圆盘,因为系统默认拿桌面图标来画,而桌面图标是自适应图标——深色底 #0B1522 上叠了一座雪山,在浅色启动背景上就露出了黑底。

现在给启动画面单独挂了一幅透明底的雪山矢量(ic_splash_mark),只画山体、雪帽、旗杆和旗面,不带任何底板:

  • 浅色模式启动背景 #F1F6FA、深色模式 #070D16,都与进入后的页面底色一致,图标切换过去不会跳色
  • 图标内容落在中央 192dp 安全区内,各屏幕密度下都不会被裁切
  • 桌面上的图标本身没动,仍是原来的黑底雪山

Android 11 及以下没有系统启动画面图标,不受影响。

修好「开发者模式 → 成就测试」点不进去

设置页里那个「成就测试」按钮点了没反应,界面纹丝不动。原因是分支判断顺序:成就测试页是从设置页里打开的,showSettings 一直是 true,而判断链里 showSettings 排在 showAchievements 前面,于是永远先命中设置页。

把 showAchievements 提到 showSettings 之前即可。现在点进去是成就测试页,返回回到设置页,与直觉一致。成就解锁弹窗本身一直是正常的,这次没碰。


v0.19.24 要点

从 v0.19.11 算起,这一系列版本只做了一件事:把内容层铺到十种语言。v0.19.24 是收官——最后一种语言(Italiano)四层全量,十种界面语言全部有内容支撑,运行时不再回退。

语言:十种界面语言,九种翻译语言四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Italiano 补到全量:

  • Italiano:9,422 条题库 + 443 条要点 + 全部课名、单元名、山峰与技能书 h32–h35。题干与解析用 tu,要点用无人称句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español / Français / Svenska,九种翻译语言与英文键集合逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。简体中文作为原文语言,内容层本身就是它——十种界面语言至此全部落地。

顺带清了最后一批历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,其余语言在逐语补齐的过程中陆续跟上。十种语言现在都没有孤儿键。

如果某一项在所选语言里意外缺失,回退顺序是「当前语言 → 英文 → 中文原文」。这条路径现在只是兜底,正常不会再触发。

三种数字写法,刻意分开

同一套内容,各语言按本地习惯写数字。三种口径在译文和术语表里都标住了,不会混:

  • 英文、中文、日文:6.5 °C、5,000 m
  • 德文、西文、意文:6,5 °C、1.000 m(小数逗号、千位点)
  • 法文、瑞典文:6,5 °C、5 000 m(小数逗号、千位空格)

人称也各自不同:德文无人称 man-Form、西文 tú、法文 vous、瑞典文与意文 du / tu,而课程要点在所有语言里都是无人称句。

术语一致性

各语言沿用自己登山圈既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken
  • 西文:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、cinta transportadora de nieve
  • 法文:nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke、kort fast rep、expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla
  • 意文:corda fissa、corrimano、attrezzamento della via、rinvio intermedio (re-belay)、guasto in serie、bloccante per mano / pettorale、nastro trasportatore di neve、seppellimento critico、sacca d'aria

医学与救援的硬数字一律照技能书原值,不取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限、队伍内控 0,8、水位 15 cm、胸带必解;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 题库按语言拆文件:单个 Kotlin 文件约 2,500 条会让编译守护进程崩溃(Daemon compilation failed: null),所以英文、繁中、日文、俄文、德文、西文、法文、瑞典文、意文各拆三支,合并行在 ContentPack.kt
  • tools/i18n/ 的三个命令(status.py / prep.py / apply.py)在十种语言上通用,--lang 决定读写哪一套包;繁中另有 tw.py、tw_entry.py
  • 每批译文进库前跑五项自查:键集合与「真实缺失集」的差集(缺 + 多)、片段内重复键、CJK 残留、英文单词残留、空值键。其中「多」这一栏在最后三种语言里抓出了六次误插的空值占位行

v0.19.23 要点

从上个发布版(v0.19.21)到现在,还是同一件事:把剩下的语言也铺满。

语言:内容层现在是八种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Français 与 Svenska 补到全量,并清理了两门语言里的历史遗留键:

  • Français:9,422 条题库 + 443 条要点 + 全部课名与技能书。题干与解析用 vous,要点用无人称句
  • Svenska:同上。题干与解析用 du,要点用陈述句

加上此前完成的 English / 繁體中文 / 日本語...

Read more

v0.20.1

Choose a tag to compare

@github-actions github-actions released this 26 Oct 10:05

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.20.1 要点

修复:模型自带的光效不显示

三个原因叠在一起,导致高原病守门人的灯笼、目标锁定的聚光灯在 APK 里完全看不出来:

一、光源实体没进场景。 glTF 的 KHR_lights_punctual 光不会被 getEntities() 带出来(实测 entities=25 / lights=1 / renderables=24),必须单独把 lightEntities 加进 Scene。之前那盏聚光灯压根没被渲染。

二、自发光强度被丢弃。 模型用 KHR_materials_emissive_strength 把灯笼设到 6×、镜片设到 8×,但 gltfio 对这一扩展支持不稳定,退化成一个普通亮色块。现在构建期把它直接乘进 emissiveFactor(glTF 允许 > 1),不再依赖运行时扩展支持。

三、光强与场景曝光不匹配。 聚光灯是 54 cd,而场景主光是 66000 lux,同一场景里差几个数量级,就算加进场景也等于没开。现在对 glTF 自带的点/聚光灯统一乘 20 倍增益。

另外开启了泛光(bloom),自发光才会真正「溢出」成光晕,而不是一块白斑。泛光参数压到最低档(3 层、180px、LOW)。低端机自动降级:帧时间连续两次超过 28ms 就自动关掉泛光,不会为了光晕把帧率拖到 30 以下。

顺带

  • 主光与环境光略微回收(IBL 46000 → 38000、主光 74000 → 66000),给自发光留出对比空间,避免整体过曝。
  • 包体不变,仍是 39 MB。

v0.20.0 要点

成就徽章从「图」换成「实物」

接入 Filament 实时渲染,17 枚已出模型的成就改为真 3D:可拖动旋转、双指缩放、静止后正面小幅摆动。模型来自 Blender 模型库,金属与珐琅按 PBR 材质渲染,光照用一张程序生成的棚拍环境贴图(128 KB KTX)。

未出模型的 23 枚仍用定稿图做透视角度的「假 3D」,观感是收藏卡片,接口与真 3D 一致,后续补模型即可自动切换。

解锁弹窗与预览弹窗也用上 3D

AchievementUnlockOverlay 现在渲染 3D 徽章(首帧到达前用定稿图占位,避免空白)。开发者测试区的「预览」与真实解锁走同一个弹窗,因此两处一致。

弹窗卡片是深色,金属模型透明底直接贴上去会糊成黑块,所以真 3D 徽章下面加了一块浅色圆盘底座;图片假 3D 自带深色底,不套底座。

解锁时两侧喷彩带

从屏幕左右两侧向内喷射 56 条彩带,受重力下坠并自转,2.8 秒淡出。颜色取当前稀有度色 + 金 + 白。尊重系统「移除动画」设置(关闭动效时不喷)。

展示页改为亮色背景

详情页背景换成重模糊的风景(天空渐变 + 四层山脊 + 雾带,程序生成 27 KB),徽章用透明 TextureView 叠在上面。同时把环境光强度从 30000 提到 46000、主光提到 74000,解决之前偏暗的问题。

手势方向反转

左右拖动与上下俯仰都反向,符合「拖着徽章转」的直觉;惯性方向同步。

三枚徒步成就补上形象

trail_first / trail_camp / trail_high 已有模型,徽章墙缩略图取自模型渲染图。trail_finish 与 two_tracks 仍是占位图,等模型。

包体

debug APK 29 MB → 39 MB。20.4 MB 模型资源是主要增量(最大一枚雪崩之眼 5.1 MB / 9.2 万三角面)。若后续觉得太大,可以把模型改成按需下载。


v0.19.31 要点

五枚徒步成就的文案补齐九种语言

v0.19.27 新增的 5 枚徒步成就当时只有中文原文,非中文界面会回退显示中文。这一版补齐:

  • 5 条标题 + 5 条描述 × 九种翻译语言(英 / 繁中 / 日 / 俄 / 德 / 西 / 法 / 瑞典 / 意)
  • 每种语言的键集合与英文逐条对齐,10,544 → 10,554,缺 0、重复 0、孤儿键 0

译名各自贴本地说法:英文 First Trail Steps / Trekking Graduate,日文「トレイルの第一歩」/「トレッキング卒業」,德文 Erste Schritte am Weg/Trekking-Abschluss,瑞典文 Första stegen på leden/Vandringsexamen;繁中用「踏出第一步」/「徒步畢業」,与既有徽章命名习惯一致。

README 通读修正

英文与中文两份都过了一遍,改掉与代码脱节的地方:当前版本号、安装体积、权限说明(现在也用于提交反馈)、徽章数 35 → 40、键数 10,544 → 10,554、「九种语言各拆三支」的说法,并补上反馈页说明与 v0.19.25–30 的变更记录。


v0.19.30 要点

反馈改成一点即发

上一版把反馈交给系统邮件应用,用户还得在邮件里再点一次发送,中间多一道。现在直接 POST 到 Formspree(https://formspree.io/f/mrppzwqp),点「发送反馈」就完成提交,不经过邮箱。

  • 请求是 JSON,Accept: application/json,成功收 {"ok":true}
  • 字段:type(问题/建议/纠错)、message、email(留了才带)、app(版本号)、diagnostics(勾选才带)
  • 三次状态:发送中 / 已收到(绿色)/ 发送失败(红色,并出现「改用邮件发送」退路)

用 HttpURLConnection + org.json 手写,没引入 OkHttp/Retrofit —— 这个工程一直只依赖 Compose,为一次 POST 加两个库不划算。

联网权限:仍然不需要新增。INTERNET 是题库更新时就已经有的。

退路:网络不通时点「改用邮件发送」,走 ACTION_SENDTO + mailto:;连邮件应用都没有,正文会自动进剪贴板,一个字都不会丢。

诊断信息

跟着请求一起提交,默认关闭、必须手动勾选。内容包括版本、系统、机型、界面语言、题库版本、当前大类、完成课数、徽章数,以及最近一次崩溃堆栈;不含课程内容、做题记录、账号。

需要留意:反馈内容会经过 Formspree(第三方服务)转发到表单绑定的邮箱,免费额度每月 50 条。


v0.19.29 要点

反馈入口与反馈页

「我的」页账号下方新增「反馈与建议」(位置在风险声明之上)。页面里有三样东西:

  • 类型:问题反馈 / 功能建议 / 内容纠错
  • 描述 + 联系邮箱(选填)
  • 附带诊断信息:默认关闭,必须自己打开

发送走系统邮件应用(ACTION_SENDTO + mailto:),收件人预填、标题正文都已写好,用户确认后点发送。没有在 App 里直连 SMTP 或表单接口 —— SMTP 得把账号密码打进 APK,谁都能扒出来;表单接口需要一个后端。等有了固定收件邮箱,改 FeedbackScreen.kt 顶部那一个常量即可。没有邮件应用时,内容自动复制到剪贴板,不会丢。

联网权限:不需要新增。发邮件是邮件应用联网,跟本 App 无关;App 里已有的 INTERNET 权限只用于题库更新。

诊断信息包含:应用版本、Android 版本、机型、界面语言、题库版本、当前大类、完成课数与徽章数,以及最近一次崩溃的堆栈。不含课程内容、做题记录、账号与任何用户输入 —— 这句口径也写在界面上,用户勾选前看得见。

崩溃记录

新增 Diagnostics:装一个兜底的未捕获异常处理器,把堆栈写进应用私有目录(最多留 5 条),然后原样交还给系统 —— 只记录、不拦截,不会因为加了日志把崩溃吞掉。

顶部胶囊加图标

主界面的「高山攀登 / 徒步」胶囊前面加了 14dp 图标,与弹层里那两枚同源。


v0.19.28 要点

开屏 logo 缩小 40%

开屏中央的雪山标记按中心等比缩到原来的 60%,图形高度从 188/288 降到约 113/288。留白更足,小屏设备上不再显得笨重。桌面图标没动。

课程大类切换图标重画

底部弹层里两个大类原来用的是文本字符:攀登是「▲」、徒步是「≡」——三条横杠完全看不出和徒步的关系。现在换成两枚实心卡通图标:

  • 高山攀登:三角山体 + 一条锯齿雪线(挖空),比纯三角多一层「雪山」的信息
  • 徒步:登山靴——鞋帮、带齿鞋底、两道鞋带。44dp 下轮廓清楚,也不会和雪山混淆

图标是 24 网格的实心剪影,evenodd 挖孔,仍然用 Icon(tint = ...) 整体着色,所以选中态(绿底白图标)与未选中态(灰底灰图标)共用同一份路径,不额外增加资源。

另外在画布上放了一版「顶部胶囊加 14dp 图标」的预览,如果那个方向也想要,说一声我就加。


v0.19.27 要点

成就系统与 89 课新题库对齐

成就定义写于「66 课、只有攀登一条线」的时代,题库铺到 89 课(攀登 68 / 徒步 21)之后有两条判定脱节了:

  • full_route 理论大满贯:目标写死 66 课,实际攀登已有 68 课;更要紧的是判定写的是「当前轨道所有单元都完成」,于是徒步走完 21 课就能拿到「理论大满贯」。
  • five_zones 五区足迹:按「任意 5 个单元各完成 ≥1 课」计数,攀登现在有 6 个单元、徒步只有 4 个 —— 徒步线上永远拿不到。

两条都改成显式点名单元:full_route → 攀登大满贯(68 课),five_zones → 六区足迹(攀登 6 个单元各完成 ≥1 课)。

徒步线补上 5 枚成就

徒步 21 课此前一枚成就都没有,走完整条线没有任何反馈。按攀登那套节奏补齐:

成就 条件 稀有度
走出第一步 完成 t01(线路难度与自我定位) 普通
扎营一夜 徒步单元 t2(多日与露营)全部 8 课 稀有
高原行走 徒步单元 t3(高原徒步)全部 5 课 稀有
徒步毕业 徒步全部 21 课 史诗
双线并进 攀登 ≥10 课且徒步 ≥10 课 史诗

成就总数 35 → 40。五枚新徽章暂时共用一张占位图(badge_placeholder_agi),等专属徽章画好逐个替换即可,业务定义不用动。

顺手修的判定口径

成就的单元/轨道进度过去按当前选中轨道统计。这在单线时代没问题,双线之后就错了:切到徒步轨道时攀登进度会变成 0,full_route 这类成就会反而更容易命中。现在统一按全部轨道统计(新增 AchievementStats.trackProgress),与「已完成课程 id」这套全局进度一致。

开发者测试区的条件校验也改成拿全轨道的课程/单元 id 比对,否则徒步的 t01、t1–t4 在攀登轨道上会被误报成「引用了不存在的课程」。

同源问题还修了一处显示 bug:个人主页与「我的」页的路线进度,分子数是两条轨道的完成总数、分母却是当前轨道的课数,攀登学完切到徒步会显示「68 / 21 课」。现在分子只数当前轨道。

已知待办:五枚新成就的文案目前只有中文原文,其余九种语言会回退显示中文。下一批 i18n 会把 10 个新键一次性加进十语言对齐。


v0.19.26 要点

简体中文系统上装完却是繁体

这是 Android 资源匹配的经典坑:values/(默认桶)装的是简体,但它没有语言限定符;繁体装在 values-zh-rTW 里,有限定符。系统语言是 zh-CN 时,框架先找 zh-rCN(不存在),再找「同语言变体」,于是命中了繁体桶 —— 整个界面变繁体。

手动去语言页选一次「简体中文」会恢复正常,因为手动选择时框架给请求带上了脚本子标签,请求变精确才绕开繁体桶。这正好解释了「自动检测是简体、界面却是繁体、手动切一下才对」。

修法是给简体补一个精确桶:构建时把 res/values/strings.xml 复制成 values-zh-rCN/strings.xml(Gradle 任务 genZhCnRes,在 preBuild 之前生成)。精确匹配永远赢过「同语言变体」,简体系统从此稳定走简体桶。单一事实来源仍然是 res/values/strings.xml,生成目录不要手改。

顺带修了一处同类判定:简体繁体过去只看地区,于是「港澳台地区用简体」(zh-Hans-HK / zh-Hans-MO / zh-Hans-TW)会被误判成繁体。现在脚本优先于地区 —— 显式 Hans 一律简体,显式 Hant 一律繁体,没有脚本时才看地区。界面语言与内容层(课程名、题库)两处的归一规则已同步。


v0.19.25 要点

一个纯修问题的版本,两处都是老毛病。

开屏中央不再有黑色底

开屏(Android 12 及以上的系统启动画面)中央那块一直是个深色圆盘,因为系统默认拿桌面图标来画,而桌面图标是自适应图标——深色底 #0B1522 上叠了一座雪山,在浅色启动背景上就露出了黑底。

现在给启动画面单独挂了一幅透明底的雪山矢量(ic_splash_mark),只画山体、雪帽、旗杆和旗面,不带任何底板:

  • 浅色模式启动背景 #F1F6FA、深色模式 #070D16,都与进入后的页面底色一致,图标切换过去不会跳色
  • 图标内容落在中央 192dp 安全区内,各屏幕密度下都不会被裁切
  • 桌面上的图标本身没动,仍是原来的黑底雪山

Android 11 及以下没有系统启动画面图标,不受影响。

修好「开发者模式 → 成就测试」点不进去

设置页里那个「成就测试」按钮点了没反应,界面纹丝不动。原因是分支判断顺序:成就测试页是从设置页里打开的,showSettings 一直是 true,而判断链里 showSettings 排在 showAchievements 前面,于是永远先命中设置页。

把 showAchievements 提到 showSettings 之前即可。现在点进去是成就测试页,返回回到设置页,与直觉一致。成就解锁弹窗本身一直是正常的,这次没碰。


v0.19.24 要点

从 v0.19.11 算起,这一系列版本只做了一件事:把内容层铺到十种语言。v0.19.24 是收官——最后一种语言(Italiano)四层全量,十种界面语言全部有内容支撑,运行时不再回退。

语言:十种界面语言,九种翻译语言四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Italiano 补到全量:

  • Italiano:9,422 条题库 + 443 条要点 + 全部课名、单元名、山峰与技能书 h32–h35。题干与解析用 tu,要点用无人称句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español / Français / Svenska,九种翻译语言与英文键集合逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。简体中文作为原文语言,内容层本身就是它——十种界面语言至此全部落地。

顺带清了最后一批历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,其余语言在逐语补齐的过程中陆续跟上。十种语言现在都没有孤儿键。

如果某一项在所选语言里意外缺失,回退顺序是「当前语言 → 英文 → 中文原文」。这条路径现在只是兜底,正常不会再触发。

三种数字写法,刻意分开

同一套内容,各语言按本地习惯写数字。三种口径在译文和术语表里都标住了,不会混:

  • 英文、中文、日文:6.5 °C、5,000 m
  • 德文、西文、意文:6,5 °C、1.000 m(小数逗号、千位点)
  • 法文、瑞典文:6,5 °C、5 000 m(小数逗号、千位空格)

人称也各自不同:德文无人称 man-Form、西文 tú、法文 vous、瑞典文与意文 du / tu,而课程要点在所有语言里都是无人称句。

术语一致性

各语言沿用自己登山圈既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken
  • 西文:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、cinta transportadora de nieve
  • 法文:nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke、kort fast rep、expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla
  • 意文:corda fissa、corrimano、attrezzamento della via、rinvio intermedio (re-belay)、guasto in serie、bloccante per mano / pettorale、nastro trasportatore di neve、seppellimento critico、sacca d'aria

医学与救援的硬数字一律照技能书原值,不取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限、队伍内控 0,8、水位 15 cm、胸带必解;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 题库按语言拆文件:单个 Kotlin 文件约 2,500 条会让编译守护进程崩溃(Daemon compilation failed: null),所以英文、繁中、日文、俄文、德文、西文、法文、瑞典文、意文各拆三支,合并行在 ContentPack.kt
  • tools/i18n/ 的三个命令(status.py / prep.py / apply.py)在十种语言上通用,--lang 决定读写哪一套包;繁中另有 tw.py、tw_entry.py
  • 每批译文进库前跑五项自查:键集合与「真实缺失集」的差集(缺 + 多)、片段内重复键、CJK 残留、英文单词残留、空值键。其中「多」这一栏在最后三种语言里抓出了六次误插的空值占位行

v0.19.23 要点

从上个发布版(v0.19.21)到现在,还是同一件事:把剩下的语言也铺满。

语言:内容层现在是八种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Français 与 Svenska 补到全量,并清理了两门语言里的历史遗留键:

  • Français:9,422 条题库 + 443 条要点 + 全部课名与技能书。题干与解析用 vous,要点用无人称句
  • Svenska:同上。题干与解析用 du,要点用陈述句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español,八种语言现在与英文逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。

顺带清了法文与瑞典文里各 5 条历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,这几门语言陆续补上。只剩 Italiano 还有这 5 条,收尾时一并处理。

最后一种语言(Italiano)仍覆盖扩充前的旧题库,新增题目回退英文——这是设计行为,不是缺失。

数字写法:三种口径,不要混

同一套内容,各语言按本地习惯写数字,这一点在译文和术语表里都标住了:

  • 法文与瑞典文:小数逗号,千位空格(6,5 °C、5 000 m、8 848,86 m)
  • 德文与西文:小数逗号,千位点(6,5 °C、1.000 m)
  • 英文与中日文:6.5 °C、5,000 m

术语一致性

法文与瑞典文都沿用各自语言里既有的专业写法,不做音译:

  • 法文:autorretención 体系对应 autorétraction、nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke / kort fast rep / expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla、kvävningsfas / latensfas

医学与救援的硬数字一律照技能书原值,不做取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2...

Read more

v0.19.31

Choose a tag to compare

@github-actions github-actions released this 23 Oct 03:27

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.19.31 要点

五枚徒步成就的文案补齐九种语言

v0.19.27 新增的 5 枚徒步成就当时只有中文原文,非中文界面会回退显示中文。这一版补齐:

  • 5 条标题 + 5 条描述 × 九种翻译语言(英 / 繁中 / 日 / 俄 / 德 / 西 / 法 / 瑞典 / 意)
  • 每种语言的键集合与英文逐条对齐,10,544 → 10,554,缺 0、重复 0、孤儿键 0

译名各自贴本地说法:英文 First Trail Steps / Trekking Graduate,日文「トレイルの第一歩」/「トレッキング卒業」,德文 Erste Schritte am Weg/Trekking-Abschluss,瑞典文 Första stegen på leden/Vandringsexamen;繁中用「踏出第一步」/「徒步畢業」,与既有徽章命名习惯一致。

README 通读修正

英文与中文两份都过了一遍,改掉与代码脱节的地方:当前版本号、安装体积、权限说明(现在也用于提交反馈)、徽章数 35 → 40、键数 10,544 → 10,554、「九种语言各拆三支」的说法,并补上反馈页说明与 v0.19.25–30 的变更记录。


v0.19.30 要点

反馈改成一点即发

上一版把反馈交给系统邮件应用,用户还得在邮件里再点一次发送,中间多一道。现在直接 POST 到 Formspree(https://formspree.io/f/mrppzwqp),点「发送反馈」就完成提交,不经过邮箱。

  • 请求是 JSON,Accept: application/json,成功收 {"ok":true}
  • 字段:type(问题/建议/纠错)、message、email(留了才带)、app(版本号)、diagnostics(勾选才带)
  • 三次状态:发送中 / 已收到(绿色)/ 发送失败(红色,并出现「改用邮件发送」退路)

用 HttpURLConnection + org.json 手写,没引入 OkHttp/Retrofit —— 这个工程一直只依赖 Compose,为一次 POST 加两个库不划算。

联网权限:仍然不需要新增。INTERNET 是题库更新时就已经有的。

退路:网络不通时点「改用邮件发送」,走 ACTION_SENDTO + mailto:;连邮件应用都没有,正文会自动进剪贴板,一个字都不会丢。

诊断信息

跟着请求一起提交,默认关闭、必须手动勾选。内容包括版本、系统、机型、界面语言、题库版本、当前大类、完成课数、徽章数,以及最近一次崩溃堆栈;不含课程内容、做题记录、账号。

需要留意:反馈内容会经过 Formspree(第三方服务)转发到表单绑定的邮箱,免费额度每月 50 条。


v0.19.29 要点

反馈入口与反馈页

「我的」页账号下方新增「反馈与建议」(位置在风险声明之上)。页面里有三样东西:

  • 类型:问题反馈 / 功能建议 / 内容纠错
  • 描述 + 联系邮箱(选填)
  • 附带诊断信息:默认关闭,必须自己打开

发送走系统邮件应用(ACTION_SENDTO + mailto:),收件人预填、标题正文都已写好,用户确认后点发送。没有在 App 里直连 SMTP 或表单接口 —— SMTP 得把账号密码打进 APK,谁都能扒出来;表单接口需要一个后端。等有了固定收件邮箱,改 FeedbackScreen.kt 顶部那一个常量即可。没有邮件应用时,内容自动复制到剪贴板,不会丢。

联网权限:不需要新增。发邮件是邮件应用联网,跟本 App 无关;App 里已有的 INTERNET 权限只用于题库更新。

诊断信息包含:应用版本、Android 版本、机型、界面语言、题库版本、当前大类、完成课数与徽章数,以及最近一次崩溃的堆栈。不含课程内容、做题记录、账号与任何用户输入 —— 这句口径也写在界面上,用户勾选前看得见。

崩溃记录

新增 Diagnostics:装一个兜底的未捕获异常处理器,把堆栈写进应用私有目录(最多留 5 条),然后原样交还给系统 —— 只记录、不拦截,不会因为加了日志把崩溃吞掉。

顶部胶囊加图标

主界面的「高山攀登 / 徒步」胶囊前面加了 14dp 图标,与弹层里那两枚同源。


v0.19.28 要点

开屏 logo 缩小 40%

开屏中央的雪山标记按中心等比缩到原来的 60%,图形高度从 188/288 降到约 113/288。留白更足,小屏设备上不再显得笨重。桌面图标没动。

课程大类切换图标重画

底部弹层里两个大类原来用的是文本字符:攀登是「▲」、徒步是「≡」——三条横杠完全看不出和徒步的关系。现在换成两枚实心卡通图标:

  • 高山攀登:三角山体 + 一条锯齿雪线(挖空),比纯三角多一层「雪山」的信息
  • 徒步:登山靴——鞋帮、带齿鞋底、两道鞋带。44dp 下轮廓清楚,也不会和雪山混淆

图标是 24 网格的实心剪影,evenodd 挖孔,仍然用 Icon(tint = ...) 整体着色,所以选中态(绿底白图标)与未选中态(灰底灰图标)共用同一份路径,不额外增加资源。

另外在画布上放了一版「顶部胶囊加 14dp 图标」的预览,如果那个方向也想要,说一声我就加。


v0.19.27 要点

成就系统与 89 课新题库对齐

成就定义写于「66 课、只有攀登一条线」的时代,题库铺到 89 课(攀登 68 / 徒步 21)之后有两条判定脱节了:

  • full_route 理论大满贯:目标写死 66 课,实际攀登已有 68 课;更要紧的是判定写的是「当前轨道所有单元都完成」,于是徒步走完 21 课就能拿到「理论大满贯」。
  • five_zones 五区足迹:按「任意 5 个单元各完成 ≥1 课」计数,攀登现在有 6 个单元、徒步只有 4 个 —— 徒步线上永远拿不到。

两条都改成显式点名单元:full_route → 攀登大满贯(68 课),five_zones → 六区足迹(攀登 6 个单元各完成 ≥1 课)。

徒步线补上 5 枚成就

徒步 21 课此前一枚成就都没有,走完整条线没有任何反馈。按攀登那套节奏补齐:

成就 条件 稀有度
走出第一步 完成 t01(线路难度与自我定位) 普通
扎营一夜 徒步单元 t2(多日与露营)全部 8 课 稀有
高原行走 徒步单元 t3(高原徒步)全部 5 课 稀有
徒步毕业 徒步全部 21 课 史诗
双线并进 攀登 ≥10 课且徒步 ≥10 课 史诗

成就总数 35 → 40。五枚新徽章暂时共用一张占位图(badge_placeholder_agi),等专属徽章画好逐个替换即可,业务定义不用动。

顺手修的判定口径

成就的单元/轨道进度过去按当前选中轨道统计。这在单线时代没问题,双线之后就错了:切到徒步轨道时攀登进度会变成 0,full_route 这类成就会反而更容易命中。现在统一按全部轨道统计(新增 AchievementStats.trackProgress),与「已完成课程 id」这套全局进度一致。

开发者测试区的条件校验也改成拿全轨道的课程/单元 id 比对,否则徒步的 t01、t1–t4 在攀登轨道上会被误报成「引用了不存在的课程」。

同源问题还修了一处显示 bug:个人主页与「我的」页的路线进度,分子数是两条轨道的完成总数、分母却是当前轨道的课数,攀登学完切到徒步会显示「68 / 21 课」。现在分子只数当前轨道。

已知待办:五枚新成就的文案目前只有中文原文,其余九种语言会回退显示中文。下一批 i18n 会把 10 个新键一次性加进十语言对齐。


v0.19.26 要点

简体中文系统上装完却是繁体

这是 Android 资源匹配的经典坑:values/(默认桶)装的是简体,但它没有语言限定符;繁体装在 values-zh-rTW 里,有限定符。系统语言是 zh-CN 时,框架先找 zh-rCN(不存在),再找「同语言变体」,于是命中了繁体桶 —— 整个界面变繁体。

手动去语言页选一次「简体中文」会恢复正常,因为手动选择时框架给请求带上了脚本子标签,请求变精确才绕开繁体桶。这正好解释了「自动检测是简体、界面却是繁体、手动切一下才对」。

修法是给简体补一个精确桶:构建时把 res/values/strings.xml 复制成 values-zh-rCN/strings.xml(Gradle 任务 genZhCnRes,在 preBuild 之前生成)。精确匹配永远赢过「同语言变体」,简体系统从此稳定走简体桶。单一事实来源仍然是 res/values/strings.xml,生成目录不要手改。

顺带修了一处同类判定:简体繁体过去只看地区,于是「港澳台地区用简体」(zh-Hans-HK / zh-Hans-MO / zh-Hans-TW)会被误判成繁体。现在脚本优先于地区 —— 显式 Hans 一律简体,显式 Hant 一律繁体,没有脚本时才看地区。界面语言与内容层(课程名、题库)两处的归一规则已同步。


v0.19.25 要点

一个纯修问题的版本,两处都是老毛病。

开屏中央不再有黑色底

开屏(Android 12 及以上的系统启动画面)中央那块一直是个深色圆盘,因为系统默认拿桌面图标来画,而桌面图标是自适应图标——深色底 #0B1522 上叠了一座雪山,在浅色启动背景上就露出了黑底。

现在给启动画面单独挂了一幅透明底的雪山矢量(ic_splash_mark),只画山体、雪帽、旗杆和旗面,不带任何底板:

  • 浅色模式启动背景 #F1F6FA、深色模式 #070D16,都与进入后的页面底色一致,图标切换过去不会跳色
  • 图标内容落在中央 192dp 安全区内,各屏幕密度下都不会被裁切
  • 桌面上的图标本身没动,仍是原来的黑底雪山

Android 11 及以下没有系统启动画面图标,不受影响。

修好「开发者模式 → 成就测试」点不进去

设置页里那个「成就测试」按钮点了没反应,界面纹丝不动。原因是分支判断顺序:成就测试页是从设置页里打开的,showSettings 一直是 true,而判断链里 showSettings 排在 showAchievements 前面,于是永远先命中设置页。

把 showAchievements 提到 showSettings 之前即可。现在点进去是成就测试页,返回回到设置页,与直觉一致。成就解锁弹窗本身一直是正常的,这次没碰。


v0.19.24 要点

从 v0.19.11 算起,这一系列版本只做了一件事:把内容层铺到十种语言。v0.19.24 是收官——最后一种语言(Italiano)四层全量,十种界面语言全部有内容支撑,运行时不再回退。

语言:十种界面语言,九种翻译语言四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Italiano 补到全量:

  • Italiano:9,422 条题库 + 443 条要点 + 全部课名、单元名、山峰与技能书 h32–h35。题干与解析用 tu,要点用无人称句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español / Français / Svenska,九种翻译语言与英文键集合逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。简体中文作为原文语言,内容层本身就是它——十种界面语言至此全部落地。

顺带清了最后一批历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,其余语言在逐语补齐的过程中陆续跟上。十种语言现在都没有孤儿键。

如果某一项在所选语言里意外缺失,回退顺序是「当前语言 → 英文 → 中文原文」。这条路径现在只是兜底,正常不会再触发。

三种数字写法,刻意分开

同一套内容,各语言按本地习惯写数字。三种口径在译文和术语表里都标住了,不会混:

  • 英文、中文、日文:6.5 °C、5,000 m
  • 德文、西文、意文:6,5 °C、1.000 m(小数逗号、千位点)
  • 法文、瑞典文:6,5 °C、5 000 m(小数逗号、千位空格)

人称也各自不同:德文无人称 man-Form、西文 tú、法文 vous、瑞典文与意文 du / tu,而课程要点在所有语言里都是无人称句。

术语一致性

各语言沿用自己登山圈既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken
  • 西文:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、cinta transportadora de nieve
  • 法文:nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke、kort fast rep、expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla
  • 意文:corda fissa、corrimano、attrezzamento della via、rinvio intermedio (re-belay)、guasto in serie、bloccante per mano / pettorale、nastro trasportatore di neve、seppellimento critico、sacca d'aria

医学与救援的硬数字一律照技能书原值,不取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限、队伍内控 0,8、水位 15 cm、胸带必解;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 题库按语言拆文件:单个 Kotlin 文件约 2,500 条会让编译守护进程崩溃(Daemon compilation failed: null),所以英文、繁中、日文、俄文、德文、西文、法文、瑞典文、意文各拆三支,合并行在 ContentPack.kt
  • tools/i18n/ 的三个命令(status.py / prep.py / apply.py)在十种语言上通用,--lang 决定读写哪一套包;繁中另有 tw.py、tw_entry.py
  • 每批译文进库前跑五项自查:键集合与「真实缺失集」的差集(缺 + 多)、片段内重复键、CJK 残留、英文单词残留、空值键。其中「多」这一栏在最后三种语言里抓出了六次误插的空值占位行

v0.19.23 要点

从上个发布版(v0.19.21)到现在,还是同一件事:把剩下的语言也铺满。

语言:内容层现在是八种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Français 与 Svenska 补到全量,并清理了两门语言里的历史遗留键:

  • Français:9,422 条题库 + 443 条要点 + 全部课名与技能书。题干与解析用 vous,要点用无人称句
  • Svenska:同上。题干与解析用 du,要点用陈述句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español,八种语言现在与英文逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。

顺带清了法文与瑞典文里各 5 条历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,这几门语言陆续补上。只剩 Italiano 还有这 5 条,收尾时一并处理。

最后一种语言(Italiano)仍覆盖扩充前的旧题库,新增题目回退英文——这是设计行为,不是缺失。

数字写法:三种口径,不要混

同一套内容,各语言按本地习惯写数字,这一点在译文和术语表里都标住了:

  • 法文与瑞典文:小数逗号,千位空格(6,5 °C、5 000 m、8 848,86 m)
  • 德文与西文:小数逗号,千位点(6,5 °C、1.000 m)
  • 英文与中日文:6.5 °C、5,000 m

术语一致性

法文与瑞典文都沿用各自语言里既有的专业写法,不做音译:

  • 法文:autorretención 体系对应 autorétraction、nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke / kort fast rep / expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla、kvävningsfas / latensfas

医学与救援的硬数字一律照技能书原值,不做取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 法文题库拆三支(PackFrQuiz / 2 / 3),瑞典文同样三支;单文件过大会让 Kotlin 编译守护进程崩溃
  • tools/i18n/ 的三个命令扩到十种语言通用,--lang 参数决定读写哪一套包

v0.19.21 要点

从上个发布版(v0.19.11)到现在,只做了一件事:把剩下两种语言也铺满。

语言:内容层现在是五种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Deutsch 与 Español 补到全量,与英文键集合逐条对齐:

  • Deutsch:9,422 条题库 + 443 条要点 + 全部课名与技能书,体例为无人称 man-Form,数字走德式写法(6,5 °C、1.000 m、35–50 Liter)
  • Español:同上,题干与解析用 tú、要点用无人称句,数字走西式写法(6,5 °C、1.000 m)

加上此前完成的 English / 繁體中文 / 日本語 与 Русский,六种语言现在与英文逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。

顺带清了德文与西语里各 5 条历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,这两门语言没跟上。

其余三种语言(Français、Svenska、Italiano)仍覆盖扩充前的旧题库,新增题目回退英文——这是设计行为,不是缺失,后续按同一 key 体系逐语铺开。

术语一致性

德文与西语都沿用各自语言里既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken、Bestätigungsfehler、Ankereffekt
  • 西语:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、calicata、cinta transportadora de nieve、cat hole

医学与救援的硬数字一律照技能书原值,不做取整:雪崩存活 48 / 47,6 / 96 %,决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径,搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min,渡河 1,0 m²/s 上限,固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 西语题库拆成三支(PackEsQuiz / 2 / 3),德文同样三支;单文件过大会让 Kotlin 编译守护进程崩溃
  • tools/i18n/ 的三个命令扩到十种语言通用,--lang 参数决定读写哪一套包

v0.19.11 要点

从上个发布版(v0.18.35)到现在,主要是两件事:内容翻了一倍多,以及**三种语言做到全量*...

Read more

v0.19.30

Choose a tag to compare

@github-actions github-actions released this 23 Oct 03:14

安装

Android 8.0(API 26)及以上,需开启「允许安装未知来源应用」。

附件为 debug 构建,仅供测试分发,未做 release 签名与 R8 混淆。


v0.19.30 要点

反馈改成一点即发

上一版把反馈交给系统邮件应用,用户还得在邮件里再点一次发送,中间多一道。现在直接 POST 到 Formspree(https://formspree.io/f/mrppzwqp),点「发送反馈」就完成提交,不经过邮箱。

  • 请求是 JSON,Accept: application/json,成功收 {"ok":true}
  • 字段:type(问题/建议/纠错)、message、email(留了才带)、app(版本号)、diagnostics(勾选才带)
  • 三次状态:发送中 / 已收到(绿色)/ 发送失败(红色,并出现「改用邮件发送」退路)

用 HttpURLConnection + org.json 手写,没引入 OkHttp/Retrofit —— 这个工程一直只依赖 Compose,为一次 POST 加两个库不划算。

联网权限:仍然不需要新增。INTERNET 是题库更新时就已经有的。

退路:网络不通时点「改用邮件发送」,走 ACTION_SENDTO + mailto:;连邮件应用都没有,正文会自动进剪贴板,一个字都不会丢。

诊断信息

跟着请求一起提交,默认关闭、必须手动勾选。内容包括版本、系统、机型、界面语言、题库版本、当前大类、完成课数、徽章数,以及最近一次崩溃堆栈;不含课程内容、做题记录、账号。

需要留意:反馈内容会经过 Formspree(第三方服务)转发到表单绑定的邮箱,免费额度每月 50 条。


v0.19.29 要点

反馈入口与反馈页

「我的」页账号下方新增「反馈与建议」(位置在风险声明之上)。页面里有三样东西:

  • 类型:问题反馈 / 功能建议 / 内容纠错
  • 描述 + 联系邮箱(选填)
  • 附带诊断信息:默认关闭,必须自己打开

发送走系统邮件应用(ACTION_SENDTO + mailto:),收件人预填、标题正文都已写好,用户确认后点发送。没有在 App 里直连 SMTP 或表单接口 —— SMTP 得把账号密码打进 APK,谁都能扒出来;表单接口需要一个后端。等有了固定收件邮箱,改 FeedbackScreen.kt 顶部那一个常量即可。没有邮件应用时,内容自动复制到剪贴板,不会丢。

联网权限:不需要新增。发邮件是邮件应用联网,跟本 App 无关;App 里已有的 INTERNET 权限只用于题库更新。

诊断信息包含:应用版本、Android 版本、机型、界面语言、题库版本、当前大类、完成课数与徽章数,以及最近一次崩溃的堆栈。不含课程内容、做题记录、账号与任何用户输入 —— 这句口径也写在界面上,用户勾选前看得见。

崩溃记录

新增 Diagnostics:装一个兜底的未捕获异常处理器,把堆栈写进应用私有目录(最多留 5 条),然后原样交还给系统 —— 只记录、不拦截,不会因为加了日志把崩溃吞掉。

顶部胶囊加图标

主界面的「高山攀登 / 徒步」胶囊前面加了 14dp 图标,与弹层里那两枚同源。


v0.19.28 要点

开屏 logo 缩小 40%

开屏中央的雪山标记按中心等比缩到原来的 60%,图形高度从 188/288 降到约 113/288。留白更足,小屏设备上不再显得笨重。桌面图标没动。

课程大类切换图标重画

底部弹层里两个大类原来用的是文本字符:攀登是「▲」、徒步是「≡」——三条横杠完全看不出和徒步的关系。现在换成两枚实心卡通图标:

  • 高山攀登:三角山体 + 一条锯齿雪线(挖空),比纯三角多一层「雪山」的信息
  • 徒步:登山靴——鞋帮、带齿鞋底、两道鞋带。44dp 下轮廓清楚,也不会和雪山混淆

图标是 24 网格的实心剪影,evenodd 挖孔,仍然用 Icon(tint = ...) 整体着色,所以选中态(绿底白图标)与未选中态(灰底灰图标)共用同一份路径,不额外增加资源。

另外在画布上放了一版「顶部胶囊加 14dp 图标」的预览,如果那个方向也想要,说一声我就加。


v0.19.27 要点

成就系统与 89 课新题库对齐

成就定义写于「66 课、只有攀登一条线」的时代,题库铺到 89 课(攀登 68 / 徒步 21)之后有两条判定脱节了:

  • full_route 理论大满贯:目标写死 66 课,实际攀登已有 68 课;更要紧的是判定写的是「当前轨道所有单元都完成」,于是徒步走完 21 课就能拿到「理论大满贯」。
  • five_zones 五区足迹:按「任意 5 个单元各完成 ≥1 课」计数,攀登现在有 6 个单元、徒步只有 4 个 —— 徒步线上永远拿不到。

两条都改成显式点名单元:full_route → 攀登大满贯(68 课),five_zones → 六区足迹(攀登 6 个单元各完成 ≥1 课)。

徒步线补上 5 枚成就

徒步 21 课此前一枚成就都没有,走完整条线没有任何反馈。按攀登那套节奏补齐:

成就 条件 稀有度
走出第一步 完成 t01(线路难度与自我定位) 普通
扎营一夜 徒步单元 t2(多日与露营)全部 8 课 稀有
高原行走 徒步单元 t3(高原徒步)全部 5 课 稀有
徒步毕业 徒步全部 21 课 史诗
双线并进 攀登 ≥10 课且徒步 ≥10 课 史诗

成就总数 35 → 40。五枚新徽章暂时共用一张占位图(badge_placeholder_agi),等专属徽章画好逐个替换即可,业务定义不用动。

顺手修的判定口径

成就的单元/轨道进度过去按当前选中轨道统计。这在单线时代没问题,双线之后就错了:切到徒步轨道时攀登进度会变成 0,full_route 这类成就会反而更容易命中。现在统一按全部轨道统计(新增 AchievementStats.trackProgress),与「已完成课程 id」这套全局进度一致。

开发者测试区的条件校验也改成拿全轨道的课程/单元 id 比对,否则徒步的 t01、t1–t4 在攀登轨道上会被误报成「引用了不存在的课程」。

同源问题还修了一处显示 bug:个人主页与「我的」页的路线进度,分子数是两条轨道的完成总数、分母却是当前轨道的课数,攀登学完切到徒步会显示「68 / 21 课」。现在分子只数当前轨道。

已知待办:五枚新成就的文案目前只有中文原文,其余九种语言会回退显示中文。下一批 i18n 会把 10 个新键一次性加进十语言对齐。


v0.19.26 要点

简体中文系统上装完却是繁体

这是 Android 资源匹配的经典坑:values/(默认桶)装的是简体,但它没有语言限定符;繁体装在 values-zh-rTW 里,有限定符。系统语言是 zh-CN 时,框架先找 zh-rCN(不存在),再找「同语言变体」,于是命中了繁体桶 —— 整个界面变繁体。

手动去语言页选一次「简体中文」会恢复正常,因为手动选择时框架给请求带上了脚本子标签,请求变精确才绕开繁体桶。这正好解释了「自动检测是简体、界面却是繁体、手动切一下才对」。

修法是给简体补一个精确桶:构建时把 res/values/strings.xml 复制成 values-zh-rCN/strings.xml(Gradle 任务 genZhCnRes,在 preBuild 之前生成)。精确匹配永远赢过「同语言变体」,简体系统从此稳定走简体桶。单一事实来源仍然是 res/values/strings.xml,生成目录不要手改。

顺带修了一处同类判定:简体繁体过去只看地区,于是「港澳台地区用简体」(zh-Hans-HK / zh-Hans-MO / zh-Hans-TW)会被误判成繁体。现在脚本优先于地区 —— 显式 Hans 一律简体,显式 Hant 一律繁体,没有脚本时才看地区。界面语言与内容层(课程名、题库)两处的归一规则已同步。


v0.19.25 要点

一个纯修问题的版本,两处都是老毛病。

开屏中央不再有黑色底

开屏(Android 12 及以上的系统启动画面)中央那块一直是个深色圆盘,因为系统默认拿桌面图标来画,而桌面图标是自适应图标——深色底 #0B1522 上叠了一座雪山,在浅色启动背景上就露出了黑底。

现在给启动画面单独挂了一幅透明底的雪山矢量(ic_splash_mark),只画山体、雪帽、旗杆和旗面,不带任何底板:

  • 浅色模式启动背景 #F1F6FA、深色模式 #070D16,都与进入后的页面底色一致,图标切换过去不会跳色
  • 图标内容落在中央 192dp 安全区内,各屏幕密度下都不会被裁切
  • 桌面上的图标本身没动,仍是原来的黑底雪山

Android 11 及以下没有系统启动画面图标,不受影响。

修好「开发者模式 → 成就测试」点不进去

设置页里那个「成就测试」按钮点了没反应,界面纹丝不动。原因是分支判断顺序:成就测试页是从设置页里打开的,showSettings 一直是 true,而判断链里 showSettings 排在 showAchievements 前面,于是永远先命中设置页。

把 showAchievements 提到 showSettings 之前即可。现在点进去是成就测试页,返回回到设置页,与直觉一致。成就解锁弹窗本身一直是正常的,这次没碰。


v0.19.24 要点

从 v0.19.11 算起,这一系列版本只做了一件事:把内容层铺到十种语言。v0.19.24 是收官——最后一种语言(Italiano)四层全量,十种界面语言全部有内容支撑,运行时不再回退。

语言:十种界面语言,九种翻译语言四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Italiano 补到全量:

  • Italiano:9,422 条题库 + 443 条要点 + 全部课名、单元名、山峰与技能书 h32–h35。题干与解析用 tu,要点用无人称句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español / Français / Svenska,九种翻译语言与英文键集合逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。简体中文作为原文语言,内容层本身就是它——十种界面语言至此全部落地。

顺带清了最后一批历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,其余语言在逐语补齐的过程中陆续跟上。十种语言现在都没有孤儿键。

如果某一项在所选语言里意外缺失,回退顺序是「当前语言 → 英文 → 中文原文」。这条路径现在只是兜底,正常不会再触发。

三种数字写法,刻意分开

同一套内容,各语言按本地习惯写数字。三种口径在译文和术语表里都标住了,不会混:

  • 英文、中文、日文:6.5 °C、5,000 m
  • 德文、西文、意文:6,5 °C、1.000 m(小数逗号、千位点)
  • 法文、瑞典文:6,5 °C、5 000 m(小数逗号、千位空格)

人称也各自不同:德文无人称 man-Form、西文 tú、法文 vous、瑞典文与意文 du / tu,而课程要点在所有语言里都是无人称句。

术语一致性

各语言沿用自己登山圈既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken
  • 西文:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、cinta transportadora de nieve
  • 法文:nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke、kort fast rep、expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla
  • 意文:corda fissa、corrimano、attrezzamento della via、rinvio intermedio (re-belay)、guasto in serie、bloccante per mano / pettorale、nastro trasportatore di neve、seppellimento critico、sacca d'aria

医学与救援的硬数字一律照技能书原值,不取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限、队伍内控 0,8、水位 15 cm、胸带必解;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 题库按语言拆文件:单个 Kotlin 文件约 2,500 条会让编译守护进程崩溃(Daemon compilation failed: null),所以英文、繁中、日文、俄文、德文、西文、法文、瑞典文、意文各拆三支,合并行在 ContentPack.kt
  • tools/i18n/ 的三个命令(status.py / prep.py / apply.py)在十种语言上通用,--lang 决定读写哪一套包;繁中另有 tw.py、tw_entry.py
  • 每批译文进库前跑五项自查:键集合与「真实缺失集」的差集(缺 + 多)、片段内重复键、CJK 残留、英文单词残留、空值键。其中「多」这一栏在最后三种语言里抓出了六次误插的空值占位行

v0.19.23 要点

从上个发布版(v0.19.21)到现在,还是同一件事:把剩下的语言也铺满。

语言:内容层现在是八种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Français 与 Svenska 补到全量,并清理了两门语言里的历史遗留键:

  • Français:9,422 条题库 + 443 条要点 + 全部课名与技能书。题干与解析用 vous,要点用无人称句
  • Svenska:同上。题干与解析用 du,要点用陈述句

加上此前完成的 English / 繁體中文 / 日本語 / Русский / Deutsch / Español,八种语言现在与英文逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。

顺带清了法文与瑞典文里各 5 条历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,这几门语言陆续补上。只剩 Italiano 还有这 5 条,收尾时一并处理。

最后一种语言(Italiano)仍覆盖扩充前的旧题库,新增题目回退英文——这是设计行为,不是缺失。

数字写法:三种口径,不要混

同一套内容,各语言按本地习惯写数字,这一点在译文和术语表里都标住了:

  • 法文与瑞典文:小数逗号,千位空格(6,5 °C、5 000 m、8 848,86 m)
  • 德文与西文:小数逗号,千位点(6,5 °C、1.000 m)
  • 英文与中日文:6.5 °C、5,000 m

术语一致性

法文与瑞典文都沿用各自语言里既有的专业写法,不做音译:

  • 法文:autorretención 体系对应 autorétraction、nœud autobloquant、défaillance en série、tapis roulant à neige、ensevelissement critique、poche d'air、phase d'asphyxie / de latence、ECLS
  • 瑞典文:handräcke / kort fast rep / expeditionsutläggning、mellanförankring (re-belay)、seriefel(对 redundans)、snötransportband、lufthåla、kvävningsfas / latensfas

医学与救援的硬数字一律照技能书原值,不做取整:雪崩存活 48 / 47,6 / 96 %,死因窒息 65–100 %、创伤 5–29 %、低温 0–4 %;决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径;搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min;渡河 1,0 m²/s 上限;固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 法文题库拆三支(PackFrQuiz / 2 / 3),瑞典文同样三支;单文件过大会让 Kotlin 编译守护进程崩溃
  • tools/i18n/ 的三个命令扩到十种语言通用,--lang 参数决定读写哪一套包

v0.19.21 要点

从上个发布版(v0.19.11)到现在,只做了一件事:把剩下两种语言也铺满。

语言:内容层现在是五种语言全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库)。这一版把 Deutsch 与 Español 补到全量,与英文键集合逐条对齐:

  • Deutsch:9,422 条题库 + 443 条要点 + 全部课名与技能书,体例为无人称 man-Form,数字走德式写法(6,5 °C、1.000 m、35–50 Liter)
  • Español:同上,题干与解析用 tú、要点用无人称句,数字走西式写法(6,5 °C、1.000 m)

加上此前完成的 English / 繁體中文 / 日本語 与 Русский,六种语言现在与英文逐条一致(10,544 / 10,544),缺项 0、重复 0、孤儿键 0。

顺带清了德文与西语里各 5 条历史遗留的孤儿键(q.l2#5.c、m15#17.c、m16#18.c、m16#22.c、m16#24.c)——中文侧早前删过带上下文的情景题,英文当时清了,这两门语言没跟上。

其余三种语言(Français、Svenska、Italiano)仍覆盖扩充前的旧题库,新增题目回退英文——这是设计行为,不是缺失,后续按同一 key 体系逐语铺开。

术语一致性

德文与西语都沿用各自语言里既有的专业写法,不做音译:

  • 德文:Selbstbremsgriff、Flachfusstechnik、Klemmknoten、Prusiken、Fussstrippe、Umlenkpunkt、Schneefang、Wechte、Apsis、versunkener Aufwand、Gruppendenken、Bestätigungsfehler、Ankereffekt
  • 西语:autorretención、técnica francesa、nudo autobloqueante、refilado、reunión、cordada、ARVA、placa de viento、calicata、cinta transportadora de nieve、cat hole

医学与救援的硬数字一律照技能书原值,不做取整:雪崩存活 48 / 47,6 / 96 %,决策线 2023 版 60 分钟并保留 2013 版 35 分钟作为历史口径,搜索带 40 m、定点网格 25 cm、雪传送带 26° 与 13,2 / 25,3 cm/min,渡河 1,0 m²/s 上限,固定绳 EN 892 / 1891 A / 567 / 12277。

工程

  • 西语题库拆成三支(PackEsQuiz / 2 / 3),德文同样三支;单文件过大会让 Kotlin 编译守护进程崩溃
  • tools/i18n/ 的三个命令扩到十种语言通用,--lang 参数决定读写哪一套包

v0.19.11 要点

从上个发布版(v0.18.35)到现在,主要是两件事:内容翻了一倍多,以及三种语言做到全量。

内容扩充:47 课 → 89 课

  • 攀登轨道从 47 课扩到 68 课,补上 6000 / 7000 / 8000 米三个高海拔单元,含慕士塔格、阿玛达布朗、玉珠、启孜、罗布切东、岛峰,以及世界 14 座 8000 米峰的课程
  • 新增徒步轨道 21 课:一日徒步、多日与露营、高原徒步、长线与应急四个单元
  • 题目 711 → 1,533 道(9,422 条 key:题干、选项、解析),技能书 31 → 35 篇,新增雪崩埋压、雪崩复苏、雪崩三件套、固定绳系统、渡河五篇
  • 新增约 100 座山峰资料、成就系统
  • 题库版本 v15 → v19

语言:英文、繁體中文、日文四层全量

内容层分四层(入口 / 课程要点 / 技能书正文 / 题库),这三种语言现在每层都完整,运行时不再回退中文:

  • English:9,422 条题库 + 443 条要点 + 全部课名与技能书
  • 繁體中文:走 OpenCC s2twp 加一份术语表(確保站、高山症、公尺等),并用既有 4,727 条译文做回归校验,复现差异为 0
  • 日本語:题库用 ですます調、技能书与要点用 だ・である調,两层语体分开;术语沿用库内...
Read more