v0.8.1 界面六条:删离线入口 / 标语统一 / 最近纪念日 / 图标真上色 / 真头像 / 日程四修
用户 2026-10-18 六条(全部已在真机逐条验证):
① 登录页「先不登录 / 离线使用」彻底删除
用户:「把那些不登录、看离线数据之类的提示全部去掉。以后就不再拥有这样的
功能了,把这些功能也全部删除。」
⇒ 两个按钮 + onSkip + allowSkip 参数 + Index 里的 skip 分支一起删净。
这是产品决定(不是隐藏):该路径本身就是安全缺口,v58 上了整库加密后更要堵死。
② 标语统一为「一家人用岁月写成的一本书」
用户:「这也是我们"家书"这个名字的由来。所以你不要再乱换这个标语了,
只要是想出现标语或者副标题的地方,就用这样一句话。」
· 端上 FB_DEFAULT_SLOGAN 是唯一定义处(登录页副标题 + 抽屉回落都用它);
· 抽屉左上角原来是家庭名,现在显示**标语**;
· 三层优先级(个人 slogan → 家庭 motto → 应用默认口号)**在服务端算**
(Family::slogan,与网页端首页 heroSlogan 同一套),/login 与 /me 都返回。
用户还说:「如果这个用户自己有标语……这个地方就是用户自己自定义的标语。」
真机实测:登录者杨永全自己写了「修身,齐家」⇒ 抽屉就显示他那句。
③ 首页新增「最近纪念日」(放在近期任务之后、往年的今天之前)
用户:「未来最近的三个纪念日,包括每个人的生日,以及手动填写的各个纪念日。
以倒计时形式展示:距离哪个纪念日还有多少天,距离谁谁谁的生日还有多少天。」
· /home.recent_days = Anniversary::upcoming(fam,pid,370) 取前 3 ——
取满一年:窗口太小会让"刚过完生日"的家庭一个都取不到,模块直接空着;
· 数据源 all() = 派生生日 + 自建纪念日,正好覆盖用户说的两样;
· 倒计时:0 天显示「就是今天」(写「还有 0 天」读起来像已经过了)。
④ 悬浮栏图标也上色(用户:「除了下面的汉字,上面图标的颜色也变成跟汉字一样的颜色」)
🔴🔴 真根因两层,都是"无报错失效":
· 第一层:Image.fillColor() **只对 SVG 生效**,而本工程 30+ 图标**全是 PNG**
⇒ 全工程 24 处图标染色一直是空操作(文字走 fontColor 所以只有文字变了)。
· 第二层(真机才现形):改用 colorFilter 后,矩阵写成了"系数乘 RGB"
(R' = R_原 × 系数) —— 对白色图标成立,但本工程图标是**纯黑**,
黑 × 任何系数 = 仍是黑 ⇒ 真机上图标像素依旧是 (0,0,0)。
⇒ 最终形态:`fbTint` 用 **alpha 当载体**(R' = (r/255) × A_原):
系数是归一化约定(官方灰度示例系数和为 1,量纲确定);
形状完全由原图 alpha 决定 ⇒ 黑/白图标都成立,描边抗锯齿自然过渡。
真机像素实测:日程项图标与文字同为 (176,120,64)≈#B0763A;
未选中项图标 (44,39,35) 深灰(不再是纯黑)。
⚠️ 全工程 24 处 fillColor 一并改掉;FbIconButton.tint 类型改成 string,
让"误传 Resource"变成编译错误而不是又一个静默失效。
⑤ 顶栏:真实头像 + 拉开按钮间距
用户:「右上角的头像应该是真实的……现在提醒的按钮距离头像的按钮太近了。」
· /home 给 me_avatar、/login 给 avatar_url(avatar_url() 按线上存储驱动拼好);
· 三颗按钮(同步 / 铃铛 / 头像)统一用 FbMetric.gapTopActions = 8。
⑥ 日程四处
· 「日期下面有几个点」⇒ 月视图与周视图的圆点全部删除,
连 FbDot / dots() / count / dotColor 一起清(不留死代码);
· 「农历全部都是初一」⇒ 真根因是端上 lunarOf() **硬编码 return '初一'**,
而服务端 lunarRange() 本来就每天给真实农历(title)⇒ 改取 title;
· 「列表这个视图,今天的数据缺一条」⇒ 服务端 /calendar 的 from/to **默认只给本月**,
而列表视图要显示 -7 ~ +60 天 ⇒ 端上显式传范围
(loadModule 新增 pathOverride 参数);
· 「点击了某一天之后并不明显,应该把这一天的颜色变深,而今天用一个较浅的颜色」
⇒ 照 SyncCalendar:选中 = 深色实底白字、今天 = 浅色底。
真机实测:17 号(选中)bg=#FFB0763A,18 号(今天)bg=#FFF5F0EA。
另:FbKeyStore 补上一个真机抓到的 HUKS 坑 —— isKeyItemExist 在密钥不存在时
**会抛 12000011**(不是返回 false),首次运行必被误判成"本机不支持 HUKS"
⇒ 永久明文降级。改成把"不存在"当正常分支,且降级态每次启动重试一次
(把同一把 DEK 重新用 KEK 包起来,不换密钥以免重下全部附件)。
验证:hvigor BUILD SUCCESSFUL;_fb_arkts_guard.js 328/0;
_fb_v59ui_falsify.py 19 项注入 23/0;_fb_home_api.py 60/0;
六条已在真机逐条取像素/布局树确认。
This commit is contained in:
@@ -75,10 +75,103 @@ export class FbMetric {
|
||||
/** 顶栏高度 —— 用户要求「图标和标题尽量靠上」,所以压到 48vp(常规是 56)。
|
||||
* 顶栏下面的内容因此整体上移,首屏能多看到一行。 */
|
||||
static readonly topBarH: number = 48;
|
||||
/**
|
||||
* 顶栏右侧「同步图标 / 铃铛 / 头像」三颗之间的间距(vp)。
|
||||
*
|
||||
* 🔴 v59(用户 2026-10-18):「现在提醒的按钮距离头像的按钮太近了。」
|
||||
* ⇒ 统一在这里给一个值,三个按钮**两两之间**都用它。
|
||||
* ⚠️ 不要只在铃铛上单独加一个 margin:三颗的间距不统一时,
|
||||
* 视觉上会变成"两个挤在一起、一个孤零零"(本次要修的正是这个观感)。
|
||||
*/
|
||||
static readonly gapTopActions: number = 8;
|
||||
/** 抽屉宽度 */
|
||||
static readonly drawerW: number = 264;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把一张**单色 PNG 图标**染成指定颜色(返回喂给 `Image.colorFilter()` 的矩阵)。
|
||||
*
|
||||
* 🔴🔴 为什么必须有这个函数(2026-10-18 真机实测,用户报的"图标不变色"真根因):
|
||||
* `Image.fillColor()` **只对 SVG 生效** —— 本机 SDK 的 `image.d.ts` 原话:
|
||||
* > This attribute applies only to SVG images. To set the fill color for a
|
||||
* > PNG image, use `colorFilter`.
|
||||
* 而本工程 30 多个图标(`fb_ic_*.png`)**全是 PNG**(`ls resources/base/media`
|
||||
* 里一个 .svg 都没有)⇒ 所有 `fillColor(...)` 调用**一直是空操作**。
|
||||
*
|
||||
* 这解释了用户看到的两处不一致(同一个 bug 的两种表现):
|
||||
* · 悬浮快捷栏:「只有下面的汉字颜色变了,上面的图标颜色没有变」
|
||||
* (文字走 `fontColor` —— 那个是真的生效;图标走 `fillColor` —— 无效);
|
||||
* · 抽屉侧栏里"未选中图标应有模块色"也一直没生效(同样是 PNG + fillColor)。
|
||||
* ⚠️ 所以**不要把这里的图换成 SVG 就当修好了**:图标是设计给的位图,
|
||||
* 换格式会连带影响所有引用点;用颜色矩阵染色是**改动最小**且**通用**的做法。
|
||||
*
|
||||
* 做法(4×5 颜色矩阵,[r,g,b,a] 各行):把整张图的 RGB 一律压成目标色,
|
||||
* 保留原图的**alpha**(描边抗锯齿的柔和边缘不能丢)——
|
||||
* 等价于"用目标色给这张单色图的形状填色"。
|
||||
*
|
||||
* @param color `#RRGGBB` 或 `#AARRGGBB`;解析失败回落品牌红
|
||||
*/
|
||||
export function fbTint(color: string): ColorFilter {
|
||||
let s: string = color.startsWith('#') ? color.substring(1) : color;
|
||||
// 8 位(#AARRGGBB)时丢掉 alpha 段:染色**不**改透明度,透明度永远来自原图
|
||||
if (s.length === 8) {
|
||||
s = s.substring(2);
|
||||
}
|
||||
if (s.length !== 6) {
|
||||
s = 'A84A28';
|
||||
}
|
||||
const r: number = parseInt(s.substring(0, 2), 16) / 255;
|
||||
const g: number = parseInt(s.substring(2, 4), 16) / 255;
|
||||
const b: number = parseInt(s.substring(4, 6), 16) / 255;
|
||||
|
||||
/* 🔴🔴 这里踩过两次(真机实测逐次定位),最终形态是**用 alpha 当载体**:
|
||||
*
|
||||
* ❌ 第一版(系数乘 RGB):`R' = R_原 × r`
|
||||
* 对**白色**图标成立;但本工程图标是**纯黑** (0,0,0)
|
||||
* ⇒ 黑 × 任何系数 = 黑 ⇒ 真机上图标一点没变(实测像素仍是 (0,0,0))。
|
||||
* ❌ 第二版(第 5 列加性偏移 `…, r*255`):本想让输出恒等于目标色,
|
||||
* 但**第 5 列的量纲在文档里没有明确**(0..1 还是 0..255)——
|
||||
* 猜错就又是"看着对、真机不生效",同一个坑踩第三次不值。
|
||||
*
|
||||
* ✅ 本版:`R' = (r/255) × A_原`,**只用第 4 列(alpha),一个偏移都不用**。
|
||||
* · 系数是**归一化**约定(官方灰度示例 `0.2126/0.7152/0.0722` 三者和为 1
|
||||
* 即证明输入输出都在 0..1)⇒ 这一列的量纲是确定的;
|
||||
* · 形状完全由**原图 alpha** 决定 ⇒ 黑图标、白图标都成立,
|
||||
* 且描边抗锯齿(半透明像素)自然过渡,不会变成硬边;
|
||||
* · `A' = 1 × A_原` ⇒ 透明度保持不变(不会把图案外的空白也填上色)。
|
||||
*/
|
||||
return new ColorFilter([
|
||||
0, 0, 0, r, 0,
|
||||
0, 0, 0, g, 0,
|
||||
0, 0, 0, b, 0,
|
||||
0, 0, 0, 1, 0
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 图标染色的 hex 色板 —— 与 `resources/base/element/color.json` **同值**。
|
||||
*
|
||||
* 🔴 为什么需要这一份(不能直接用 `FbColors.*`):
|
||||
* `Image.colorFilter()` **只吃数字矩阵**(`ColorFilter`),拿不到 `$r(...)`
|
||||
* 资源的解析值;而 `$r` 的 `Resource` 在运行期也**取不到**它的名字/值。
|
||||
* ⇒ 需要染色的地方必须拿 hex。这里把这几个常用的抄成常量。
|
||||
*
|
||||
* ⚠️ **改了 color.json 就要同步改这里**(两处必须一致)。为把风险压到最小,
|
||||
* 这里只保留"图标要染色"用到的那几个;其余一律传 hex(模块色本来就是 hex)。
|
||||
*/
|
||||
export class FbTint {
|
||||
/** 与 color.json 的 `ink` 同值(主文字墨色) */
|
||||
static readonly ink: string = '#2C231D';
|
||||
/** 与 color.json 的 `muted` 同值(次级文字) */
|
||||
static readonly muted: string = '#7E6B5A';
|
||||
/** 与 color.json 的 `faint` 同值(最弱文字) */
|
||||
static readonly faint: string = '#A8988A';
|
||||
/** 与 color.json 的 `brand` 同值(砖红) */
|
||||
static readonly brand: string = '#A84A28';
|
||||
/** 白(图标压在实底上时用) */
|
||||
static readonly white: string = '#FFFFFF';
|
||||
}
|
||||
|
||||
/**
|
||||
* 模块主题色 → 客户端可用的三档调色板。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user