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:
@@ -36,7 +36,8 @@ import { FbLoginPage } from './login/FbLoginPage';
|
||||
import { FB_TOKEN_STORE } from '../data/FbTokenStore';
|
||||
import { FB_SERVER_STORE } from '../data/FbServerStore';
|
||||
import { FB_DEVICE_STORE } from '../data/FbDeviceStore';
|
||||
import { FB_SESSION, SESSION_NEED_LOGIN, SESSION_OFFLINE } from '../data/FbSession';
|
||||
import { FB_SESSION, FbMeIdentityResult, SESSION_NEED_LOGIN, SESSION_OFFLINE } from '../data/FbSession';
|
||||
import { FbAccount, FbSession } from '../model/Types';
|
||||
import { fbOnUnauthorized } from '../data/FbHttp';
|
||||
import { FbDb } from '../data/FbDb';
|
||||
import { FB_ATTACH } from '../data/FbAttachQueue';
|
||||
@@ -188,6 +189,14 @@ struct Index {
|
||||
this.app.needLogin = false;
|
||||
this.app.offlineLocked = false;
|
||||
this.entered = true;
|
||||
/* 🔴 v59:把 `/me` 带回来的**身份**写进全局状态(姓名 / 真头像 /
|
||||
家庭名 / 标语)。用户 2026-10-18 两条要求都靠它:
|
||||
· 「右上角的头像应该是真实的」 → `me.avatarUrl`
|
||||
· 抽屉左上角要显示标语 → `session.slogan`
|
||||
⚠️ 必须判 `has`:断网启动时 `check()` 仍会回 SESSION_OK(离线可用),
|
||||
但**没有**身份数据。不判就会把已有的头像/标语冲成空 —— 那是
|
||||
"一次断网,头像就没了"这种最难解释的 bug。 */
|
||||
this.applyIdentity(r.identity);
|
||||
}
|
||||
this.bootChecked = true;
|
||||
}
|
||||
@@ -360,6 +369,46 @@ struct Index {
|
||||
this.reopenLocal();
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔴 v59:把 `/me` 带回来的身份写进全局状态。
|
||||
*
|
||||
* 处理的是"**启动时校验会话**"这条路径(登录那一刻的身份由登录页自己写,
|
||||
* 见 `FbLoginPage.applySession`);两条路径都必须能更新这些字段,
|
||||
* 否则会出现"登录后标语是对的,重启一次又变回旧的"。
|
||||
*
|
||||
* ⚠️ 逐项判空后再写:`check()` 在**断网**时也会回 SESSION_OK(离线可用),
|
||||
* 但那时没有身份数据。整块替换会把头像/标语清成空
|
||||
* (症状:"坐一趟飞机回来,头像和标语都没了")。
|
||||
* ⚠️ `slogan` 只在服务端给了非空值时覆盖 —— 兜底那句话由端上的
|
||||
* `FB_DEFAULT_SLOGAN` 负责,服务端不给就保持原值。
|
||||
*/
|
||||
private applyIdentity(id: FbMeIdentityResult | undefined): void {
|
||||
if (id === undefined || !id.has) {
|
||||
return;
|
||||
}
|
||||
const old: FbSession = this.app.session;
|
||||
// 姓名 / 头像 / 角色 变了才整体换(V2 对 interface 的深层属性观察不可靠,
|
||||
// 换引用才能保证读它的页面都刷新 —— 与登录页 applySession 同一理由)
|
||||
const me: FbAccount = {
|
||||
id: old.me.id,
|
||||
name: id.name !== '' ? id.name : old.me.name,
|
||||
kinship: old.me.kinship,
|
||||
avatarColor: old.me.avatarColor,
|
||||
avatarUrl: id.avatarUrl !== '' ? id.avatarUrl : old.me.avatarUrl,
|
||||
role: old.me.role,
|
||||
isGuest: old.me.isGuest,
|
||||
canWrite: old.me.canWrite,
|
||||
};
|
||||
const next: FbSession = {
|
||||
loggedIn: true,
|
||||
familyId: old.familyId,
|
||||
familyTitle: id.familyName !== '' ? id.familyName : old.familyTitle,
|
||||
slogan: id.slogan !== '' ? id.slogan : old.slogan,
|
||||
me: me,
|
||||
};
|
||||
this.app.session = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新建立本地库 + 附件索引(登录成功后调)。
|
||||
*
|
||||
@@ -440,26 +489,20 @@ struct Index {
|
||||
// ---- 未登录 / 被要求重新登录:登录页(**不显示抽屉/悬浮栏**)----
|
||||
// 🔴 v55:`needLogin` 是设置页「退出登录 / 更换服务器」置的位 ——
|
||||
// 本应用没有路由栈,登录页只能靠这个状态位回到前台。
|
||||
//
|
||||
// 🔴🔴 v59(用户 2026-10-18):**「先不登录 / 离线使用」已彻底移除**。
|
||||
// 用户原话:「登录页面,把那些不登录、看离线数据之类的提示全部去掉。
|
||||
// 以后就不再拥有这样的功能了,把这些功能也全部删除。」
|
||||
// ⇒ 没有 `allowSkip`、没有 `onSkip`,**登录页就是唯一下车口**。
|
||||
// ⚠️ 这是产品决定,别再"顺手"加回一个跳过按钮 —— 它本来就是个
|
||||
// 安全缺口(被踢之后不该能看任何内容),v58 上了整库加密之后更要堵死。
|
||||
FbLoginPage({
|
||||
// 传 app 只为让它拿到**状态栏高度**(全屏布局下登录页也要自己让位)
|
||||
app: this.app,
|
||||
// 从第几步开始(1=连地址一起换,2=只重登,0=自动)
|
||||
startStep: this.app.loginStartStep,
|
||||
/* 🔴 v57:只有"从没登录过"才允许「先不登录」。
|
||||
被踢 / 主动退出后必须重新登录 —— 用户原话:
|
||||
「退到登录页面之后,里面所有的资源、所有的内容都是不允许看的。」
|
||||
留着那个按钮就等于留了一扇后门(v58 上了加密才真正堵死)。 */
|
||||
allowSkip: this.app.lockReason === '',
|
||||
onLoggedIn: (): void => {
|
||||
this.onLoggedIn();
|
||||
},
|
||||
onSkip: (): void => {
|
||||
// 「先不登录」:不登录也进主界面 —— 本地优先架构下,
|
||||
// 没令牌照样能看已同步的数据。把用户堵在登录页是错的。
|
||||
// ⚠️ 必须同时复位 needLogin,否则又会被判回登录页。
|
||||
this.app.needLogin = false;
|
||||
this.app.loginStartStep = 0;
|
||||
this.entered = true;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user