import fspromises from 'fs/promises' import { v4 as uuidv4 } from 'uuid' import { version } from '../../package.json' import { graphics } from 'systeminformation' import { app, shell, BrowserWindow, ipcMain, dialog, nativeTheme, session } from 'electron' import path, { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/icon.ico?asset' import { define } from '../define/define.js' import { func } from './func.js' import { AsyncQueue } from './quene' import { DEFINE_STRING } from '../define/define_string' import { Tools } from './tools.js' import { ImageGenerate } from './ReverseManage/imageGenerate.js' import { Setting } from './setting/setting.js' import { has, isEmpty } from 'lodash' import { AutoSync } from './setting/autoSync.js' import { TaskManager } from './Service/taskManage' // ipc import { DiscordIpc, RemoveDiscordIpc } from './IPCEvent/discordIpc.js' import { Logger } from './logger.js' import { RegisterIpc } from './IPCEvent/index.js' let tools = new Tools() let imageGenerate = new ImageGenerate(global) let setting = new Setting(global) async function InitData(gl) { let res = await setting.getSettingDafultData() gl.config = res return res } function setIpcHandler(hash) { if (hash == 'discord') { DiscordIpc(global) } } function removeIpcHandler(hash) { if (hash == 'discord') { RemoveDiscordIpc() } } async function createWindow(hash = 'ShowMessage', data, url = null) { // Create the browser window. await InitData(global) global.currentHash = hash // 判断当前是不是有设置的宽高,用的话记忆 let isRe = global.config.window_wh_bm_remember && hash == 'ShowMessage' && global.config.window_wh_bm const ses = session.fromPartition('persist:my-session') let mainWindow = new BrowserWindow({ width: isRe ? global.config.window_wh_bm.width : 900, height: isRe ? global.config.window_wh_bm.height : 675, x: isRe ? global.config.window_wh_bm.x : 100, y: isRe ? global.config.window_wh_bm.y : 100, title: 'LAITool', icon: '../../resources/icon.ico', show: false, autoHideMenuBar: true, ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, nodeIntegration: true, // 在网页中集成Node nodeIntegrationInWorker: true, webSecurity: false, partition: 'persist:my-partition', session: ses, webviewTag: true } }) mainWindow.myID = uuidv4() mainWindow.on('ready-to-show', () => { mainWindow.show() }) mainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) // HMR for renderer base on electron-vite cli. // Load the remote URL for development or the local html file for production. // 判断是不是加载外部网页 if (url) { mainWindow.loadURL(url) } else { if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/#/' + hash) // mainWindow.webContents.openDevTools() } else { if (hash != '') { mainWindow.loadURL(`file://${path.join(__dirname, '../renderer/index.html')}#/${hash}`) } else { mainWindow.loadFile(join(__dirname, '../renderer/index.html')) } } } mainWindow.on('close', async () => { // 判断指定的窗口,移除指定的监听 removeIpcHandler(hash) global.newWindow = global.newWindow.filter((item) => item.id != mainWindow.id) // 判断当前的是不是开启了记录功能 if (global.config.window_wh_bm_remember && hash == 'ShowMessage') { let window_wh_bm = mainWindow.getBounds() // 记录到文件中 await setting.ModifySampleSetting(JSON.stringify({ window_wh_bm: window_wh_bm })) } }) // 创建一个新的窗口,添加对应的监听 global.newWindow.push({ hash, id: mainWindow.id, win: mainWindow, init_folder: data }) setIpcHandler(hash) return mainWindow } let mainWindow global.createWindow = createWindow // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(async () => { // Set app user model id for windows electronApp.setAppUserModelId('com.electron') // Default open or close DevTools by F12 in development // and ignore CommandOrControl + R in production. // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window) }) //判断是不是又配置文件,没有的话,将temp中的基础配置加载 // 判断文件夹是不是存在 let config_p = path.dirname(define.config_path) let isE = await tools.checkExists(config_p) // 文件夹存在判断json文件数量 let ex_json = [] if (isE) { let ex_json_path = await tools.getFilesWithExtensions(config_p, '.json') for (let i = 0; i < ex_json_path.length; i++) { const element = ex_json_path[i] ex_json.push(path.basename(element)) } } else { await fspromises.mkdir(config_p, { recursive: true }) } // 判断文件是不是存在,不存在添加 if (ex_json.length != 5) { let temp_path = path.join(path.dirname(define.draft_temp_path), 'config') let tmp_json_path = await tools.getFilesWithExtensions(temp_path, '.json') for (let i = 0; i < tmp_json_path.length; i++) { const element = tmp_json_path[i] if (!ex_json.includes(path.basename(element))) { await fspromises.copyFile(element, path.join(config_p, path.basename(element))) } } } // 判断动态文件是不是存在 tools.checkJsonFileExistsOrCreate(path.normalize(define.dynamic_setting)) // 判断标签文件是不是存在 tools.checkJsonFileExistsOrCreate( path.normalize(define.tag_setting), JSON.stringify({ character_tags: [], style_tags: [], scene_tags: [], prefix_tags: [], suffix_tags: [] }) ) // 判断SD图片缓存文件是不是存在(不存在创建) tools.checkFolderExistsOrCreate(path.normalize(define.temp_sd_image)) tools.checkFolderExistsOrCreate(path.normalize(path.join(define.image_path, 'c_s'))) app.on('activate', async function () { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) { mainWindow = createWindow('ShowMessage', null) } }) global.logger = new Logger(define.logger_path) // 同步数据 await AutoSync() global.newWindow = [] mainWindow = await createWindow('ShowMessage', null) global.requestQuene = new AsyncQueue(global, global.config.task_number) global.fileQueue = new AsyncQueue(global, 1) }) // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) RegisterIpc(createWindow) ipcMain.handle('dark-mode:toggle', (event, value) => { if (value) { nativeTheme.themeSource = value } else { nativeTheme.themeSource = 'system' } return nativeTheme.shouldUseDarkColors }) // In this file you can include the rest of your app"s specific main process // code. You can also put them in separate files and require them here. ipcMain.handle(DEFINE_STRING.GET_SETTING_Dafault_DATA, async (event) => { return await InitData(global) }) ipcMain.handle(DEFINE_STRING.GET_DRAFT_FILE_LIST, async (event) => { let res = await func.getDraftFileList() return res }) ipcMain.handle(DEFINE_STRING.SELECT_FOLDER, async (event, value = null) => { let po = ['openDirectory'] if (value && !isEmpty(value.multi)) { po.push('multiSelections') } let { filePaths } = await dialog.showOpenDialog({ properties: po, defaultPath: value && !isEmpty(value.defaultPath) ? value.defaultPath : '' }) return filePaths }) ipcMain.handle(DEFINE_STRING.SELECT_FILE, async (event, value) => { try { let { filePaths } = await dialog.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'fileName', extensions: value }] }) return { code: 1, value: filePaths[0] } } catch (error) { return { code: 0, message: `Error Message ${error}` } } }) ipcMain.handle(DEFINE_STRING.GET_DRAFT_TEXT_STYLE, async (event, value) => { let res = await func.getDraftTextStyle(value) return res }) ipcMain.handle(DEFINE_STRING.GET_TEXT_STYLE_LIST, async (event) => { let res = await func.getClipSetting('text_style') return res }) ipcMain.handle(DEFINE_STRING.GET_FRIENDLY_REMINDER_LIST, async (event) => { let res = await func.getClipSetting('friendly_reminder_setting') return res }) ipcMain.handle(DEFINE_STRING.GET_FRIENDLY_REMINDER_DRAFT, async (event, value) => { let res = await func.GetDraftFriendlyReminder(value) return res }) ipcMain.handle(DEFINE_STRING.ADD_DRAFT, async (event, value) => { let res = await func.addDraft(value) return res }) // 获取当前版本 ipcMain.handle(DEFINE_STRING.GET_VERSION, async (event) => { // 获取当前电脑的显卡信息 let da = await graphics() for (let i = 0; i < da.controllers.length; i++) { // 获取第一个英伟达或者是AMD的显卡信息 const element = da.controllers[i] if (element.vendor.startsWith('NVIDIA')) { global.gpu = element global.gpu.type = 'NVIDIA' break } else if (element.vendor.startsWith('AMD') || element.vendor.startsWith('Advanced')) { global.gpu = element global.gpu.type = 'AMD' break } else { global.gpu = { name: 'OTHER' } global.gpu.type = 'OTHER' } } return version + ' ' + (global.gpu?.name ? global.gpu.name : '') }) // 监听保存SD配置 ipcMain.handle(DEFINE_STRING.SAVE_SD_CONFIG, async (event, value) => await func.SaveSDConfig(value)) // 监听保存生成视频的简单配置 ipcMain.handle( DEFINE_STRING.SAVE_GENERAL_SETTING, async (event, value) => await func.SaveGeneralSetting(value) ) // 获取当前的视频合成配置信息 ipcMain.handle( DEFINE_STRING.GET_VIDEO_CONFIG_MESSAGE, async (event) => await func.GetVideoConfigMessage() ) // 监听保存字幕的是指信息 ipcMain.handle( DEFINE_STRING.SAVE_ASS_CONFIG, async (event, value) => await func.SaveAssConfig(value) ) // 监听获取当前系统安装的字体 ipcMain.handle( DEFINE_STRING.GET_SYSTEM_INSTALL_FONTNAME, async (event) => await func.GetSystemInstallFontName() ) // 监听删除视频配置任务(删除指定ID的值) ipcMain.handle( DEFINE_STRING.DELETE_VIDEO_CONFIG, async (event, value) => await func.DeleteVideoConfig(value) ) // 监听添加生图任务信息 ipcMain.handle( DEFINE_STRING.ADD_IMAGE_TASK_LIST, async (event, value) => await func.AddImageTask(value) ) // 监听删除生成图片列表中的信息 ipcMain.handle( DEFINE_STRING.DELETE_IMAGE_TASK_LIST, async (event, value) => await func.DeleteImageTaskList(value) ) // 监听获取加密的机械码任务 ipcMain.handle(DEFINE_STRING.GET_MACHINE_ID, async (event, value) => await func.GetMachineId()) // 监听获取不想要的提示词任务 ipcMain.handle(DEFINE_STRING.GET_BAD_PROMPT, async (event) => await func.GetBadPrompt()) // 保存不想要的提示词 ipcMain.handle( DEFINE_STRING.SAVE_BAD_PROMPT, async (event, value) => await func.SaveBadPrompt(value) ) // 一键删除不想要的值 ipcMain.handle(DEFINE_STRING.DELETE_BAD_PROMPT, async (event) => await func.DeleteBadPrompt()) // 监听反推任务 ipcMain.handle(DEFINE_STRING.PUSH_BACK_PROMPT, async (event) => await func.PushBackPrompt()) // 打开GPT购买界面 ipcMain.on(DEFINE_STRING.OPEN_GPT_BUY_URL, async (event, value) => await func.openGptBuyUrl(value)) // 监听打开任意网站的任务 ipcMain.on(DEFINE_STRING.OPEN_URL, async (event, value) => await func.OpenUrl(value)) // 监听抽帧任务 ipcMain.handle(DEFINE_STRING.GET_FRAME, async (event, value) => await func.getFrame(value)) // 监听获取ADtailer列表的任务 ipcMain.handle(DEFINE_STRING.GET_ADETAILER_LIST, async (event) => await func.GetADetailerList()) // 监听保存ADtailer数据 ipcMain.handle( DEFINE_STRING.SAVE_DETAILER_CONFIG, async (event, value) => await func.SaveADetailerConfig(value) ) // 分镜识别。语音识别 ipcMain.handle( DEFINE_STRING.START_STORY_BOARDING, async (event, value) => await func.StartStoryboarding(value) ) // 保存试用结束时间 ipcMain.on(DEFINE_STRING.SAVE_TRIAL_END_TIME, (event, value) => { global.endTime = value.endTime global.permissions = value.permissions }) // 获取当前机器的权限 ipcMain.handle(DEFINE_STRING.GET_PERMISSION, async (event) => { return { code: 1, endTime: global.endTime, permissions: global.permissions } }) // 监听字幕的保存 ipcMain.handle(DEFINE_STRING.SAVE_NEW_WORD, async (event, value) => { return await func.SaveNewWord(value) }) /** * 监听字幕对齐任务,通过前端传过来的数据 */ ipcMain.handle(DEFINE_STRING.ALIGN_DRAFT_IMG_TO_TEXT, async (event, value) => { return await func.alginDraftImgToText(value) }) /** * 监听单张重绘任务 */ ipcMain.handle(DEFINE_STRING.RE_GENERATE_IAMGE_ONE, async (event, value) => { console.log(value[0]) let newWindow = global.newWindow.filter((item) => item.id == value[0]) let res = await func.ReGenerateImageOne(newWindow, value) return res }) /** * 监听文件夹高清任务 */ ipcMain.handle(DEFINE_STRING.IMPROVE_IMAGE_RESOULTION, async (event, value) => { let res = await imageGenerate.ImproveResolution(value) return res }) /** * 监听刷新窗口的事件 */ ipcMain.handle(DEFINE_STRING.REFRASH_IMAGWE_DATA, async (event, value) => { console.log(value) let newWindow = global.newWindow.filter((item) => item.id == value[0]) let img_dir = path.join(global.config.project_path, 'tmp/' + value[1]) let res = await imageGenerate.getFolderImageList(newWindow, img_dir, true) return res }) /** * 监听一个窗口,返回窗口创建成功后需要的基础数据 */ ipcMain.on(DEFINE_STRING.SHOW_NEW_WINDOW, async (event, value) => { let newW = createWindow(value[0], value[1]) }) // 监听程序关闭 ipcMain.on(DEFINE_STRING.QUIT_APP, (event) => { app.quit() }) /** * 监听图片对齐任务 */ ipcMain.on(DEFINE_STRING.ALIGN_DRAFT_IMG, async (event, value) => { func.alignDraftImage(mainWindow, value) })