docs: plan web branding and message sound
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# Web Brand And Message Sound Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 将生产 Web 品牌统一为“迅工捷使”,精简登录页,并为符合提醒条件的新消息播放用户提供的提示音。
|
||||
|
||||
**Architecture:** 继续以 `web/src/lib/config.ts` 作为显示品牌名来源,认证页和系统消息只消费该常量;品牌图标和 MP3 作为 Vite `public/` 静态资源。消息声音接入现有 `push.ts` 新消息扫描链路,在浏览器通知权限判断之前复用“本人消息、当前可见会话、会话免打扰”的过滤结果。
|
||||
|
||||
**Tech Stack:** React 19、TypeScript、Vite、Node test runner、Jiti。
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 写品牌和提示音红测
|
||||
|
||||
**Files:**
|
||||
- Create: `web/tests/brand-and-notification-sound.test.mjs`
|
||||
|
||||
- [ ] **Step 1: 写失败测试**
|
||||
|
||||
创建 Node 测试,核心断言如下;可按实际导出补齐 fake `Audio` 的类型字段,但不得降低断言:
|
||||
|
||||
```js
|
||||
const webRoot = new URL('../', import.meta.url);
|
||||
assert.match(await readFile(new URL('index.html', webRoot), 'utf8'), /<title>迅工捷使<\/title>/);
|
||||
assert.doesNotMatch(await readFile(new URL('src/features/auth/LoginPage.tsx', webRoot), 'utf8'), /桌面端|下载桌面客户端|iOS \/ Android|帮助中心/);
|
||||
assert.doesNotMatch(await readFile(new URL('src/features/auth/TenantEntryPage.tsx', webRoot), 'utf8'), /MeetingIM/);
|
||||
assert.doesNotMatch(await readFile(new URL('src/features/system/SystemMessagesView.tsx', webRoot), 'utf8'), /MeetingIM 安全团队/);
|
||||
assert.equal(audioSource, '/message-notification.mp3');
|
||||
assert.equal(playCount, 1);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 运行测试确认失败**
|
||||
|
||||
Run: `node --experimental-strip-types --test tests/brand-and-notification-sound.test.mjs`
|
||||
|
||||
Expected: FAIL,因为品牌仍是 `MeetingIM`,提示音模块和静态资源尚不存在。
|
||||
|
||||
### Task 2: 更新品牌和登录页
|
||||
|
||||
**Files:**
|
||||
- Modify: `web/index.html`
|
||||
- Modify: `web/src/lib/config.ts`
|
||||
- Modify: `web/src/features/auth/LoginPage.tsx`
|
||||
- Modify: `web/src/features/auth/TenantEntryPage.tsx`
|
||||
- Modify: `web/src/features/system/SystemMessagesView.tsx`
|
||||
- Create: `web/public/app-icon.png`
|
||||
- Delete: `web/public/favicon.svg`
|
||||
- Modify: `web/src/lib/notifications/tabIndicator.ts`
|
||||
- Modify: `web/src/lib/notifications/push.ts`
|
||||
|
||||
- [ ] **Step 1: 复制官方品牌图标**
|
||||
|
||||
将 `../im-ios-website/dist/assets/app-icon.png` 原样复制为 `web/public/app-icon.png`,所有 Web 图标引用统一指向它。
|
||||
|
||||
- [ ] **Step 2: 最小化更新可见品牌**
|
||||
|
||||
把浏览器标题、认证页和系统消息署名改为“迅工捷使”;`APP_NAME` 保留 `MeetingIM/<version>` 作为现有 Tinode 客户端技术标识,避免把显示品牌替换扩大成协议改名。
|
||||
|
||||
```ts
|
||||
export const BASE_APP_NAME = '迅工捷使';
|
||||
export const APP_NAME = `MeetingIM/${__APP_VERSION__}`;
|
||||
```
|
||||
|
||||
认证页统一使用:
|
||||
|
||||
```tsx
|
||||
<img src="/app-icon.png" alt="" className="h-full w-full rounded-[inherit]" />
|
||||
<strong>{BASE_APP_NAME}</strong>
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 精简登录页**
|
||||
|
||||
说明文案改为“单聊、群聊、通讯录、文件与收藏、音视频通话,消息与回执在手机端保持一致。”,删除底部三个入口。
|
||||
|
||||
```tsx
|
||||
<p className="mt-4 max-w-md text-base text-white/80">
|
||||
单聊、群聊、通讯录、文件与收藏、音视频通话,消息与回执在手机端保持一致。
|
||||
</p>
|
||||
```
|
||||
|
||||
### Task 3: 接入消息提示音
|
||||
|
||||
**Files:**
|
||||
- Create: `web/src/lib/notifications/sound.ts`
|
||||
- Modify: `web/src/lib/notifications/push.ts`
|
||||
- Create: `web/public/message-notification.mp3`
|
||||
|
||||
- [ ] **Step 1: 复制用户提供的提示音**
|
||||
|
||||
将 `/Users/aa/Downloads/universfield-new-notification-012-363675.mp3` 原样复制为 `web/public/message-notification.mp3`。
|
||||
|
||||
- [ ] **Step 2: 实现安全播放器**
|
||||
|
||||
首次需要时创建 `Audio('/message-notification.mp3')`,每次播放前设置 `currentTime = 0`;对同步异常和 `play()` Promise 拒绝均静默处理。
|
||||
|
||||
```ts
|
||||
let messageAudio: HTMLAudioElement | null = null;
|
||||
|
||||
export function playMessageSound(): void {
|
||||
try {
|
||||
messageAudio ||= new Audio('/message-notification.mp3');
|
||||
messageAudio.currentTime = 0;
|
||||
void messageAudio.play().catch(() => {});
|
||||
} catch {
|
||||
// Optional audio must never interrupt message delivery.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 接入新消息过滤链路**
|
||||
|
||||
把“本人消息、当前可见会话、会话免打扰”抽成通知与声音共享的判断。通过判断后先播放声音;仅当 Notification API 可用且权限为 `granted` 时再显示系统通知。
|
||||
|
||||
```ts
|
||||
if (!shouldAlert(topicName, latest)) return;
|
||||
playMessageSound();
|
||||
if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
|
||||
fireNotification(topicName, latest);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 跑绿测**
|
||||
|
||||
Run: `node --experimental-strip-types --test tests/*.test.ts tests/*.test.mjs`
|
||||
|
||||
Expected: 现有 6 项和新增测试全部 PASS。
|
||||
|
||||
### Task 4: 验证、提交与部署
|
||||
|
||||
**Files:**
|
||||
- Verify only
|
||||
|
||||
- [ ] **Step 1: 静态验证**
|
||||
|
||||
Run: `npm run build && npm run lint`
|
||||
|
||||
Expected: 构建退出码 0;lint 无 error,允许记录既有 warning。
|
||||
|
||||
- [ ] **Step 2: 完整性验证**
|
||||
|
||||
Run: `git diff --check`
|
||||
|
||||
Expected: 无输出,退出码 0;MP3 和应用图标的 SHA-256 与来源文件一致。
|
||||
|
||||
- [ ] **Step 3: 提交并推送**
|
||||
|
||||
提交精确修改文件到 `dev`,推送前先 fetch 并确认无远端分叉。
|
||||
|
||||
- [ ] **Step 4: 部署和公网回归**
|
||||
|
||||
触发 Gitea `deploy.yml`,等待成功,确认 K3s Deployment 2/2;访问 `https://web.118im.com` 验证标题、品牌、登录页删减及双账号新消息提醒路径。
|
||||
@@ -0,0 +1,34 @@
|
||||
# Web 品牌与消息提示音设计
|
||||
|
||||
## 目标
|
||||
|
||||
将当前生产 Web 的用户可见品牌统一为“迅工捷使”,精简登录页指定文案,并使用用户提供的 MP3 为新收到的消息播放提示音。
|
||||
|
||||
## 范围
|
||||
|
||||
- 当前 Dockerfile 实际构建的 `web/` 目录。
|
||||
- 浏览器标题、企业码页、登录页、系统消息署名和应用图标。
|
||||
- 登录页说明改为“消息与回执在手机端保持一致”,删除底部三个入口。
|
||||
- 复用 Android/iOS 已有蓝底扳手图标。
|
||||
- 新消息提示音使用用户提供的 `universfield-new-notification-012-363675.mp3`。
|
||||
|
||||
## 行为
|
||||
|
||||
- 只为他人发来的新消息播放一次提示音。
|
||||
- 正在可见地查看对应会话时不播放。
|
||||
- 会话设置为消息免打扰时不播放。
|
||||
- 声音播放失败不得影响消息接收、列表更新或浏览器通知。
|
||||
- 浏览器系统通知权限不控制声音;声音与现有通知共用同一条新消息判定链路。
|
||||
|
||||
## 明确不改
|
||||
|
||||
- 后端代码和后端默认推送、短信名称。
|
||||
- `X-MeetingIM-APIKey`、`X-MeetingIM-Auth` 等协议头。
|
||||
- `meetingim-session` 等已有存储键。
|
||||
- 仓库名、镜像名、域名和旧版未部署 Web 入口。
|
||||
|
||||
## 验证
|
||||
|
||||
- 自动测试覆盖品牌文字、登录页删减、品牌图片引用和提示音播放器。
|
||||
- Web 全量测试、构建、lint 和 `git diff --check`。
|
||||
- 部署后实测企业码页、登录页、浏览器标题、图标,以及双账号新消息提示音路径。
|
||||
Reference in New Issue
Block a user