Files
DP/AdminPanel/src/utils/theme.ts

172 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// <reference types="types-for-adobe/Photoshop/2015.5"/>
/**
* theme.ts
* 处理 Photoshop 主题颜色同步
* 支持两种模式:
* 1. 直接 CEP 模式CSInterface 可用)
* 2. iframe 模式(通过 postMessage 接收主题)
*/
import { cep } from './cep';
import { logger } from './logger';
interface Color {
red: number;
green: number;
blue: number;
alpha: number;
}
interface PSThemeMessage {
type: 'PS_THEME';
theme: {
bgColor: string;
isLight: boolean;
fontSize: number;
};
}
/**
* 将 Adobe 颜色对象转换为 CSS RGB 字符串
*/
function toHex(color: Color): string {
const r = Math.round(color.red).toString(16).padStart(2, '0');
const g = Math.round(color.green).toString(16).padStart(2, '0');
const b = Math.round(color.blue).toString(16).padStart(2, '0');
return `#${r}${g}${b}`;
}
/**
* 计算颜色的亮度 (0-255)
*/
function getBrightness(color: Color): number {
return (color.red * 299 + color.green * 587 + color.blue * 114) / 1000;
}
/**
* 应用主题到页面
*/
function applyTheme(bgColor: string, isLight: boolean, fontSize?: number) {
const root = document.documentElement;
let textColorHex, borderColorHex, iconColorHex;
if (isLight) {
document.body.removeAttribute('arco-theme');
textColorHex = '#222222';
borderColorHex = '#d0d0d0';
iconColorHex = '#333333';
} else {
document.body.setAttribute('arco-theme', 'dark');
textColorHex = '#dfdfdf';
borderColorHex = '#4a4a4a';
iconColorHex = '#f0f0f0';
}
// 设置 CSS 变量
root.style.setProperty('--ps-bg', bgColor);
root.style.setProperty('--ps-text', textColorHex);
root.style.setProperty('--ps-border', borderColorHex);
root.style.setProperty('--ps-icon', iconColorHex);
if (fontSize) {
root.style.setProperty('--ps-font-size', `${fontSize}px`);
}
// Arco Design 主题变量
root.style.setProperty('--color-bg-1', bgColor);
root.style.setProperty('--color-bg-2', bgColor);
root.style.setProperty('--color-bg-3', borderColorHex);
root.style.setProperty('--color-text-1', textColorHex);
root.style.setProperty('--color-border', borderColorHex);
// 应用到 body
document.body.style.backgroundColor = bgColor;
document.body.style.color = textColorHex;
logger.log(`[Theme] 已应用主题: ${isLight ? '浅色' : '深色'}, 背景: ${bgColor}`);
}
/**
* 从 CSInterface 直接获取并更新主题
*/
export const updateTheme = () => {
if (!cep.inCEP) {
// 浏览器模式 - 使用默认深色主题
applyTheme('#323232', false);
return;
}
const hostEnv = cep.getHostEnvironment();
if (!hostEnv) return;
const skinInfo = hostEnv.appSkinInfo;
const panelBgColor = skinInfo.panelBackgroundColor.color;
const bgColorHex = toHex(panelBgColor);
const brightness = getBrightness(panelBgColor);
const isLight = brightness > 128;
applyTheme(bgColorHex, isLight, skinInfo.baseFontSize);
// 发送主题给 iframe
const iframe = document.querySelector('iframe');
if (iframe && iframe.contentWindow) {
const message: PSThemeMessage = {
type: 'PS_THEME',
theme: {
bgColor: bgColorHex,
isLight: isLight,
fontSize: skinInfo.baseFontSize
}
};
iframe.contentWindow.postMessage(message, '*');
}
};
/**
* 处理来自子 iframe 的请求
*/
function handleChildMessage(event: MessageEvent) {
if (event.data && event.data.type === 'REQUEST_THEME') {
updateTheme();
}
}
/**
* 处理来自父窗口的主题消息iframe 模式)
*/
function handleThemeMessage(event: MessageEvent) {
const data = event.data as PSThemeMessage;
if (data && data.type === 'PS_THEME' && data.theme) {
logger.log('[Theme] 收到父窗口主题消息');
applyTheme(data.theme.bgColor, data.theme.isLight, data.theme.fontSize);
}
}
/**
* 初始化主题监听
*/
export const initThemeListener = () => {
// 检测是否在 iframe 中运行
const inIframe = window !== window.parent;
if (inIframe) {
// iframe 模式:监听来自父窗口的消息
logger.log('[Theme] iframe 模式 - 监听 postMessage');
window.addEventListener('message', handleThemeMessage);
// 请求父窗口发送主题
window.parent.postMessage({ type: 'REQUEST_THEME' }, '*');
} else if (cep.inCEP) {
// 直接 CEP 模式
logger.log('[Theme] CEP 模式 - 直接监听主题变化');
updateTheme();
cep.addEventListener('com.adobe.csxs.events.ThemeColorChanged', updateTheme);
// 监听来自 iframe 的请求
window.addEventListener('message', handleChildMessage);
} else {
// 纯浏览器模式
logger.log('[Theme] 浏览器模式 - 使用默认主题');
applyTheme('#323232', false);
}
};