Files
fenix8v3-watchface/source/Fenix8V3App.mc
ericwyuan 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

87 lines
3.4 KiB
MonkeyC
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Toybox.Application;
import Toybox.Background;
import Toybox.Lang;
import Toybox.System;
import Toybox.Time;
import Toybox.WatchUi;
import Owm;
// ============================================================================
// 应用入口
// ----------------------------------------------------------------------------
// 表盘没有菜单也拿不到输入,所以这个壳子只做三件事:
// 1. 交出 view
// 2. 设置变更时请求重绘
// 3. 管理拉取 OpenWeatherMap 的后台服务
// ============================================================================
class Fenix8V3App extends Application.AppBase {
// OWM 免费档的调用额度很宽裕,但表盘每分钟才重绘一次、数据本身也是小时级的,
// 拉太勤只是白白唤醒射频费电。半小时是个合适的折中。
const OWM_PERIOD_MIN = 30;
function initialize() {
AppBase.initialize();
}
function onStart(state as Dictionary?) as Void {
}
function onStop(state as Dictionary?) as Void {
}
// ⚠️ 定时器的注册必须放在 getInitialView 里,不能放 onStart。
// 因为 onStart **在后台服务进程里也会被调用一次**,而在后台进程里调
// registerForTemporalEvent 会抛 Out of Bounds。
// getInitialView 只在前台进程运行,是安全的位置。
function getInitialView() as [Views] or [Views, InputDelegates] {
scheduleWeather();
return [new Fenix8V3View()];
}
function getServiceDelegate() as [System.ServiceDelegate] {
return [new Fenix8V3Background()];
}
// 只有用户真的填了 API key 才注册定时器 —— 没填就没什么可拉的,
// 注册了纯属浪费电。反过来,用户把 key 清空时也要及时注销。
function scheduleWeather() as Void {
if (!(Background has :registerForTemporalEvent)) { return; }
// ⚠️ deleteTemporalEvent 在「本来就没注册」时会抛 Out of Bounds
// 而这个错误是 VM 级的,**try/catch 抓不住**。
// 所以这里不去问系统当前状态,而是自己在 Storage 里记一个标志位。
// 重复注册本身是无害的(只是重置周期),所以只在状态真的变化时动手。
var want = Owm.enabled();
var have = Application.Storage.getValue("bgOn");
have = (have != null) && (have as Boolean);
if (want == have) { return; }
if (want) {
Background.registerForTemporalEvent(
new Time.Duration(OWM_PERIOD_MIN * 60));
} else {
Background.deleteTemporalEvent();
}
Application.Storage.setValue("bgOn", want);
}
// 手机把新设置推下来时触发。
// view 每次绘制都是现读设置,所以重绘一下就够了;
// 但天气定时器要跟着新的 key 状态启停,所以先过一遍 scheduleWeather。
function onSettingsChanged() as Void {
scheduleWeather();
WatchUi.requestUpdate();
}
// 后台服务把结果通过这里交回前台。存进 Storage 供表盘读取,然后重绘。
function onBackgroundData(data as Application.PersistableType) as Void {
if (data != null) {
Application.Storage.setValue(Owm.STORE, data);
WatchUi.requestUpdate();
}
}
}
function getApp() as Fenix8V3App {
return Application.getApp() as Fenix8V3App;
}