jim800121chen 6a797d5eb5 feat(frontend): 設備管理三態/註冊 + 模型共享庫/公開設定(B + C)
B 設備管理:device-store 補 registeredAt + register/unregister actions;
deriveTriState 三態(已連接/未連接/已連接未註冊);三態 badge(warning token
+ icon + 文字不只色);排序/filter chips;註冊 UI(明確區分取消註冊≠移除)。

C 模型共享:/models/library cursor 無限捲動 + 搜尋/filter/排序;visibility badge
三態;公開設定 Dialog(RadioGroup + shares 管理 + public 警告 + 二次確認);
profile 頁 owner/公開雙態;radio-group 新元件;owner 用 name 不洩 email。

共用檔 types/api.ts(B error codes)+ i18n en/zh(devices.* B / models.* C)。
零新 Design Token。reviewer B(0C/0M) + C(0C/0M、設計12/12 API8/8) 通過。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 16:30:22 +08:00

39 lines
1.6 KiB
TypeScript
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.

/**
* 相對時間格式化(共用 util
*
* 從 `components/cloud/remote-device-badge.tsx` 的 `formatRelativeTime` 抽出共用,
* 讓「模型共享」的 owner 資訊列 / 共享時間沿用同一份規格與 i18n key避免重複實作。
*
* 規格components.md §10.3
* - < 60 秒 → 「剛剛」remote.lastSeen.justNow
* - < 60 分 → 「X 分鐘前」remote.lastSeen.minutesAgo
* - < 24 時 → 「X 小時前」remote.lastSeen.hoursAgo
* - ≥ 24 時 → 絕對時間「MM/DD HH:mm」
*/
/**
* @param isoString ISO 8601 時間字串(無法解析時回空字串)
* @param nowMs 當前時間ms— 由 caller 傳入以便測試 deterministic
* @param t i18n 翻譯函式(需含 remote.lastSeen.* key
*/
export function formatRelativeTime(
isoString: string,
nowMs: number,
t: (k: string) => string,
): string {
const ts = Date.parse(isoString);
if (Number.isNaN(ts)) return "";
const diffSec = Math.max(0, Math.floor((nowMs - ts) / 1000));
if (diffSec < 60) return t("remote.lastSeen.justNow");
const diffMin = Math.floor(diffSec / 60);
if (diffMin < 60) return t("remote.lastSeen.minutesAgo").replace("{n}", String(diffMin));
const diffHour = Math.floor(diffMin / 60);
if (diffHour < 24) return t("remote.lastSeen.hoursAgo").replace("{n}", String(diffHour));
const d = new Date(ts);
const mm = String(d.getMonth() + 1).padStart(2, "0");
const dd = String(d.getDate()).padStart(2, "0");
const hh = String(d.getHours()).padStart(2, "0");
const mi = String(d.getMinutes()).padStart(2, "0");
return `${mm}/${dd} ${hh}:${mi}`;
}