feat(app-iced): M114 账户页三轨登录(微软正版 / 第三方皮肤站 / 本地档案)

- 账户页:当前账户卡 + 全部账户列表 + 空态三入口 + 皮肤区;五项动作(添加/切换/删除/重新登录/校验)
- 三轨添加流程:设备码(用户码+链接+倒计时+过期重试+取消)、授权码(浏览器+可复制链接+取消)、
  本地档案(名字校验)、第三方站(服务地址 + 服务发现校验 + 密码登录,密码掩码且用完即弃)
- 导航:账户为一等页,入口是轨底头像位(未登录=描边剪影 / 已登录=首字母块+名字;窄高收成图标条)
- 凭据红线:DTO 侧形状脱敏 + 状态层二次脱敏 + 密码掩码;Inject-JWT 测试断言视图模型干净(已做变异取证)
- presenter:authlib 登录/服务发现/皮肤抓取(复用下载引擎的 HTTP 客户端,无新增依赖)、
  皮肤原图经 DTO 到 UI 裁剪成头像(既有 image 依赖,未改 Cargo.toml)
- i18n:新增 account 域 51 条中英文案(离线档案口径全量写入),金表同步
This commit is contained in:
AskaEth committed 2026-11-05 05:08:35 +08:00
1 parent e7b04c4afe
commit 1ff00bbe50
43 files changed
+4343 -117

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
//! 导航轨底部**账户头像位**的状态换算(M114)。
//!
//! 为什么单独一个文件:`app/view.rs` 贴着 400 行硬线,而这块逻辑与页面树无关——
//! 它只回答「轨底那个头像位现在该显示成未登录,还是某个账户」。
use crate::shell;
use super::super::state::App;
/// 导航轨收成「图标条」的窗口高度(M114)。
///
/// 判据不是「项数」而是**真实可用高度**:四项 + 底部头像位在 48 标题栏之上还要放得下
/// 4 × 52 + 4 × 4 + 52 ≈ 300;留出一屏正文的最小高度(424 行宽 + 页头 + 边距),
/// 低于 720 就把标签收掉,只留图标与头像位(头像位**永远可见**,任务要求)。
const RAIL_COMPACT_HEIGHT: f32 = 720.0;
impl App {
/// 导航轨底部头像位的状态(M114):未登录 / 已登录两态要一眼能分。
pub(super) fn rail_account(&self) -> shell::RailAccount {
let compact = self.height < RAIL_COMPACT_HEIGHT;
match self.state.active_account() {
Some(account) => {
shell::RailAccount::signed_in(account.monogram(), account.name.clone())
.compact(compact)
}
// M106:未登录标签跟着**生效语言**走(早期钉死 `Lang::En` 的写法已删)。
None => shell::RailAccount::signed_out(
self.lang()
.catalog()
.text(unlucky_i18n::Key::AccountRailSignedOut),
)
.compact(compact),
}
}
}