| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- import { previewKindOf } from '../components/preview/file-kind';
- /**
- * 文件点击后的打开方式(2026-11-06)
- *
- * ## 用户裁决
- *
- * 「文件的预览形态保持当前逻辑。需要实现的是:**点击文件卡片之后,
- * 右侧侧边栏会自动打开进行预览**。」并补充:**图片走灯箱,其余走侧边栏**。
- *
- * ## 为什么要抽成纯函数
- *
- * 原先这段分流逻辑散在 `desktop/pages/chat/chat.ts#openFile`、
- * `mobile/pages/chat/chat.ts#openFile`、`mobile/components/m-msg/m-msg.ts#openFile`
- * 三处,且**右栏列表点击完全不经过它**(`session-rail.ts` 自己 set 了预览,
- * 结果图片也被塞进右栏内联预览)—— 这就是「同一张图,从消息里点和从右栏点
- * 表现不同」的根源。收成一份,所有入口共用。
- *
- * 纯函数,便于单测;不依赖 Angular 与任何组件。
- */
- /** 打开目标 */
- export type FileOpenTarget =
- /** 图片:全屏灯箱 */
- | { kind: 'lightbox'; file: OpenableFile }
- /** 音视频:模态播放器 */
- | { kind: 'media'; file: OpenableFile }
- /** 其余(PDF / 文档 / 表格 / 文本…):右侧栏内联预览 */
- | { kind: 'rail'; file: OpenableFile };
- /** 分流所需的最小字段集(`FileCard`、`RailFile` 都能满足) */
- export interface OpenableFile {
- name: string;
- url: string;
- mimeType?: string;
- size?: number;
- }
- /**
- * 按文件类型决定打开到哪里。
- *
- * 判定复用 `previewKindOf`(扩展名优先,mimeType 兜底),
- * 与 `file-preview` 组件内部使用的口径**完全一致**,
- * 避免「分流认为是图片、预览组件却当成文本」这类错配。
- */
- export function routeOpen(f: OpenableFile): FileOpenTarget {
- const file: OpenableFile = {
- name: f.name,
- url: f.url,
- mimeType: f.mimeType ?? '',
- size: f.size,
- };
- // 没有地址:按「右栏」处理,由预览组件给出「文件还没有同步到云盘」的明确提示。
- // 不在这里吞掉 —— 用户点了要有反馈,不能点了没反应。
- if (!file.url) return { kind: 'rail', file };
- const kind = previewKindOf(file.name || file.url, file.mimeType);
- if (kind === 'image') return { kind: 'lightbox', file };
- if (kind === 'video' || kind === 'audio') return { kind: 'media', file };
- return { kind: 'rail', file };
- }
- /** 该文件是否能在右栏预览(供禁用态判断) */
- export function canPreviewInRail(f: OpenableFile): boolean {
- return routeOpen(f).kind === 'rail';
- }
|