Skip to content

Commit 089d7f0

Browse files
committed
chat: split groupApplyHashDom into modules
1 parent 49737dd commit 089d7f0

9 files changed

Lines changed: 705 additions & 599 deletions

File tree

src/public/parts/shells/chat/public/src/groupApplyHashDom.mjs

Lines changed: 2 additions & 599 deletions
Large diffs are not rendered by default.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { addDragAndDropSupport } from '../ui/dragAndDrop.mjs'
2+
3+
/**
4+
* 在消息输入框上挂载拖放上传,文件入队由调用方处理。
5+
* @param {HTMLElement | null} input 消息输入框根节点
6+
* @param {{ enqueuePendingFile: (f: File) => void, signal: AbortSignal }} opts 入队与卸载信号
7+
* @returns {void}
8+
*/
9+
export function attachGroupInputDragDrop(input, { enqueuePendingFile, signal }) {
10+
if (!input) return
11+
addDragAndDropSupport(input, files => {
12+
for (const f of files) enqueuePendingFile(f)
13+
}, { signal })
14+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* 按当前频道类型显示或隐藏 `#group-av-panel`(流媒体频道展开)。
3+
* @param {string} channelId 当前频道 ID
4+
* @param {Record<string, object>} lastChannels 频道 ID 到 meta 的映射
5+
* @returns {void}
6+
*/
7+
export function updateGroupAvPanelVisibility(channelId, lastChannels) {
8+
const avPanel = document.getElementById('group-av-panel')
9+
if (!avPanel) return
10+
const isStream = lastChannels[channelId]?.type === 'streaming'
11+
if (isStream) {
12+
avPanel.classList.remove('hidden')
13+
avPanel.classList.add('flex')
14+
}
15+
else {
16+
avPanel.classList.add('hidden')
17+
avPanel.classList.remove('flex')
18+
}
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* 装配 `setupGroupWebSocket` / `createWsMessageHandler` 所需载荷(纯数据对象)。
3+
* @param {import('../groupApplyHashWs.mjs').ApplyGroupHashWsPayload} payload 频道状态、加载回调、打字指示等依赖
4+
* @returns {import('../groupApplyHashWs.mjs').ApplyGroupHashWsPayload} 供 `setupGroupWebSocket` 使用的载荷
5+
*/
6+
export function buildApplyGroupHashWsPayload(payload) {
7+
return payload
8+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { flattenChannelTree } from '../ui/dagMessageUtils.mjs'
2+
3+
/**
4+
* 渲染左侧频道树(含层级缩进与当前频道高亮)。
5+
* @param {HTMLElement} tree 频道树 `<ul>` 容器
6+
* @param {{ groupId: string, channelId: string, lastChannels: Record<string, object> }} opts 群组、当前频道与频道元数据映射
7+
* @returns {void}
8+
*/
9+
export function renderGroupChannelTree(tree, { groupId, channelId, lastChannels }) {
10+
tree.innerHTML = ''
11+
const flat = flattenChannelTree(lastChannels)
12+
for (const { id, meta, depth } of flat) {
13+
const li = document.createElement('li')
14+
const a = document.createElement('a')
15+
const iconSrc = meta.type === 'list'
16+
? 'https://api.iconify.design/mdi/format-list-bulleted.svg'
17+
: meta.type === 'streaming'
18+
? 'https://api.iconify.design/mdi/video-outline.svg'
19+
: 'https://api.iconify.design/line-md/chat-round-dots.svg'
20+
a.replaceChildren()
21+
const chIcon = document.createElement('img')
22+
chIcon.src = iconSrc
23+
chIcon.className = 'w-4 h-4 inline shrink-0 align-middle mr-1'
24+
chIcon.alt = ''
25+
a.appendChild(chIcon)
26+
a.appendChild(document.createTextNode(meta.name || id))
27+
a.href = `#${groupId}:${id}`
28+
a.className = channelId === id ? 'active' : ''
29+
li.style.paddingLeft = `${8 + depth * 12}px`
30+
li.appendChild(a)
31+
tree.appendChild(li)
32+
}
33+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { fetchGroupStateData } from '../groupApplyHashState.mjs'
2+
import { handleUIError } from '../utils.mjs'
3+
4+
import { updateGroupAvPanelVisibility } from './avPanelToggle.mjs'
5+
import { renderGroupChannelTree } from './channelTreeRender.mjs'
6+
import { renderGroupMemberList } from './memberListRender.mjs'
7+
8+
/**
9+
* 拉取群组状态并刷新频道树、成员列表与音视频面板显隐。
10+
* @param {{
11+
* groupId: string,
12+
* channelId: string,
13+
* tree: HTMLElement,
14+
* members: HTMLElement | null,
15+
* stateSlice: {
16+
* lastGroupSettings: object,
17+
* lastChannels: Record<string, object>,
18+
* lastChannelMeta: object | null,
19+
* },
20+
* }} args 群组标识、DOM 容器与可变的 `stateSlice` 引用
21+
* @returns {Promise<void>}
22+
*/
23+
export async function loadGroupStateDom({
24+
groupId,
25+
channelId,
26+
tree,
27+
members,
28+
stateSlice,
29+
}) {
30+
try {
31+
const data = await fetchGroupStateData(groupId)
32+
if (!data) return
33+
stateSlice.lastGroupSettings = data.groupSettings || {}
34+
tree.innerHTML = ''
35+
stateSlice.lastChannels = data.channels || {}
36+
stateSlice.lastChannelMeta = stateSlice.lastChannels[channelId] || null
37+
renderGroupChannelTree(tree, { groupId, channelId, lastChannels: stateSlice.lastChannels })
38+
const mlist = Array.isArray(data.members) ? data.members : []
39+
renderGroupMemberList(members, mlist)
40+
updateGroupAvPanelVisibility(channelId, stateSlice.lastChannels)
41+
}
42+
catch (e) {
43+
handleUIError(e, 'chat.group.loadError', 'loadState failed')
44+
}
45+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* 渲染群组成员列表(空态 i18n、在线绿点)。
3+
* @param {HTMLElement | null} members 成员列表容器;无侧栏时为 null(调用方已判空则仍可传)
4+
* @param {unknown[]} mlist 成员对象数组
5+
* @returns {void}
6+
*/
7+
export function renderGroupMemberList(members, mlist) {
8+
if (!members) return
9+
members.innerHTML = ''
10+
if (!mlist.length) {
11+
const li = document.createElement('li')
12+
li.className = 'text-xs opacity-70'
13+
li.dataset.i18n = 'chat.group.membersEmpty'
14+
members.appendChild(li)
15+
return
16+
}
17+
for (const m of mlist) {
18+
const li = document.createElement('li')
19+
li.className = 'text-xs truncate font-mono'
20+
const displayName = m.profile?.name || m.profile?.memberId || (m.pubKeyHash ? `${m.pubKeyHash.slice(0, 8)}…` : '?')
21+
li.textContent = displayName
22+
li.title = m.pubKeyHash || ''
23+
if (m.isOnline) {
24+
const dot = document.createElement('span')
25+
dot.className = 'inline-block w-2 h-2 rounded-full bg-success ml-1'
26+
li.appendChild(dot)
27+
}
28+
members.appendChild(li)
29+
}
30+
}

0 commit comments

Comments
 (0)