import { ipcMain, screen, session } from "electron"; import http from 'http'; import https from 'https'; import { URL } from 'url'; import { ApiResponse, MenuItem, TagResolutionConfig, EIACDesktopApi, SpecialPUrlItem } from './EIAC_Desktop_Api'; export function initialize(): void { // Get primary display(需要注意:size 是逻辑像素尺寸(logical screen size),已被 DPI 缩放影响,需要除以 DPI 缩放比例才是物理像素尺寸(physical screen size)) ipcMain.handle('get-primary-display', () => screen.getPrimaryDisplay()); // Check if the URL is available ipcMain.handle('check-url-available', async (event, rawUrl: string) => { try { const url: URL = new URL(rawUrl); const lib = url.protocol === 'https:' ? https : http; return await new Promise((resolve) => { // 先用HEAD请求,如果遇到403,则再用GET请求再试一次(部分服务器可能禁止HEAD请求)。 const requestOptions: http.RequestOptions | https.RequestOptions = { hostname: url.hostname, port: url.port || undefined, path: url.pathname + url.search, headers: { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } }; const headReq = lib.request( { method: 'HEAD', timeout: 3000, ...requestOptions }, (res) => { console.log('check-url-available HEAD', url.toString(), res.statusCode, res.statusMessage); if (res.statusCode === 403) { headReq.destroy() const getReq = lib.get({ method: 'GET', ...requestOptions }, (res) => { console.log('check-url-available GET', url.toString(), res.statusCode, res.statusMessage); resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); getReq.destroy() }); getReq.on('error', (err) => { resolve({ ok: false, status: -1, message: err.message }); }); getReq.on('timeout', () => { resolve({ ok: false, status: -1, message: 'GET Timeout' }); getReq.destroy(); }); } else { resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); headReq.destroy(); } } ); headReq.on('error', (err) => { resolve({ ok: false, status: -1, message: err.message }); }); headReq.on('timeout', () => { resolve({ ok: false, status: -1, message: 'HEAD Timeout' }); headReq.destroy(); }); headReq.end(); }) } catch (e) { return { ok: false, status: -1, message: 'Invalid URL' }; } }); // Set webview‘s cookie ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => { try { const parsedUrl = new URL(url); const cookies: Array<{ Key: string, Value: string }> = JSON.parse(cookie); for (const cookieItem of cookies) { await session.defaultSession.cookies.set({ url: url, name: cookieItem.Key.trim(), value: cookieItem.Value.trim(), domain: parsedUrl.hostname, path: '/', secure: parsedUrl.protocol === 'https:', httpOnly: true }); } return true; } catch (error) { console.error('设置cookie失败:', error); return false; } }); // Get menu cache ipcMain.handle('get-menu-cache', async () => menuData ?? await menuDataReadyPromise); // Get config cache ipcMain.handle('get-config-cache', async () => configData ?? await configDataReadyPromise); // Get zoom factor ipcMain.handle('get-zoom-factor-by-url', async (event, url: string) => { const display: Electron.Display = screen.getPrimaryDisplay(); const physicalSize: Electron.Size = { width: display.size.width * display.scaleFactor, height: display.size.height * display.scaleFactor }; const resolution: string = `${physicalSize.width}*${physicalSize.height}`; console.log('PhysicalResolution:', resolution); console.log(`Resolution: ${display.size.width}*${display.size.height}`); console.log(`ScaleFactor: ${display.scaleFactor}`); if (!configData) { await configDataReadyPromise; } if (configData.code != 200 || configData.status != 0) { console.error('Get config failed:', configData.msg + ', status: ' + configData.status + ', code: ' + configData.code); return display.scaleFactor; } const configList: TagResolutionConfig[] = configData.data; let config: TagResolutionConfig = configList.find(c => c.Resolutions.includes(resolution)); if (!config) { config = configList.find(c => c.Resolutions === '*'); } if (!config) { config = configList[0]; } console.log('Match Config:', config); let specialPUrl: SpecialPUrlItem = config.SpecialPUrl.find(s => s.SPUrl.toLowerCase() === url.toLowerCase()); if (!specialPUrl) { specialPUrl = config.SpecialPUrl.find(s => url.toLowerCase().startsWith(s.SPUrl.toLowerCase())); } console.log('specialPUrl:', specialPUrl); let percentage: number = typeof config.Percentage === 'string' ? parseInt(config.Percentage) : config.Percentage; if (specialPUrl) { percentage = typeof specialPUrl.SPPer === 'string' ? parseInt(specialPUrl.SPPer) : specialPUrl.SPPer; } console.log('Percentage:', percentage); return percentage; }); } let menuData: ApiResponse = null; let menuDataReadyPromise: Promise>; let configData: ApiResponse = null; let configDataReadyPromise: Promise>; function getMenuAsync(): void { if (!menuDataReadyPromise) { menuDataReadyPromise = new Promise((resolve, reject) => { EIACDesktopApi.Menu.GetMenuAsync() .then(data => { menuData = data; resolve(data); }) .catch(err => { reject(err); }); }); } } function getConfigAsync(): void { if (!configDataReadyPromise) { configDataReadyPromise = new Promise((resolve, reject) => { EIACDesktopApi.Menu.GetConfigAsync() .then(data => { configData = data; resolve(data); }) .catch(err => { reject(err); }); }); } } export function preloadData(): void { getMenuAsync(); getConfigAsync(); }