189 lines
5.5 KiB
JavaScript
189 lines
5.5 KiB
JavaScript
|
|
// 聊天室好友与通用大卡片广播通知监听,集中管理 Echo 订阅和弹窗渲染。
|
|||
|
|
|
|||
|
|
import { escapeHtml } from "./html.js";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 读取页面 CSRF Token。
|
|||
|
|
*
|
|||
|
|
* @returns {string}
|
|||
|
|
*/
|
|||
|
|
function getCsrfToken() {
|
|||
|
|
return document.querySelector('meta[name="csrf-token"]')?.content ?? "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 等待 Echo 与聊天上下文就绪后再订阅频道。
|
|||
|
|
*
|
|||
|
|
* @param {Function} callback
|
|||
|
|
* @returns {void}
|
|||
|
|
*/
|
|||
|
|
function whenEchoReady(callback) {
|
|||
|
|
if (!window.Echo || !window.chatContext) {
|
|||
|
|
window.setTimeout(() => whenEchoReady(callback), 500);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
callback();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 同步移除对方好友关系。
|
|||
|
|
*
|
|||
|
|
* @param {string} username
|
|||
|
|
* @returns {Promise<void>}
|
|||
|
|
*/
|
|||
|
|
async function removeFriendBack(username) {
|
|||
|
|
await fetch(`/friend/${encodeURIComponent(username)}/remove`, {
|
|||
|
|
method: "DELETE",
|
|||
|
|
headers: {
|
|||
|
|
"Content-Type": "application/json",
|
|||
|
|
"X-CSRF-TOKEN": getCsrfToken(),
|
|||
|
|
"Accept": "application/json",
|
|||
|
|
},
|
|||
|
|
body: JSON.stringify({
|
|||
|
|
room_id: window.chatContext?.roomId,
|
|||
|
|
}),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 显示好友添加居中大卡弹窗。
|
|||
|
|
*
|
|||
|
|
* @param {string} fromUsername
|
|||
|
|
* @param {boolean} hasAddedBack
|
|||
|
|
* @returns {void}
|
|||
|
|
*/
|
|||
|
|
export function showFriendBanner(fromUsername, hasAddedBack) {
|
|||
|
|
if (!window.chatBanner) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (hasAddedBack) {
|
|||
|
|
window.chatBanner.show({
|
|||
|
|
id: "friend-banner",
|
|||
|
|
icon: "🎉💚🎉",
|
|||
|
|
title: "好友通知",
|
|||
|
|
name: fromUsername,
|
|||
|
|
body: "将你加为好友了!",
|
|||
|
|
sub: "你们现在互为好友 🎊",
|
|||
|
|
gradient: ["#065f46", "#059669", "#10b981"],
|
|||
|
|
titleColor: "#a7f3d0",
|
|||
|
|
autoClose: 5000,
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.chatBanner.show({
|
|||
|
|
id: "friend-banner",
|
|||
|
|
icon: "💚📩",
|
|||
|
|
title: "好友申请",
|
|||
|
|
name: fromUsername,
|
|||
|
|
body: "将你加为好友了!",
|
|||
|
|
sub: "但你还没有回加对方为好友",
|
|||
|
|
gradient: ["#1e3a5f", "#1d4ed8", "#0891b2"],
|
|||
|
|
titleColor: "#bae6fd",
|
|||
|
|
autoClose: 0,
|
|||
|
|
buttons: [
|
|||
|
|
{
|
|||
|
|
label: "➕ 回加好友",
|
|||
|
|
color: "#10b981",
|
|||
|
|
onClick: async (button, close) => {
|
|||
|
|
await window.quickFriendAction?.("add", fromUsername, button);
|
|||
|
|
if (button.textContent.startsWith("✅")) {
|
|||
|
|
window.setTimeout(close, 1500);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
label: "稍后再说",
|
|||
|
|
color: "rgba(255,255,255,0.15)",
|
|||
|
|
onClick: (button, close) => close(),
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 订阅好友私有频道通知。
|
|||
|
|
*
|
|||
|
|
* @returns {void}
|
|||
|
|
*/
|
|||
|
|
export function setupFriendNotification() {
|
|||
|
|
whenEchoReady(() => {
|
|||
|
|
const myId = window.chatContext.userId;
|
|||
|
|
|
|||
|
|
window.Echo.private(`user.${myId}`)
|
|||
|
|
.listen(".FriendAdded", (event) => {
|
|||
|
|
showFriendBanner(event.from_username, event.has_added_back);
|
|||
|
|
})
|
|||
|
|
.listen(".FriendRemoved", (event) => {
|
|||
|
|
const fromUsername = String(event.from_username ?? "");
|
|||
|
|
const safeUsername = escapeHtml(fromUsername);
|
|||
|
|
|
|||
|
|
if (event.had_added_back) {
|
|||
|
|
window.chatToast?.show?.({
|
|||
|
|
title: "好友通知",
|
|||
|
|
message: `<b>${safeUsername}</b> 已将你从好友列表移除。<br><span style="color:#6b7280; font-size:12px;">你的好友列表中仍保留对方,可点击同步移除。</span>`,
|
|||
|
|
icon: "👥",
|
|||
|
|
color: "#6b7280",
|
|||
|
|
duration: 10000,
|
|||
|
|
action: {
|
|||
|
|
label: `🗑️ 同步移除 ${fromUsername}`,
|
|||
|
|
onClick: async () => removeFriendBack(fromUsername),
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.chatToast?.show?.({
|
|||
|
|
title: "好友通知",
|
|||
|
|
message: `<b>${safeUsername}</b> 已将你从他的好友列表移除。`,
|
|||
|
|
icon: "👥",
|
|||
|
|
color: "#9ca3af",
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 订阅通用大卡片通知广播。
|
|||
|
|
*
|
|||
|
|
* @returns {void}
|
|||
|
|
*/
|
|||
|
|
export function setupBannerNotification() {
|
|||
|
|
whenEchoReady(() => {
|
|||
|
|
const myId = window.chatContext.userId;
|
|||
|
|
const roomId = window.chatContext.roomId;
|
|||
|
|
const showBanner = (event) => {
|
|||
|
|
if (event.options && typeof event.options === "object") {
|
|||
|
|
window.chatBanner?.show?.(event.options);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 私有频道只推送给指定用户,房间频道推送给当前房间在线用户。
|
|||
|
|
window.Echo.private(`user.${myId}`).listen(".BannerNotification", showBanner);
|
|||
|
|
|
|||
|
|
if (roomId) {
|
|||
|
|
window.Echo.join(`room.${roomId}`).listen(".BannerNotification", showBanner);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 绑定好友与大卡片通知监听,并暴露旧全局函数。
|
|||
|
|
*
|
|||
|
|
* @returns {void}
|
|||
|
|
*/
|
|||
|
|
export function bindFriendNotificationControls() {
|
|||
|
|
if (typeof window === "undefined") {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.showFriendBanner = showFriendBanner;
|
|||
|
|
window.setupFriendNotification = setupFriendNotification;
|
|||
|
|
window.setupBannerNotification = setupBannerNotification;
|
|||
|
|
|
|||
|
|
setupFriendNotification();
|
|||
|
|
setupBannerNotification();
|
|||
|
|
}
|