Files
chatroom/resources/js/chat-room/font-size.js
T

130 lines
3.8 KiB
JavaScript

// 聊天室字号偏好控制,保留旧的 localStorage key 以兼容已有用户设置。
export const CHAT_FONT_SIZE_STORAGE_KEY = "chat_font_size";
export const CHAT_DEFAULT_FONT_SIZE = 13;
export const CHAT_FONT_SIZE_MIN = 10;
export const CHAT_FONT_SIZE_MAX = 30;
let fontSizeEventsBound = false;
/**
* 规整聊天室字号,过滤非法或越界的旧缓存值。
*
* @param {unknown} size 字号大小
* @returns {number|null}
*/
export function normalizeChatFontSize(size) {
const px = Number.parseInt(String(size ?? ""), 10);
if (Number.isNaN(px) || px < CHAT_FONT_SIZE_MIN || px > CHAT_FONT_SIZE_MAX) {
return null;
}
return px;
}
/**
* 同步底部输入框上方工具按钮字号。
*
* @param {number} px 用户选择的聊天字号
* @returns {void}
*/
function applyInputToolbarFontSize(px) {
const toolbarRow = document.querySelector("#chat-form > .input-row");
if (!(toolbarRow instanceof HTMLElement)) {
return;
}
const fontSize = `${px}px`;
toolbarRow.style.fontSize = fontSize;
toolbarRow.style.fontFamily = "inherit";
toolbarRow.style.lineHeight = "1.2";
toolbarRow.querySelectorAll([
":scope > label",
":scope > label select",
":scope > label input",
":scope > button",
":scope > div > button",
"#feature-menu button",
"#admin-menu button",
].join(",")).forEach((control) => {
control.style.fontFamily = "inherit";
control.style.fontSize = "inherit";
control.style.lineHeight = "1.2";
control.style.fontWeight = "400";
});
}
/**
* 应用字号到聊天消息窗口和输入栏工具按钮,并保存到 localStorage。
*
* @param {string|number} size 字号大小
* @param {{syncContext?:boolean}} options 同步选项
* @returns {boolean}
*/
export function applyFontSize(size, options = {}) {
const px = normalizeChatFontSize(size);
if (px === null) {
return false;
}
const publicContainer = document.getElementById("chat-messages-container");
const privateContainer = document.getElementById("chat-messages-container2");
if (publicContainer) {
publicContainer.style.fontSize = `${px}px`;
}
if (privateContainer) {
privateContainer.style.fontSize = `${px}px`;
}
applyInputToolbarFontSize(px);
localStorage.setItem(CHAT_FONT_SIZE_STORAGE_KEY, String(px));
if (options.syncContext !== false && window.chatContext && typeof window.chatContext === "object") {
window.chatContext.chatPreferences = {
...(window.chatContext.chatPreferences || {}),
font_size: px,
};
}
const selector = document.getElementById("font_size_select");
if (selector) {
selector.value = String(px);
}
return true;
}
/**
* 从账号偏好或 localStorage 恢复已保存的聊天室字号。
*
* @returns {boolean}
*/
export function restoreChatFontSize() {
const serverFontSize = normalizeChatFontSize(window.chatContext?.chatPreferences?.font_size);
const localFontSize = normalizeChatFontSize(localStorage.getItem(CHAT_FONT_SIZE_STORAGE_KEY));
const saved = serverFontSize ?? localFontSize ?? CHAT_DEFAULT_FONT_SIZE;
return applyFontSize(saved, { syncContext: serverFontSize !== null });
}
/**
* 绑定字号选择器事件。
*
* @returns {void}
*/
export function bindChatFontSizeControl() {
if (fontSizeEventsBound || typeof document === "undefined") {
return;
}
fontSizeEventsBound = true;
document.addEventListener("change", (event) => {
if (!(event.target instanceof HTMLSelectElement) || event.target.id !== "font_size_select") {
return;
}
if (applyFontSize(event.target.value)) {
void window.saveChatPreferences?.();
}
});
}