迁移在线名单点击事件
This commit is contained in:
@@ -1,9 +1,75 @@
|
||||
// 聊天室右侧名单/房间面板事件绑定,逐步替代 Blade 内联事件。
|
||||
|
||||
let rightPanelEventsBound = false;
|
||||
// 用户名单由 Blade 主脚本动态重建,点击/双击状态必须放在模块层避免 DOM 重建后残留闭包。
|
||||
const userListClickTimers = new WeakMap();
|
||||
const userListLastTapTimes = new WeakMap();
|
||||
const USER_LIST_CLICK_DELAY = 250;
|
||||
const USER_LIST_DOUBLE_TAP_DELAY = 300;
|
||||
|
||||
/**
|
||||
* 绑定右侧在线面板的 tab、刷新、排序和搜索事件。
|
||||
* 选择聊天目标并聚焦输入框。
|
||||
*
|
||||
* @param {string} username 目标用户名
|
||||
* @returns {void}
|
||||
*/
|
||||
function selectChatTarget(username) {
|
||||
const toUserSelect = document.getElementById("to_user");
|
||||
if (toUserSelect instanceof HTMLSelectElement) {
|
||||
toUserSelect.value = username;
|
||||
}
|
||||
|
||||
// 手机抽屉里的名单点击后需要收起抽屉,桌面端没有该函数时自然跳过。
|
||||
window.closeMobileDrawer?.();
|
||||
document.getElementById("content")?.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开用户资料卡并取消待执行的单击选择。
|
||||
*
|
||||
* @param {HTMLElement} item 用户列表项
|
||||
* @returns {void}
|
||||
*/
|
||||
function openUserCardFromList(item) {
|
||||
const username = item.dataset.username || "";
|
||||
const clickTimer = userListClickTimers.get(item);
|
||||
|
||||
if (!username) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickTimer) {
|
||||
window.clearTimeout(clickTimer);
|
||||
userListClickTimers.delete(item);
|
||||
}
|
||||
|
||||
window.closeMobileDrawer?.();
|
||||
window.openUserCard?.(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调度用户列表单击选择,延迟执行用于和双击打开名片互斥。
|
||||
*
|
||||
* @param {HTMLElement} item 用户列表项
|
||||
* @returns {void}
|
||||
*/
|
||||
function scheduleUserListSelection(item) {
|
||||
const username = item.dataset.username || "";
|
||||
|
||||
if (!username || userListClickTimers.has(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clickTimer = window.setTimeout(() => {
|
||||
userListClickTimers.delete(item);
|
||||
selectChatTarget(username);
|
||||
}, USER_LIST_CLICK_DELAY);
|
||||
|
||||
userListClickTimers.set(item, clickTimer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定右侧在线面板的 tab、刷新、排序、搜索与用户列表选择事件。
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
@@ -31,9 +97,58 @@ export function bindChatRightPanelControls() {
|
||||
if (refreshButton) {
|
||||
event.preventDefault();
|
||||
window.renderUserList?.();
|
||||
return;
|
||||
}
|
||||
|
||||
const everyoneItem = event.target.closest("[data-user-list-everyone]");
|
||||
if (everyoneItem) {
|
||||
event.preventDefault();
|
||||
selectChatTarget("大家");
|
||||
return;
|
||||
}
|
||||
|
||||
const userItem = event.target.closest("[data-user-list-entry]");
|
||||
if (userItem instanceof HTMLElement) {
|
||||
event.preventDefault();
|
||||
scheduleUserListSelection(userItem);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("dblclick", (event) => {
|
||||
if (!(event.target instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userItem = event.target.closest("[data-user-list-entry]");
|
||||
if (userItem instanceof HTMLElement) {
|
||||
event.preventDefault();
|
||||
openUserCardFromList(userItem);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("touchend", (event) => {
|
||||
if (!(event.target instanceof Element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userItem = event.target.closest("[data-user-list-entry]");
|
||||
if (!(userItem instanceof HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 移动端双触发沿用旧的 300ms 口径,单触摸仍交给 click 事件选择聊天目标。
|
||||
const now = Date.now();
|
||||
const lastTapTime = userListLastTapTimes.get(userItem) || 0;
|
||||
if (now - lastTapTime < USER_LIST_DOUBLE_TAP_DELAY) {
|
||||
event.preventDefault();
|
||||
userListLastTapTimes.delete(userItem);
|
||||
openUserCardFromList(userItem);
|
||||
return;
|
||||
}
|
||||
|
||||
userListLastTapTimes.set(userItem, now);
|
||||
}, { passive: false });
|
||||
|
||||
document.addEventListener("change", (event) => {
|
||||
if (!(event.target instanceof HTMLSelectElement) || event.target.id !== "user-sort-select") {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user