Commit Graph

9 Commits

Author SHA1 Message Date
230180febf 新增 docs/:商店文案、图标与各机型截图
Connect IQ Store 后台要填的素材都放进 docs/,代码不依赖其中任何文件。

截图
  八个屏宽各一张(218/240/260/280/360/390/416/454),外加七套主题各一张。
  全部是模拟器的真实渲染 —— 字体是 Garmin 内置的 Roboto / Bionic,和真机一致。
  preview-themes.svg 用的是网页字体,不能拿去当商店截图,docs/README.md 里
  特别提了这点。

  ⚠️ 进度环是摆拍的。模拟器的 Edit Activity Monitor Info 只能改活动分钟、
  恢复时间、呼吸和压力,改不了步数/距离/卡路里(那几个输入框是 Java 自绘的
  表格,AppleScript 也够不着),所以环在模拟器里永远全灰。截图构建把四段弧
  固定成了设计稿的填充状态。除环之外画面上每个数字都是模拟器的真实取值。

  数据位用的是日出/高低温/心率/身体电量,不是默认的日出/高低温/距离/步数 ——
  后两项在模拟器里是 0,截出来底部是 "0.0 0"。这些都写进 docs/README.md 了。

文案
  中英文各一份,含名称、简介、详细描述、关键词、以及要向用户解释的四项权限。
  详细描述按「进度环 / 四个数据位 / 七套主题 / 常亮 / OWM 选用 / 其它」组织,
  156 项字段按分类列出。

图标
  store-icon-1024.png 与 512.png,与启动图标同一套视觉(渐变环 + 橙色日期带),
  由 tools/gen_icons.py 的 launcher() 渲染。

docs/README.md 还记了后台要填但不在仓库里的项(分类、价格、隐私政策 —— 启用
OWM 时会把坐标发给 api.openweathermap.org,这点建议在描述里写明),以及发布
前必须先解决的设计稿授权问题。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 12:21:22 +08:00
696b728c78 收紧常亮模式:去掉进度环,时间日期压暗到 38%
按要求把常亮再砍一档。常亮下现在不画:整条日期带底色、整个进度环、
四个数据位与电池;保留的时间、冒号、日期由 55% 压暗到 38%。

实测(fenix847mm,取表盘内区):

                  点亮像素数    平均亮度(功耗代理)
    普通模式         27.6%          14.1%
    常亮(改前)      10.4%           3.0%
    常亮(改后)       9.7%           2.5%

两个口径的差别值得记一笔:「点亮像素数」把每个抗锯齿边缘像素都算成亮的,
对大号数字表盘天然不友好 —— 时间数字压到 38% 后白色仍有 ~97 亮度,照样计入。
AMOLED 的实际功耗更接近各子像素亮度之和,也就是「平均亮度」那一列。
两个口径现在都留了余量,38% 下时间和日期在模拟器里依然清晰可读。

LICENSE、UserProfile 的 try 保护、CHANGELOG 与版本号 1.1.0 已在上一个提交
22340b0 完成,本次只动常亮相关部分与对应文档。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:37:58 +08:00
22340b09fa 机型覆盖 17 → 55 款,补 LICENSE 与 CHANGELOG
机型
  新增 38 款圆屏 + CIQ ≥ 4.2 的机型:fenix 7 Pro 全系、Venu 2/3S、
  Approach S50/S70、Descent G2/Mk3、D2 系列、Instinct 3 AMOLED、
  FR255S/265S/570/955 等。其中 34 款的屏宽已有现成图标资源。

  机型列表和 monkey.jungle 改由 tools/gen_devices.py 扫描本机 SDK 生成,
  筛选条件是「支持 watchFace + 圆屏 + CIQ ≥ 4.2」(Complications 要 4.2)。
  55 条资源路径不再手写。

  新增 218px 与 360px 两档图标。218px 上图标只有 14×14,设计稿里太阳与云
  之间那道 1.7 设计像素的暗缝连一个物理像素都占不到,光栅化出来是一坨没有
  结构的橙块 —— 该尺寸改用按目标像素直接摆的简化标记。

常亮模式:结论是不改
  为了压所谓的 10% 点亮率,一度把进度环也砍掉了。换成平均亮度(AMOLED 功耗
  的合理代理)重新量之后发现:普通模式 14.1%,常亮 2.9%,本来就只有 1/5;
  砍掉环只从 3.01% 降到 2.91%。0.1 个百分点换掉一个可见特征不划算,环留着。
  两种度量的差异和这个决定都写进了代码注释和 README。

其它
  - LICENSE(MIT)。只覆盖代码 —— design/ 下的设计稿版权归第三方,
    发布前需取得原作者授权或替换视觉,文件内已注明。
  - UserProfile.getProfile() 加异常保护(这个 API 家族已经坑过三次)
  - CHANGELOG.md,版本号 1.0.0 → 1.1.0

验证:55 款全部编译通过(分三批 18+18+19);.iq 上架包可正常导出。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:27:54 +08:00
d9d45d983b 接入系统 Complication,补齐倒计时/自定义格式/28天累计/空气质量
字段 125 → 156 项。

Toybox.Complications(source/Comp.mc)
  这条路推翻了我之前几个「表盘做不到」的判断 —— 当时只查了 ActivityMonitor /
  UserProfile / Weather,漏了系统把这些作为 complication 发布出来:
    - 下一个日程(CIQ 确实没有日历 API,但有 CALENDAR_EVENTS complication)
    - 训练状态、完赛预测 ×4、配速预测 ×4、最近高尔夫得分
    - 本周跑步 / 骑行距离(按运动分类的,按天历史做不出来)
    - 第三方 App 1–5(CGM、补水、行情这类 App 发布的)
  需要 ComplicationSubscriber 权限。

其余补齐
  - 近 28 天累计:步数 / 卡路里 / 距离 / 楼层
  - 事件倒计时:设置里填 YYYY-MM-DD,显示还剩几天
  - 自定义时间格式、日期格式 1/2:单字母占位符(h/H/m/s/a/D/M/N/Y/y/w)
  - OWM 空气质量:AQI 等级 + 描述 + PM2.5 + PM10 + CO,走
    /data/2.5/air_pollution —— 那个接口在免费档就开放,不需要 One Call 订阅

运行时踩的坑
  - Complication.unit 不保证是 String(周跑步距离返回的就不是),直接调
    .length() 抛 Symbol Not Found。unit 和 shortLabel 都改成先 instanceof 判型。
  - 浮点 value 直接 toString 印成 "0.000000",统一格式化成一位小数。
  - 第三方 App 槽位每取一次就要走完整个迭代器,四个格子都选 App 时会走四遍。
    改成每帧只枚举一次,由 view 在绘制开始时调 Comp.beginFrame() 失效。

测试
  全字段验证的 harness 本身会触发看门狗(一次 onUpdate 里算 156 个字段),
  改成分批每帧 12 个。实际使用一帧只算 4 个,不受影响。
  156 项全部可渲染,零运行时错误;17 款设备全部编译通过。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 09:03:21 +08:00
4d96ab0912 Update watch face: modular refactor + OWM/Solar/background + codegen tools
- Split render into FieldTable/Fields/Icons/Layout/Settings modules
- Add Fenix8V3Background, Owm (weather), Solar modules
- Add tools/ generators (gen_fields/gen_icons/gen_themes/gen_preview_svg)
- Tune README/manifest/strings/settings
2026-09-10 07:10:55 +08:00
52346bdd09 Split the face into modules, comment it, and verify every field
Architecture
  Fenix8V3View had grown to 632 lines mixing layout constants, font
  metrics, icon drawing, data lookup and orchestration.  Split into:

    Layout    the 500-canvas constants, scaling, font choice and text drawing
    Icons     the three bitmap icons plus the primitive glyphs
    Settings  every stored preference and its default, in one place
    Fields    unchanged in scope, but value() is now seven category
              functions that each return null for ids they do not own --
              the ids interleave, so dispatching on ranges does not work
    View      what is left: the drawing order

  The view is down to 359 lines and no longer reaches for a property or a
  font metric directly.

Verification
  Added a harness that walks all 75 ids in the simulator and reports each
  rendered value with its pixel width.  It caught a real one: pushDistance
  and pushes compile on every device but throw "Symbol Not Found" at
  runtime on a fenix 8 -- they are wheelchair counters that only some
  firmware carries.  Every optional ActivityMonitor, UserProfile, Weather
  and Activity member is now behind a `has` check.

  The same run showed two date fields overflowing their slot, so long
  values now step down a font size rather than running into the ring.

  Always-on mode checked against the simulator's Always-On display mode:
  band fill gone, unlit ticks gone, slots hidden, time and date dimmed.

Also: Chinese "Day Date" was missing its 日, since it built the string by
hand instead of going through the localised date format.

All 17 devices build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 05:48:58 +08:00
d457f8244e Add the on-device data field catalogue, always-on mode, and real icons
Fields
  75 selectable fields across date/time, activity, body, system,
  environment, weather and custom text, numbered to match
  watchface.io/docs/datafields so the two catalogues line up.  All four
  slots (both top, both bottom) pick from the same table and the bottom
  captions follow the selection.  tools/gen_fields.py owns the table and
  emits FieldTable.mc, settings.xml and both languages' strings, so those
  cannot drift apart.

  Fields.Ctx fetches each API at most once per draw, and only if some slot
  asks -- the forecast, user profile and sensor history lookups are lazy.

  The rest of that catalogue is deliberately absent: OpenWeatherMap and
  StormGlass need network calls and user API keys, the per-sport weekly and
  28-day aggregates come from a phone-side Garmin Connect integration rather
  than any on-device API, and the app complications need those apps
  installed.  README section 7 lists what was left out and why.

Permissions
  UserProfile and SensorHistory are now declared; without them resting heart
  rate, VO2 max, pulse ox and body battery throw at runtime.  Sensor turns
  out to be rejected outright for type="watchface", so altitude and pressure
  read from Activity.Info instead.

Always-on display
  AMOLED devices need the lit-pixel count cut while asleep.  drawAmbient
  drops the band fill and the unlit ticks, dims what remains, hides the
  complications, and walks the layout within +/-4 px per minute so nothing
  burns in.  Gated on requiresBurnInProtection, so MIP devices are untouched.

Icons
  The comps' sunrise and weather icons have two- and three-pixel features.
  Rebuilding them from circles and lines looked right at 454 px and turned to
  mush at 280.  They are now rasterised from the design paths once per screen
  width and tinted with drawBitmap2(:tintColor) -- which needs
  packingFormat="png", since a palettised source is refused at runtime.
  Launcher icons are generated at the five sizes the devices ask for.

All 17 devices build; checked on fenix847mm and enduro3 in the simulator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 23:53:18 +08:00
398018b51e Rebuild the face against the design kit; make fields configurable
Vendor the watchface-kit into design/ and derive everything from it instead
of from hand-transcribed constants.

Geometry, from design/rebuild.py and the ink boxes of the traced SVG paths:
  - ring ticks are annular sectors (fillPolygon), not radial lines
  - top arc is 21 ticks at 6.5+4k, not 22 at 2+4k
  - exact radii, tick widths, anchor dots, band and colon rectangles
  - element positions taken from measured ink bounding boxes

Colour, generated by tools/gen_themes.py straight out of the comps:
  - per-tick colour tables (21+21) replace 9/7 interpolated stops
  - 11-stop vertical gradients on the time digits, drawn with clip banding
  - per-element accent / value colours and per-theme unlit tick colour

Data: the design's sunrise and hi/lo fields turn out to be available after
all -- Weather.getSunrise and getDailyForecast both exist in SDK 9.1.0 --
so both are restored, and heart rate is added alongside them.

Bugs found on the way:
  - Gregorian FORMAT_MEDIUM returns day_of_week/month as strings, so the
    date band crashed on every update (caught in the simulator)
  - Stats.battery is already 0-100, multiplying by 100 gave "4000%"
  - moveBarLevel is an integer level 0..5, not a 0..1 ratio, so the move
    bar arc was all-or-nothing

Also: all four field slots are configurable with labels that follow the
selection, temperature unit is a setting, on-face wording moved into
resources with a Simplified Chinese variant, and 24h/distance/temperature
now follow the watch. Fonts are chosen by measured cap height rather than
by ascent.

Verified in the Connect IQ simulator on fenix847mm and by compiling all
17 target devices.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 22:04:27 +08:00
553c55026a Initial commit: Fenix 8 V3 data watch face
- Restore watchface-kit design (500x500, scaled per device)
- 7 themes auto-generated from tokens via gen_themes.py -> Themes.mc
- Four-segment gradient progress ring (22+21 ticks, 4 anchor dots)
- Center time, date band w/ Bluetooth icon, top battery + dual complications, bottom distance/steps
- 17 devices compiled clean (SDK 9.1.0)
- Includes browser/JS preview (preview.html) + 7-theme SVG sheet
2026-09-09 14:40:33 +08:00