Files
o62lte-customising-plan/s5e-pressure-anim/tools/s5e_pages.py
T
2026-10-03 00:01:12 +08:00

151 lines
8.0 KiB
Python
Raw 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.
# -*- coding: utf-8 -*-
"""Xiaomi Watch S5 eSIM (p62lte) 480x480 页面规格。
坐标系就是 `main.lua` 用的那一套;`s5e_render_ui.py` / `s5e_check_clip.py` 画的是同一份规格,
所以预览图是"诚实"的(不是另画一套)。与 S5 图标包那份 480 设计稿同一套语言,
只是页面文案改成压力动画替换器。
"""
import os
from paths import PROJ, DOCS, ASSETS
W = H = 480
BG = (0, 0, 0)
GRAY = '999999'
WHITE = 'ffffff'
PLATE = '002927'
CIRCLE = '4f4f4f'
OK = '43cf7c'
ERR = 'd43030'
S600, S500, S400 = 'semibold', 'medium', 'regular'
# 列表项几何
# radius=40 不是审美选择:y=88 那一行离圆心 152px,圆屏在那里的弦半宽只有 √(240²-152²)=185.8,
# 也就是该行 x 只能在 54.2..425.8 之内。底板是 x=50 w=379,圆角不够大时四个角会越过圆边
# (r=35 时角点半径 240.7 → check_clip 记为越界)。r=40 正好把角收进去。
ITEM_X, ITEM_W, ITEM_H, ITEM_R = 50, 379, 91, 40
ICONC_DX, ICONC_DY, ICONC_SZ = 21, 20, 52
ICON_DX, ICON_DY, ICON_SZ = 31, 30, 31
TITLE_DX, TITLE_DY, TITLE_W, TITLE_H = 82, 26, 214, 42
ICON_PNG = {'ic_help': 'MdiLightbulbOutline.png', 'ic_replace': 'MdiBandage.png',
'ic_about': 'MdiInformationOutline.png', 'ic_check': 'MdiClipboardTextSearchOutline.png',
'ic_rollback': 'MdiReplyAllOutline.png', 'ic_qq': 'qq.png'}
def item(y, iconkey, title):
return [
dict(kind='rect', x=ITEM_X, y=y, w=ITEM_W, h=ITEM_H, bg=PLATE, radius=ITEM_R),
dict(kind='circle', x=ITEM_X + ICONC_DX, y=y + ICONC_DY, w=ICONC_SZ, h=ICONC_SZ, bg=CIRCLE),
dict(kind='image', x=ITEM_X + ICON_DX, y=y + ICON_DY, w=ICON_SZ, h=ICON_SZ,
src=os.path.join(ASSETS, ICON_PNG[iconkey])),
dict(kind='label', x=ITEM_X + TITLE_DX, y=y + TITLE_DY, w=TITLE_W, h=TITLE_H,
text=title, size=29, weight=S500, color=WHITE, align='left', vtop=True),
]
def clock(t='10:24'):
return dict(kind='label', x=201, y=4, w=78, h=40, text=t, size=29,
weight=S600, color=GRAY, align='left', vtop=True)
def title(text, x, w=260):
return dict(kind='label', x=x, y=36, w=w, h=42, text=text, size=31,
weight=S500, color=WHITE, align='left', vtop=True)
def back_arrow(x=167):
return dict(kind='image', x=x, y=44, w=18, h=29, src=os.path.join(ASSETS, 'backarrow.png'))
def big_button(y, text):
return [
dict(kind='rect', x=111, y=y, w=258, h=82, bg=PLATE, radius=41),
dict(kind='label', x=182, y=y + 22, w=126, h=40, text=text, size=29,
weight=S500, color=WHITE, align='left', vtop=True),
]
# ------------------------------------------------------------------ 页面
# 所有文字的像素宽度都用真 MiSans 量过(tools/s5e_render_ui.py 同一套字体):
# 31px: 'S5e Pt.2'=125 '快速帮助'/'开始替换'/'正在替换'=124 '关于'=62
# 29px: '确认替换'/'重启手表'=116 '环境预检查'=145 '732681995'=155
# 25px: '检查 health 分区与负载完整性。'=369 '恢复 119 帧动画的原厂样式。'=331
# '预检查通过 | 119 条 | 15.49MB'=349 'Xiaomi Watch S5 eSIM 46mm'=367
# 圆屏在高度 y 处的弦半宽 = √(240² - (y-240)²),所以**越靠下的行越窄** ——
# 型号那行原来放在 y=229(弦半宽只有 171),'Xiaomi Watch S5 eSIM 46mm' 宽 367 直接被切掉。
# 现在把该行拆成两行、整体上移到 y=195 / 228,两行都短于那里的弦。
PAGE_HOME = [clock(), title('S5e Pt.2', 177, 127),
*item(88, 'ic_help', '快速帮助'),
*item(186, 'ic_replace', '开始替换'),
*item(285, 'ic_about', '关于')]
_HELP_HEAD = [clock(), back_arrow(167), title('快速帮助', 188, 124)]
# 说明文字必须**单行**放下(折行后第 2 行会越出圆屏,check_clip 抓过):
# y=182 处圆屏弦半宽 = √(240²-58²) = 232.9,x 从 64 起时最多能到 64+232.9 = 296.9...
# 实际用 380 的框宽是安全的(文字宽 354px < 380,且落在 64..444 内)。
_HELP_D1 = dict(kind='label', x=64, y=182, w=380, h=35,
text='检查 health 分区与负载完整性。', size=24,
weight=S500, color=GRAY, align='left', vtop=True)
_HELP_I2 = item(264, 'ic_rollback', '回滚修改')
_HELP_D2 = dict(kind='label', x=67, y=360, w=348, h=35,
text='恢复 119 帧动画的原厂样式。', size=25,
weight=S500, color=GRAY, align='left', vtop=True)
PAGE_HELP = _HELP_HEAD + item(88, 'ic_check', '环境预检查') + [_HELP_D1] + _HELP_I2 + [_HELP_D2]
# 预检查结果:最多 2 行(24px 行高 33,框高 76 >= 2*33)
HELP_DESC_OK = dict(kind='label', x=67, y=182, w=348, h=76,
text='预检查通过 | 119 条 | 15.49MB\nhealth 分区可读。',
size=24, weight=S500, color=OK, align='left', vtop=True)
HELP_DESC_ERR = dict(kind='label', x=67, y=182, w=348, h=76,
text='预检查失败:设备节点读不到,\n或分区头不是 ROMFS。',
size=24, weight=S500, color=ERR, align='left', vtop=True)
PAGE_HELP_OK = _HELP_HEAD + item(88, 'ic_check', '环境预检查') + [HELP_DESC_OK] + _HELP_I2 + [_HELP_D2]
PAGE_HELP_ERR = _HELP_HEAD + item(88, 'ic_check', '环境预检查') + [HELP_DESC_ERR] + _HELP_I2 + [_HELP_D2]
# 警告页:每行单独一个框(h=34 ≈ 25px 真行高 35),行距 34。
# 最下面那行放在 y=341:圆屏在 y=375 处正好收成一点,所以底边必须留在 375 以上。
WARN_LABELS = [
dict(kind='label', x=60, y=95, w=360, h=35,
text='替换压力检测动画之前,', size=25, weight=S500, color=GRAY,
align='left', vtop=True),
dict(kind='label', x=60, y=129, w=360, h=35,
text='请先确认自己的系统版本号为 ', size=25, weight=S500, color=GRAY, align='left', vtop=True),
dict(kind='label', x=304, y=129, w=120, h=35, text='3.112.035',
size=25, weight=S500, color=WHITE, align='left', vtop=True),
dict(kind='label', x=422, y=129, w=40, h=35, text='!',
size=25, weight=S500, color=GRAY, align='left', vtop=True),
# 型号拆成两行:y=195 处弦半宽 195,y=228 处 173 —— 367px 的长行只能拆
dict(kind='label', x=64, y=195, w=360, h=35, text='请确认自己的手表型号为',
size=25, weight=S500, color=GRAY, align='left', vtop=True),
dict(kind='label', x=64, y=229, w=360, h=35, text='Xiaomi Watch S5',
size=25, weight=S500, color=WHITE, align='left', vtop=True),
dict(kind='label', x=64, y=263, w=360, h=35, text='eSIM 46mm(p62lte)',
size=25, weight=S500, color=WHITE, align='left', vtop=True),
dict(kind='label', x=60, y=341, w=360, h=35, text='搞机有风险,变砖后果自负。',
size=25, weight=S500, color=GRAY, align='left', vtop=True),
]
PAGE_CONFIRM = [clock(), back_arrow(167), title('开始替换', 188, 124)] + WARN_LABELS + big_button(376, '确认替换')
LOG_MID = ('> 开始替换\n'
'> health 119 条\n'
'> 写入 60/119 成 60 失 0\n'
'> 替换完毕,请重启手表。\n'
'> 若发现问题,请回滚修改。')
PAGE_RUNNING = [clock(), title('正在替换', 178, 124),
dict(kind='label', x=67, y=95, w=348, h=280, text=LOG_MID, size=24,
weight=S500, color=WHITE, align='left', vtop=True),
*big_button(376, '重启手表')]
PAGE_ABOUT = [
clock(), back_arrow(198), title('关于', 220, 62),
dict(kind='rect', x=54, y=81, w=373, h=210, bg=PLATE, radius=31),
dict(kind='image', x=200, y=111, w=80, h=80, src=os.path.join(DOCS, 'logo_preview_480.png')),
dict(kind='label', x=181, y=200, w=120, h=40, text='S5e Pt.2',
size=29, weight=S500, color=WHITE, align='left', vtop=True),
dict(kind='label', x=222, y=237, w=49, h=28, text='1.0.0',
size=21, weight=S500, color=GRAY, align='left', vtop=True),
*item(300, 'ic_qq', '732681995'),
]
PAGES = {'home': PAGE_HOME, 'help': PAGE_HELP, 'help_ok': PAGE_HELP_OK, 'help_err': PAGE_HELP_ERR,
'confirm': PAGE_CONFIRM, 'running': PAGE_RUNNING, 'about': PAGE_ABOUT}