const electron = require("electron"); electron.app.setAppLogsPath(); if (electron.app.requestSingleInstanceLock()) { const { resolve, join, basename, extname } = require("node:path"); const { Socket } = require("node:net"); const { randomBytes } = require("node:crypto"); const { writeFileSync, unlinkSync, readdirSync } = require("node:fs"); const { EventEmitter } = require("node:events"); const electronStore = require("electron-store"); const packagejson = require(resolve(join(__dirname, "package.json"))); const protocol = packagejson.protocol; if (process.defaultApp && process.argv.length >= 2) electron.app.setAsDefaultProtocolClient(protocol, process.execPath, [resolve(process.argv[1])]); else electron.app.setAsDefaultProtocolClient(protocol); electron.app.on("window-all-closed", () => { if (process.platform != "darwin") return electron.app.quit(); }); return electron.app.whenReady().then(() => { const isDev = "ELECTRON_IS_DEV" in process.env ? parseInt(process.env.ELECTRON_IS_DEV, 10) == 1 && electron.app.isPackaged == false : electron.app.isPackaged == false; const icon = resolve(join(__dirname, "icon.ico")); const name = packagejson.name; const author = packagejson.author; const linkProject = String(packagejson.repository.url).split(".git")[0]; const displayName = packagejson.displayName; const defaultUrl = { base: packagejson.url, full: packagejson.url }; const is = new class { string(value) { return typeof value == "string" ? value.length > 0 : false; }; number(value) { return isNaN(Number(value)) == false; }; array(value) { return Array.isArray(value) == true ? value.length > 0 : false; }; json(value) { try { value = this.string(value) == false ? JSON.parse(JSON.stringify(value)) : JSON.parse(value); if (typeof value == "object" && value != null) { if (Object.keys(value).length > 0) return true; else return false; } else return false; } catch (error) { return false; }; }; url(value) { try { new URL(value); return true; } catch (error) { return false; }; }; deepUrl(value) { try { return new URL(value).protocol == `${protocol}:`; } catch (error) { return false; }; }; }; const parse = value => { try { return is.string(value) == false ? JSON.parse(JSON.stringify(value)) : JSON.parse(value); } catch (error) { return undefined; }; }; const deepLinkToUrl = value => { try { const deepLink = new URL(value); if (deepLink.host <= 0) return defaultUrl.base; else return `${defaultUrl.base}/${deepLink.host}${deepLink.pathname}${deepLink.search}`; } catch (error) { return defaultUrl.base; }; }; let settingsSchema = {}; settingsSchema[packagejson.exeName] = { type: "object", default: { LANGUAGE: undefined, START_UP: false, START_HIDDEN: false, START_FULL_SCREEN: false, MINIMIZE_TO_TRAY: false, SAVE_WINDOW_SIZE: false, ALWAYS_ON_TOP: false, ADBLOCK: false, DISCORD_RICH_PRESENCE: false } }; const settings = new electronStore({ name: "settings", watch: true, schema: settingsSchema }); let profileSchema = {}; profileSchema[packagejson.exeName] = { type: "object", default: { history: { }, watchlist: { }, favorite: { } } }; const profile = new electronStore({ name: "profile", watch: true, schema: profileSchema }); if (!profile.has(packagejson.exeName) || !is.json(profile.get(packagejson.exeName))) profile.set(packagejson.exeName, {}); const historyProfile = `${packagejson.exeName}.history`; if (!profile.has(historyProfile) || !is.json(profile.get(historyProfile))) profile.set(historyProfile, {}); const watchlistProfile = `${packagejson.exeName}.watchlist`; if (!profile.has(watchlistProfile) || !is.json(profile.get(watchlistProfile))) profile.set(watchlistProfile, {}); const favoriteProfile = `${packagejson.exeName}.favorite`; if (!profile.has(favoriteProfile) || !is.json(profile.get(favoriteProfile))) profile.set(favoriteProfile, {}); const screen = electron.screen.getDisplayNearestPoint(electron.screen.getCursorScreenPoint()); const size = screen.workAreaSize; const factor = screen.scaleFactor; const splashWindow = new electron.BrowserWindow({ width: 542, height: 132, title: displayName, show: false, resizable: false, minimizable: true, maximizable: false, fullscreenable: false, titleBarStyle: "hidden", titleBarOverlay: { color: "#000", symbolColor: "#FFF" }, center: true, frame: false, icon: icon, webPreferences: { devTools: false, zoomFactor: 1.0 / factor, nativeWindowOpen: true } }); splashWindow.setMenuBarVisibility(false); splashWindow.hookWindowMessage(0x0116, () => { splashWindow.setEnabled(false); splashWindow.setEnabled(true); }); splashWindow.on("system-context-menu", event => event.preventDefault()); splashWindow.on("closed", () => electron.app.exit()); return splashWindow.loadFile(resolve(join(__dirname, "splash.html"))).then(() => { defaultUrl.full = deepLinkToUrl(process.argv.find(arg => is.deepUrl(arg) == true)); let isHidden = settings.get(`${packagejson.exeName}.START_HIDDEN`); if (!isHidden) splashWindow.show(); const createWindow = () => { if (!settings.has(`${packagejson.exeName}.WIDTH`) || settings.get(`${packagejson.exeName}.WIDTH`) > size.width) settings.set(`${packagejson.exeName}.WIDTH`, Math.round((size.width - (Math.abs((size.width * 0.6) / 2 - size.width / 2))))); if (!settings.has(`${packagejson.exeName}.HEIGHT`) || settings.get(`${packagejson.exeName}.HEIGHT`) > size.height) settings.set(`${packagejson.exeName}.HEIGHT`, Math.round((size.height - (Math.abs((size.height * 0.6) / 2 - size.height / 2))))); const mainWindow = new electron.BrowserWindow({ width: settings.get(`${packagejson.exeName}.WIDTH`), height: settings.get(`${packagejson.exeName}.HEIGHT`), title: displayName, center: true, show: false, fullscreen: settings.get(`${packagejson.exeName}.START_FULL_SCREEN`), icon: icon, webPreferences: { devTools: isDev == true, zoomFactor: 1.0 / factor, nativeWindowOpen: true, preload: resolve(join(__dirname, "preload.js")) } }); const discordRichPresence = new class extends EventEmitter { #socket = undefined; #status = undefined; #interval = undefined; has() { return settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`) ? typeof this.#socket != "undefined" ? (this.#socket.closed == false || this.#socket.destroyed == false) : this.#status == "CONNECTED" : false; }; set() { if (this.has()) { let buttons; if (is.array(this.buttons)) { const filter = this.buttons.filter(data => is.json(data) == true && is.string(data.label) == true && is.url(data.url) == true); if (filter.length == 1) buttons = [filter[0]]; else if (filter.length >= 2) buttons = [filter[0], filter[1]]; }; const str = JSON.stringify({ cmd: "SET_ACTIVITY", nonce: randomBytes(16).toString("hex"), args: { pid: this.pid, activity: { state: this.state, details: this.details, timestamps: { start: (this.elapsedTimestamp || this.startTimestamp == true) && isNaN(this.startTimestamp) == true ? Date.now() : this.startTimestamp, end: this.endTimestamp }, assets: { large_image: this.largeImage, large_text: this.largeImageTooltip, small_image: this.smallImage, small_text: this.smallImageTooltip }, type: !isNaN(this.type) ? this.type : 0, buttons: buttons, instance: this.instance } } }); const len = Buffer.byteLength(str); const packet = Buffer.alloc(8 + len); packet.writeInt32LE(1, 0); packet.writeInt32LE(len, 4); packet.write(str, 8, len); if (this.#socket.write(packet)) { this.emit("running"); this.#status = "RUNNING"; if (typeof this.interval != "undefined") { clearInterval(this.interval); this.interval = undefined; }; }; } else if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) { this.#socket = new Socket(); this.#socket.setEncoding("utf8"); this.#socket.setKeepAlive(true); this.#socket.on("connect", () => { this.emit("connected"); this.#status = "CONNECTED"; }); this.#socket.on("data", data => { if (is.string(data)) data = `{${data.toString().substring(data.toString().indexOf("{") + 1)}`; if (is.json(data)) { data = JSON.parse(data); if (data.evt == "READY" && data.cmd == "DISPATCH") return this.set(); else if (data.evt == "ERROR") return this.#socket.emit("error", new Error("TR.DISCORD_RICH_PRESENCE.LOST")); }; }); this.#socket.on("error", () => { this.emit("error"); this.#status = "ERROR"; if (typeof this.#interval == "undefined") this.#interval = setInterval(() => { if (this.has()) { clearInterval(this.#interval); this.#interval = undefined; } else return this.set(); }, this.intervalTime); }); this.#socket.on("close", error => { if (!error) { if (!settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) { this.emit("disabled"); if (this.#status != "DISABLED") this.#status = "DISABLED"; } else { this.emit("closed"); if (this.#status != "CLOSED") this.#status = "CLOSED"; }; if (typeof this.#interval == "undefined") this.#interval = setInterval(() => { if (this.has()) { clearInterval(this.#interval); this.#interval = undefined; } else return this.set(); }, this.intervalTime); } else { this.emit("closed"); if (["ERROR", "DISABLED", "CLOSED"].some(key => this.#status != key)) this.#status = "CLOSED"; }; }); return this.#socket.connect("\\\\?\\pipe\\discord-ipc-0", () => { const str = JSON.stringify({ v: 1, client_id: this.clientId }); const len = Buffer.byteLength(str); let packet = Buffer.alloc(8 + len); packet.writeInt32LE(0, 0); packet.writeInt32LE(len, 4); packet.write(str, 8, len); return this.#socket.write(packet); }); }; }; del() { if (this.has()) { if (typeof this.interval != "undefined") { clearInterval(this.interval); this.interval = undefined; }; this.#socket.destroy(); this.emit("delete", !this.has()); this.#socket = undefined; this.#status = "DELETED"; }; }; clr() { this.clientId = packagejson.DISCORD_CLIENT_ID; this.intervalTime = 15000; this.pid = mainWindow.webContents.getOSProcessId(); this.state = undefined; this.details = undefined; this.startTimestamp = undefined; this.endTimestamp = undefined; this.elapsedTimestamp = true; this.largeImage = undefined; this.largeImageTooltip = undefined; this.smallImage = undefined; this.smallImageTooltip = undefined; this.type = 3; this.buttons = []; this.instance = true; this.emit("clear"); }; }; discordRichPresence.clr(); const languages = []; for (const lang of readdirSync(resolve(join(__dirname, "translations"))).filter(file => file.endsWith(".json"))) { languages.push(lang.split(extname(lang))[0].toLowerCase()); }; if (!settings.has(`${packagejson.exeName}.LANGUAGE`) || !languages.includes(String(settings.get(`${packagejson.exeName}.LANGUAGE`)).toLowerCase())) { const locale = electron.app.getLocale().toLowerCase(); const systemLocale = electron.app.getSystemLocale().toLowerCase(); if (languages.includes(locale)) settings.set(`${packagejson.exeName}.LANGUAGE`, locale); else if (languages.includes(systemLocale)) settings.set(`${packagejson.exeName}.LANGUAGE`, systemLocale); else { const findPreferred = electron.app.getPreferredSystemLanguages().find(lang => languages.includes(lang)); if (is.string(findPreferred)) settings.set(`${packagejson.exeName}.LANGUAGE`, findPreferred.toLowerCase()); else if (languages.length > 0 && is.string(languages[0])) settings.set(`${packagejson.exeName}.LANGUAGE`, languages[0]); }; }; const translation = (() => { try { if (settings.has(`${packagejson.exeName}.LANGUAGE`) && is.string(settings.get(`${packagejson.exeName}.LANGUAGE`))) { const value = require(resolve(join(__dirname, "translations", `${settings.get(`${packagejson.exeName}.LANGUAGE`)}.json`))); return is.json(value) == true ? value : {}; } else return {}; } catch (error) { return {}; }; })(); const getTranslation = key => { if (is.string(key)) { key = key.toUpperCase(); const value = key.split(".").reduce((accumulator, currentValue) => accumulator && accumulator[currentValue], translation); return is.string(value) == true ? value : key; } else return undefined; }; const setAdBlock = async () => await electron.dialog.showMessageBox(mainWindow, { title: displayName, message: getTranslation("CONFIRM_ADBLOCK_DIALOG.MESSAGE"), buttons: [getTranslation("CONFIRM_ADBLOCK_DIALOG.ALLOW"), getTranslation("CONFIRM_ADBLOCK_DIALOG.DISALLOW")], defaultId: 1, cancelId: 1, noLink: true, type: "warning" }).then(result => { if (result.response == 0) settings.set(`${packagejson.exeName}.ADBLOCK`, true); else settings.set(`${packagejson.exeName}.ADBLOCK`, false); }); let errorCode = 500; const updateError = () => { mainWindow.webContents.once("did-fail-load", (event, code) => sendError()); mainWindow.webContents.executeJavaScript(`(() => {const title = document.getElementById("title");const code = document.getElementById("code");const redirect = document.getElementById("redirect");const footer = document.getElementById("footer");if (title) title.innerText = "${getTranslation("ERROR.LABEL")}";if (code) code.innerText = "${String(getTranslation("ERROR.STATUS")).replace("#CODE#", errorCode)}";if (redirect) {redirect.href = "${defaultUrl.base}";redirect.innerText = "${getTranslation("ERROR.REDIRECT")}";}if (footer) footer.innerHTML = "${String(getTranslation("FOOTER")).replace("#COPYLEFT#", "©").replace("#TIME#", new Date().getFullYear().toString() == packagejson.releaseYear ? packagejson.releaseYear : `${packagejson.releaseYear} - ${new Date().getFullYear()}`).replace("#NEW_LINE#", "
").replace("#NAME#", `${String(displayName)} Desktop`).replace("#CODED#", "</>").replace("#HEART#", "❤").replace("#AUTHOR#", `${String(author.name)}`).replace("#CONTRIBUTORS_START#", ``).replace("#CONTRIBUTORS_END#", "")}";})();`); mainWindow.setTitle(String(getTranslation("TITLE.ERROR")).replace("#CODE#", errorCode)); discordRichPresence.clr(); discordRichPresence.details = getTranslation("ERROR.LABEL"); discordRichPresence.largeImage = "error"; discordRichPresence.largeImageTooltip = String(getTranslation("ERROR.STATUS")).replace("#CODE#", errorCode); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }; function sendError() { mainWindow.loadFile(resolve(join(__dirname, "error.html"))).then(() => { if (!is.number(errorCode)) errorCode = 500; updateError(); }); }; electron.app.on("second-instance", (event, argv) => { event.preventDefault(); const deepLink = deepLinkToUrl(argv.find(arg => is.deepUrl(arg) == true)); mainWindow.loadURL(deepLink).then(() => mainWindow.webContents.emit("will-navigate", undefined, deepLink)); if (isHidden) { mainWindow.show(); if (!mainWindow.isAlwaysOnTop()) { mainWindow.setAlwaysOnTop(true); mainWindow.setAlwaysOnTop(false); }; }; }); mainWindow.hookWindowMessage(0x0116, () => { mainWindow.setEnabled(false); mainWindow.setEnabled(true); }); mainWindow.setMenuBarVisibility(false); mainWindow.webContents.setWindowOpenHandler(() => { return { action: "deny" }; }); settings.onDidChange("START_UP", newValue => { if (newValue) { if (process.platform == "linux") writeFileSync(resolve(join(electron.app.getPath("appData"), "autostart", `${String(packagejson.name).replace("-", "_")}.desktop`)), `[Desktop Entry]\nType=Application\nName=${String(packagejson.displayName).replace("-", "_")}\nVersion=${electron.app.getVersion()}\nExec=${basename(electron.app.getPath("exe"))}\nIcon=${resolve(join(__dirname, "icon.ico")).replace("app.asar", "app.asar.unpacked")}\nComment=${packagejson.description}\nNoDisplay=false\nStartupNotify=false\nTerminal=false\nX-GNOME-Autostart-enabled=true`); else electron.app.setLoginItemSettings({ openAtLogin: true, enabled: true }); } else { if (process.platform == "linux") unlinkSync(resolve(join(electron.app.getPath("appData"), "autostart", `${String(packagejson.name).replace("-", "_")}.desktop`))); else electron.app.setLoginItemSettings({ openAtLogin: false }); }; }); settings.onDidChange("DISCORD_RICH_PRESENCE", newValue => { if (newValue) mainWindow.webContents.emit("will-navigate", undefined, mainWindow.webContents.getURL()); else discordRichPresence.del(); }); settings.onDidChange("SAVE_WINDOW_SIZE", newValue => { if (newValue) { const size = mainWindow.getBounds(); settings.set(`${packagejson.exeName}.WIDTH`, size.width); settings.set(`${packagejson.exeName}.HEIGHT`, size.height); } else { settings.delete("WIDTH"); settings.delete("HEIGHT"); }; }); settings.onDidChange("LANGUAGE", newValue => mainWindow.setAlwaysOnTop(newValue)); settings.onDidChange("ALWAYS_ON_TOP", newValue => mainWindow.setAlwaysOnTop(newValue)); settings.onDidChange("ADBLOCK", () => mainWindow.reload()); electron.session.defaultSession.webRequest.onBeforeRequest((details, callback) => { if (settings.get(`${packagejson.exeName}.ADBLOCK`)) { if (new URL(details.url).host.startsWith("pagead")) callback({ cancel: true }); else callback({}); } else callback({}); }); mainWindow.on("resized", () => { if (settings.get(`${packagejson.exeName}.SAVE_WINDOW_SIZE`)) { const size = mainWindow.getBounds(); settings.set(`${packagejson.exeName}.WIDTH`, size.width); settings.set(`${packagejson.exeName}.HEIGHT`, size.height); }; }); mainWindow.on("page-title-updated", event => event.preventDefault()); let notWatchEpisode = true; let notWatchScan = true; electron.ipcMain.on("deleteAllHistory", () => profile.set(historyProfile, {})); electron.ipcMain.on("deleteAllWatchlist", () => profile.set(watchlistProfile, {})); electron.ipcMain.on("deleteAllFavorite", () => profile.set(favoriteProfile, {})); electron.ipcMain.on("deleteHistory", (event, url) => { if (is.url(url)) profile.delete(`${historyProfile}.${new URL(url).pathname}`); }); electron.ipcMain.on("deleteWatchlist", (event, url) => { if (is.url(url)) profile.delete(`${watchlistProfile}.${new URL(url).pathname}`); }); electron.ipcMain.on("deleteFavorite", (event, url) => { if (is.url(url)) profile.delete(`${favoriteProfile}.${new URL(url).pathname}`); }); electron.ipcMain.on("episodeChange", (event, data) => { let profileData = {}; const profileName = `${packagejson.exeName}.history.${data.url}`; const profileValue = profile.get(profileName); if (!is.json(profileValue)) { if (is.string(data.type)) profileData.type = data.type == "MOVIE" ? "Film" : data.type; if (is.string(data.title)) profileData.title = data.title; if (is.string(data.image)) profileData.image = data.image; if (is.string(data.language)) profileData.language = data.language; if (is.string(data.episode)) profileData.episode = `Episode ${data.episode}`; if (is.number(data.saved)) profileData.saved = data.saved; profile.set(profileName, profileData); } else { if (is.string(data.episode)) profileData.episode = `Episode ${data.episode}`; if (is.number(data.saved)) profileData.saved = data.saved; profile.set(profileName, Object.assign(profileValue, profileData)); }; if (notWatchEpisode) { notWatchEpisode = false; discordRichPresence.clr(); if (data.type == "MOVIE") { discordRichPresence.details = getTranslation(`ACTIVITY.WATCH.MOVIE.DETAILS`); discordRichPresence.state = getTranslation(`ACTIVITY.WATCH.PAUSED`); let title = String(getTranslation("TITLE.WATCH.MOVIE")); if (is.string(data.title)) title = title.replace("#NAME#", data.title); mainWindow.setTitle(title); } else discordRichPresence.details = String(getTranslation(`ACTIVITY.WATCH.SERIE.DETAILS`)).replace("#STATUS#", getTranslation(`ACTIVITY.WATCH.PAUSED`)); if (is.string(data.image)) discordRichPresence.largeImage = data.image; if (is.string(data.title)) discordRichPresence.largeImageTooltip = data.title; mainWindow.webContents.on("media-started-playing", () => { if (!notWatchEpisode) { if (data.type == "MOVIE") discordRichPresence.state = getTranslation(`ACTIVITY.WATCH.PLAYING`); else discordRichPresence.details = String(getTranslation(`ACTIVITY.WATCH.SERIE.DETAILS`)).replace("#STATUS#", getTranslation(`ACTIVITY.WATCH.PLAYING`)); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }; }); mainWindow.webContents.on("media-paused", () => { if (!notWatchEpisode) { if (data.type == "MOVIE") discordRichPresence.state = getTranslation(`ACTIVITY.WATCH.PAUSED`); else discordRichPresence.details = String(getTranslation(`ACTIVITY.WATCH.SERIE.DETAILS`)).replace("#STATUS#", getTranslation(`ACTIVITY.WATCH.PAUSED`)); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }; }); }; discordRichPresence.buttons = []; if (data.type != "MOVIE") { const season = data.season.split("Saison")[1]; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.WATCH.SERIE.BUTTON"), url: `${defaultUrl.base}${data.url}` }); if (is.string(season)) { data.season = season.trim(); let title = String(getTranslation(`TITLE.WATCH.SERIE.SEASON`)).replace("#SEASON#", data.season); if (is.string(data.episode)) title = title.replace("#EPISODE#", data.episode); if (is.string(data.title)) title = title.replace("#NAME#", data.title); mainWindow.setTitle(title); let state = String(getTranslation(`ACTIVITY.WATCH.SERIE.STATE.SEASON`)).replace("#SEASON#", data.season); if (is.string(data.episode)) state = state.replace("#EPISODE#", data.episode); discordRichPresence.state = state; } else { let title = String(getTranslation(`TITLE.WATCH.SERIE.OTHER`)).replace("#SEASON#", data.season); if (is.string(data.episode)) title = title.replace("#EPISODE#", data.episode); if (is.string(data.title)) title = title.replace("#NAME#", data.title); mainWindow.setTitle(title); let state = String(getTranslation(`ACTIVITY.WATCH.SERIE.STATE.OTHER`)).replace("#SEASON#", data.season); if (is.string(data.episode)) state = state.replace("#EPISODE#", data.episode); discordRichPresence.state = state; }; } else discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.WATCH.MOVIE.BUTTON"), url: `${defaultUrl.base}${data.url}` }); if (is.string(data.language)) { discordRichPresence.smallImage = String(data.language).toLowerCase(); discordRichPresence.smallImageTooltip = getTranslation(`ACTIVITY.${String(data.language).toUpperCase()}`); }; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.INFO.BUTTON"), url: `${defaultUrl.base}${data.urlInfo}` }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }); electron.ipcMain.on("scanChange", (event, data) => { let profileData = {}; const profileName = `${packagejson.exeName}.history.${data.url}`; const profileValue = profile.get(profileName); if (!is.json(profileValue)) { if (is.string(data.type)) profileData.type = data.type == "SCAN" ? "Scans" : type; if (is.string(data.title)) profileData.title = data.title; if (is.string(data.image)) profileData.image = data.image; if (is.string(data.language)) profileData.language = data.language; if (is.string(data.chapter)) profileData.episode = `Chapitre ${data.chapter}`; if (is.number(data.saved)) profileData.saved = data.saved; profile.set(profileName, profileData); } else { if (is.string(data.chapter)) profileData.episode = `Chapitre ${data.chapter}`; if (is.number(data.saved)) profileData.saved = data.saved; profile.set(profileName, Object.assign(profileValue, profileData)); }; if (notWatchScan) { notWatchScan = false; discordRichPresence.clr(); discordRichPresence.details = getTranslation(`ACTIVITY.WATCH.SCAN.DETAILS`); if (is.string(data.image)) discordRichPresence.largeImage = data.image; if (is.string(data.title)) discordRichPresence.largeImageTooltip = data.title; discordRichPresence.buttons.push({ label: getTranslation(`ACTIVITY.WATCH.SCAN.BUTTON`), url: `${defaultUrl.base}${data.url}` }); discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.INFO.BUTTON"), url: `${defaultUrl.base}${data.urlInfo}` }); }; let title = String(getTranslation(`TITLE.WATCH.SCAN`)); if (is.string(data.chapter)) title = title.replace("#CHAPTER#", data.chapter); if (is.string(data.title)) title = title.replace("#NAME#", data.title); mainWindow.setTitle(title); let state = String(getTranslation(`ACTIVITY.WATCH.SCAN.STATE`)); if (is.string(data.chapter)) state = state.replace("#CHAPTER#", data.chapter); discordRichPresence.state = state; if (is.string(data.language)) { discordRichPresence.smallImage = String(data.language).toLowerCase(); discordRichPresence.smallImageTooltip = getTranslation(`ACTIVITY.${String(data.language).toUpperCase()}`); }; if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }); electron.ipcMain.on("watchlistChange", (event, data) => { let profileData = {}; const profileName = `${packagejson.exeName}.watchlist.${data.url}`; if (!is.json(profile.get(profileName))) { if (is.string(data.title)) profileData.title = data.title; if (is.string(data.image)) profileData.image = data.image; profile.set(profileName, profileData); } else profile.delete(profileName); }); electron.ipcMain.on("favoriteChange", (event, data) => { let profileData = {}; const profileName = `${packagejson.exeName}.favorite.${data.url}`; if (!is.json(profile.get(profileName))) { if (is.string(data.title)) profileData.title = data.title; if (is.string(data.image)) profileData.image = data.image; profile.set(profileName, profileData); } else profile.delete(profileName); }); mainWindow.webContents.on("will-navigate", (event, url) => { const validateUrl = new URL(url); const pathName = validateUrl.pathname.endsWith("/") ? validateUrl.pathname.slice(0, validateUrl.pathname.lastIndexOf("/")) : validateUrl.pathname; if (validateUrl.host == new URL(defaultUrl.base).host) { if (!pathName.startsWith("/catalogue/")) { discordRichPresence.clr(); notWatchEpisode = true; notWatchScan = true; mainWindow.webContents.removeAllListeners("media-started-playing"); mainWindow.webContents.removeAllListeners("media-paused"); } else { let pathName = validateUrl.pathname.endsWith("/") ? validateUrl.pathname.slice(0, validateUrl.pathname.lastIndexOf("/")) : validateUrl.pathname; pathName = pathName.split("/catalogue/")[1]; if (!pathName.includes("/")) mainWindow.once("page-title-updated", (event, originalTitle) => { event.preventDefault(); discordRichPresence.clr(); notWatchEpisode = true; notWatchScan = true; mainWindow.webContents.removeAllListeners("media-started-playing"); mainWindow.webContents.removeAllListeners("media-paused"); const fetchedTitle = originalTitle.split("|")[0].trim(); let title = getTranslation("TITLE.INFO"); if (is.string(fetchedTitle)) title = title.replace("#NAME#", fetchedTitle); mainWindow.setTitle(title); discordRichPresence.details = getTranslation(`ACTIVITY.INFO.DETAILS`); discordRichPresence.largeImage = `https://cdn.statically.io/gh/Anime-Sama/IMG/img/contenu/${validateUrl.pathname.endsWith(`/`) ? validateUrl.pathname.slice(0, validateUrl.pathname.lastIndexOf(`/`)).split("/").pop() : validateUrl.pathname.split("/").pop()}.jpg`; if (is.string(fetchedTitle)) discordRichPresence.largeImageTooltip = fetchedTitle; discordRichPresence.buttons.push({ label: getTranslation(`ACTIVITY.INFO.BUTTON`), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }); }; if (pathName.length <= 0) { mainWindow.setTitle(getTranslation("TITLE.HOME")); discordRichPresence.details = getTranslation("ACTIVITY.HOME.DETAILS"); discordRichPresence.largeImage = "logo"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.HOME.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); } else if (pathName == "/catalogue") { mainWindow.setTitle(getTranslation("TITLE.CATALOG")); discordRichPresence.details = getTranslation("ACTIVITY.CATALOG.DETAILS"); discordRichPresence.largeImage = "catalog"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.CATALOG.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); } else if (pathName == "/planning") { mainWindow.setTitle(getTranslation("TITLE.PLANNING")); discordRichPresence.details = getTranslation("ACTIVITY.PLANNING.DETAILS"); discordRichPresence.largeImage = "planning"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.PLANNING.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); } else if (pathName == "/aide") { mainWindow.setTitle(getTranslation("TITLE.HELP")); discordRichPresence.details = getTranslation("ACTIVITY.HELP.DETAILS"); discordRichPresence.largeImage = "help"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.HELP.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); } else if (pathName == "/profil") { mainWindow.setTitle(getTranslation("TITLE.PROFILE")); discordRichPresence.details = getTranslation("ACTIVITY.PROFILE.DETAILS"); discordRichPresence.largeImage = "profile"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.PROFILE.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); } else if (pathName == "/contact") { mainWindow.setTitle(getTranslation("TITLE.CONTACT")); discordRichPresence.details = getTranslation("ACTIVITY.CONTACT.DETAILS"); discordRichPresence.largeImage = "contact"; discordRichPresence.buttons.push({ label: getTranslation("ACTIVITY.CONTACT.BUTTON"), url: url }); if (settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) discordRichPresence.set(); }; } else if (validateUrl.protocol != "file:" || !url.endsWith("error.html")) { event.preventDefault(); electron.shell.openExternal(url); }; }); function init(url) { splashWindow.removeAllListeners("closed"); if (!splashWindow.isDestroyed()) { splashWindow.once("closed", () => init(url)); return splashWindow.close(); } else { const isUrl = is.url(url); if (settings.get(`${packagejson.exeName}.ALWAYS_ON_TOP`)) mainWindow.setAlwaysOnTop(true); if (isUrl) mainWindow.webContents.emit("will-navigate", undefined, url); const tray = new electron.Tray(icon); mainWindow.on("close", event => { if (settings.get(`${packagejson.exeName}.MINIMIZE_TO_TRAY`)) { event.preventDefault(); if (!isHidden) mainWindow.hide(); return false; } else { if (!tray.isDestroyed()) tray.destroy(); return true; }; }); const trayMenu = electron.Menu.buildFromTemplate([{ id: "title", enabled: false, label: displayName, icon: electron.nativeImage.createFromPath(icon).resize({ width: 16 }) }, { type: "separator" }, { id: "import", label: getTranslation("TRAY.IMPORT"), submenu: [{ id: "profileImport", label: getTranslation("TRAY.PROFILE"), click: async () => await electron.dialog.showOpenDialog(mainWindow, { defaultPath: profile.path, filters: [{ name: "JSON", extensions: ["json"] }], properties: ["openFile"] }).then(result => { if (!result.canceled && is.string(result.filePaths[0])) { if (new URL(mainWindow.webContents.getURL()).host == new URL(defaultUrl.base).host) { const importedProfile = require(result.filePaths[0]); if (is.json(importedProfile)) { const all = importedProfile[packagejson.exeName]; if (is.json(all)) { const history = all["history"]; const watchlist = all["watchlist"]; const favorite = all["favorite"]; if (is.json(history)) { for (const [key, value] of Object.entries(history).filter(([key, value]) => is.json(value) == true)) { mainWindow.webContents.send("importHistory", `${defaultUrl.base}${key}`, value["type"], value["title"], value["image"], value["language"], value["episode"], value["saved"]); }; profile.set(historyProfile, Object.assign(profile.get(historyProfile), history)); }; if (is.json(watchlist)) { for (const [key, value] of Object.entries(watchlist).filter(([key, value]) => is.json(value) == true)) { mainWindow.webContents.send("importWatchlist", `${defaultUrl.base}${key}`, value["title"], value["image"]); }; profile.set(watchlistProfile, Object.assign(profile.get(watchlistProfile), watchlist)); }; if (is.json(favorite)) { for (const [key, value] of Object.entries(favorite).filter(([key, value]) => is.json(value) == true)) { mainWindow.webContents.send("importFavorite", `${defaultUrl.base}${key}`, value["title"], value["image"]); }; profile.set(favoriteProfile, Object.assign(profile.get(favoriteProfile), favorite)); }; mainWindow.webContents.reload(); }; }; }; }; }) }, { id: "settingsImport", label: getTranslation("TRAY.SETTINGS.LABEL"), click: async () => await electron.dialog.showOpenDialog(mainWindow, { defaultPath: settings.path, filters: [{ name: "JSON", extensions: ["json"] }], properties: ["openFile"] }).then(async result => { if (!result.canceled && is.string(result.filePaths[0])) { const importedSettings = require(result.filePaths[0]); if (is.json(importedSettings)) { if (is.json(importedSettings[packagejson.exeName])) { let restartLanguage = [false]; for (let [name, value] of Object.entries(importedSettings[packagejson.exeName])) { name = name.toUpperCase(); if (name == "LANGUAGE" && is.string(value) && settings.get(`${packagejson.exeName}.${name}`) != value) restartLanguage = [true, value]; else if (name == "WIDTH" && is.number(value) && value <= size.width && settings.get(`${packagejson.exeName}.WIDTH`) != value) { settings.set(`${packagejson.exeName}.WIDTH`, value); mainWindow.setSize(value, settings.get(`${packagejson.exeName}.HEIGHT`)); mainWindow.center(); } else if (name == "HEIGHT" && is.number(value) && value <= size.height && settings.get(`${packagejson.exeName}.HEIGHT`) != value) { settings.set(`${packagejson.exeName}.HEIGHT`, value); mainWindow.setSize(settings.get(`${packagejson.exeName}.WIDTH`), value); mainWindow.center(); } else if (typeof value == "boolean" && settings.get(`${packagejson.exeName}.${name}`) != value) { if (name == "ADBLOCK") await setAdBlock(); else settings.set(`${packagejson.exeName}.${name}`, value); }; }; if (restartLanguage[0]) return await electron.dialog.showMessageBox(mainWindow, { title: displayName, message: getTranslation("CONFIRM_LANGUAGE_DIALOG.MESSAGE"), buttons: [getTranslation("CONFIRM_LANGUAGE_DIALOG.ALLOW"), getTranslation("CONFIRM_LANGUAGE_DIALOG.DISALLOW")], defaultId: 1, cancelId: 1, noLink: true, type: "warning" }).then(result => { if (result.response == 0) { settings.set(`${packagejson.exeName}.LANGUAGE`, restartLanguage[1]); electron.app.relaunch(); mainWindow.removeAllListeners("close"); if (!tray.isDestroyed()) tray.destroy(); return electron.app.quit(); }; }); }; }; }; }) }] }, { id: "export", label: getTranslation("TRAY.EXPORT"), submenu: [{ id: "profileExport", label: getTranslation("TRAY.PROFILE"), click: async () => await electron.dialog.showSaveDialog(mainWindow, { defaultPath: resolve(join(electron.app.getPath("home"), "profile.json")) }).then(result => { if (is.string(result.filePath)) writeFileSync(result.filePath, JSON.stringify(profile.store)) }) }, { id: "settingsExport", label: getTranslation("TRAY.SETTINGS.LABEL"), click: async () => await electron.dialog.showSaveDialog(mainWindow, { defaultPath: resolve(join(electron.app.getPath("home"), "settings.json")) }).then(result => { if (is.string(result.filePath)) writeFileSync(result.filePath, JSON.stringify(settings.store)); }) }] }, { type: "separator" }, { id: "actions", label: getTranslation("TRAY.ACTIONS.LABEL"), submenu: [{ id: "back", label: getTranslation("TRAY.ACTIONS.BACK"), enabled: mainWindow.webContents.canGoBack(), click: () => { mainWindow.webContents.once("did-navigate", (event, url) => mainWindow.webContents.emit("will-navigate", undefined, url)); mainWindow.webContents.goBack(); } }, { id: "forward", label: getTranslation("TRAY.ACTIONS.FORWARD"), enabled: mainWindow.webContents.canGoForward(), click: () => { mainWindow.webContents.once("did-navigate", (event, url) => mainWindow.webContents.emit("will-navigate", undefined, url)); mainWindow.webContents.goForward(); } }, { id: "restore", label: getTranslation("TRAY.ACTIONS.RESTORE"), click: () => mainWindow.show() }, { id: "reduce", label: getTranslation("TRAY.ACTIONS.REDUCE"), click: () => mainWindow.hide() }, { id: "refresh", label: getTranslation("TRAY.ACTIONS.REFRESH"), click: () => mainWindow.reload() }, { id: "forceRefresh", label: getTranslation("TRAY.ACTIONS.FORCE_REFRESH"), click: () => mainWindow.webContents.reloadIgnoringCache() }, { id: "center", label: getTranslation("TRAY.ACTIONS.CENTER"), click: () => mainWindow.center() }] }, { id: "settings", label: getTranslation("TRAY.SETTINGS.LABEL"), submenu: [{ id: "languages", label: getTranslation("TRAY.SETTINGS.LANGUAGES"), submenu: [] }, { id: "start_up", label: getTranslation("TRAY.SETTINGS.START_UP"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.START_UP`) == true, click: () => settings.set(`${packagejson.exeName}.START_UP`, !settings.get(`${packagejson.exeName}.START_UP`)) }, { id: "start_hidden", label: getTranslation("TRAY.SETTINGS.START_HIDDEN"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.START_FULL_SCREEN`) == true ? false : settings.get(`${packagejson.exeName}.START_HIDDEN`) == true, click: () => settings.set(`${packagejson.exeName}.START_HIDDEN`, !settings.get(`${packagejson.exeName}.START_HIDDEN`)) }, { id: "start_full_screen", label: getTranslation("TRAY.SETTINGS.START_FULL_SCREEN"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.START_HIDDEN`) == true ? false : settings.get(`${packagejson.exeName}.START_FULL_SCREEN`) == true, click: () => settings.set(`${packagejson.exeName}.START_FULL_SCREEN`, !settings.get(`${packagejson.exeName}.START_FULL_SCREEN`)) }, { id: "minimize_to_tray", label: getTranslation("TRAY.SETTINGS.MINIMIZE_TO_TRAY"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.MINIMIZE_TO_TRAY`) == true, click: () => settings.set(`${packagejson.exeName}.MINIMIZE_TO_TRAY`, !settings.get(`${packagejson.exeName}.MINIMIZE_TO_TRAY`)) }, { id: "save_window_size", label: getTranslation("TRAY.SETTINGS.SAVE_WINDOW_SIZE"), type: "checkbox", enabled: process.platform != "linux", checked: settings.get(`${packagejson.exeName}.SAVE_WINDOW_SIZE`) == true, click: () => settings.set(`${packagejson.exeName}.SAVE_WINDOW_SIZE`, !settings.get(`${packagejson.exeName}.SAVE_WINDOW_SIZE`)) }, { id: "always_on_top", label: getTranslation("TRAY.SETTINGS.ALWAYS_ON_TOP"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.ALWAYS_ON_TOP`) == true, click: () => settings.set(`${packagejson.exeName}.ALWAYS_ON_TOP`, !settings.get(`${packagejson.exeName}.ALWAYS_ON_TOP`)) }, { id: "adblock", label: getTranslation("TRAY.SETTINGS.ADBLOCK"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.ADBLOCK`) == true, click: async () => await setAdBlock() }, { id: "discord_rich_presence", label: getTranslation("TRAY.SETTINGS.DISCORD_RICH_PRESENCE"), type: "checkbox", checked: settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`) == true, click: () => settings.set(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`, !settings.get(`${packagejson.exeName}.DISCORD_RICH_PRESENCE`)) }] }, { id: "advanced", label: getTranslation("TRAY.ADVANCED.LABEL"), submenu: [{ id: "reload", label: getTranslation("TRAY.ADVANCED.RELOAD"), click: () => mainWindow.loadURL(defaultUrl.base).then(() => mainWindow.webContents.emit("will-navigate", undefined, defaultUrl.base)).catch((event, code) => { errorCode = code; sendError(); }) }, { id: "restart", label: getTranslation("TRAY.ADVANCED.RESTART"), click: async () => await electron.dialog.showMessageBox(mainWindow, { title: displayName, message: getTranslation("RESTART_DIALOG.MESSAGE"), buttons: [getTranslation("RESTART_DIALOG.ALLOW"), getTranslation("RESTART_DIALOG.DISALLOW")], defaultId: 1, cancelId: 1, noLink: true, type: "warning" }).then(result => { if (result.response == 0) { electron.app.relaunch(); mainWindow.removeAllListeners("close"); if (!tray.isDestroyed()) tray.destroy(); return electron.app.quit(); }; }) }, { id: "resetData", label: getTranslation("TRAY.ADVANCED.RESET_DATA"), click: async () => await electron.dialog.showMessageBox(mainWindow, { title: displayName, message: getTranslation("CHANGE_RESTART_DIALOG.MESSAGE"), buttons: [getTranslation("CHANGE_RESTART_DIALOG.ALLOW"), getTranslation("CHANGE_RESTART_DIALOG.DISALLOW")], defaultId: 1, cancelId: 1, noLink: true, type: "warning" }).then(async result => { if (result.response == 0) { const defaultSession = electron.session.defaultSession; settings.clear(); profile.clear(); await defaultSession.clearAuthCache(); await defaultSession.clearHostResolverCache(); await defaultSession.clearStorageData(); await defaultSession.clearCache(); electron.app.relaunch(); mainWindow.removeAllListeners("close"); if (!tray.isDestroyed()) tray.destroy(); return electron.app.quit(); }; }) }, { id: "forceClose", label: getTranslation("TRAY.ADVANCED.FORCE_CLOSE"), click: () => electron.app.exit() }] }, { type: "separator" }, { id: "close", label: getTranslation("TRAY.CLOSE"), click: () => { mainWindow.removeAllListeners("close"); if (!tray.isDestroyed()) tray.destroy(); return electron.app.quit(); } }]); const profileImport = trayMenu.getMenuItemById("profileImport"); const profileExport = trayMenu.getMenuItemById("profileExport"); const languagesTray = trayMenu.getMenuItemById("languages"); const startHidden = trayMenu.getMenuItemById("start_hidden"); const startFullScreen = trayMenu.getMenuItemById("start_full_screen"); const back = trayMenu.getMenuItemById("back"); const forward = trayMenu.getMenuItemById("forward"); const restore = trayMenu.getMenuItemById("restore"); const reduce = trayMenu.getMenuItemById("reduce"); const getAnotherTranslation = (key, lang) => { if (is.string(lang) && is.string(key)) { key = key.toUpperCase(); const value = key.split(".").reduce((accumulator, currentValue) => accumulator && accumulator[currentValue], (() => { try { const value = require(resolve(join(__dirname, "translations", `${lang}.json`))); return is.json(value) == true ? value : {}; } catch (error) { return {}; }; })()); return is.string(value) == true ? value : `${lang}.${key}`; } else return undefined; }; for (const lang of languages) { languagesTray.submenu.append(new electron.MenuItem({ id: lang, type: "checkbox", label: lang == settings.get(`${packagejson.exeName}.LANGUAGE`) ? getTranslation("LANGUAGE") : getAnotherTranslation("LANGUAGE", lang), icon: resolve(join(__dirname, "translations", `${lang}.png`)), checked: lang == settings.get(`${packagejson.exeName}.LANGUAGE`), click: async () => await electron.dialog.showMessageBox(mainWindow, { title: displayName, message: getTranslation("CONFIRM_LANGUAGE_DIALOG.MESSAGE"), buttons: [getTranslation("CONFIRM_LANGUAGE_DIALOG.ALLOW"), getTranslation("CONFIRM_LANGUAGE_DIALOG.DISALLOW")], defaultId: 1, cancelId: 1, noLink: true, type: "warning" }).then(result => { if (result.response == 0) { settings.set(`${packagejson.exeName}.LANGUAGE`, lang); electron.app.relaunch(); mainWindow.removeAllListeners("close"); if (!tray.isDestroyed()) tray.destroy(); return electron.app.quit(); }; }) })); }; if (!electron.globalShortcut.isRegistered("CommandOrControl+Shift+Z")) electron.globalShortcut.register("CommandOrControl+Shift+Z", () => { if (back && mainWindow.isFocused()) back.click(); }); if (!electron.globalShortcut.isRegistered("CommandOrControl+Shift+Y")) electron.globalShortcut.register("CommandOrControl+Shift+Y", () => { if (forward && mainWindow.isFocused()) forward.click(); }); if (startHidden && startFullScreen) { settings.onDidChange("START_HIDDEN", newValue => { if (newValue) { startHidden.checked = true; settings.set(`${packagejson.exeName}.START_FULL_SCREEN`, false); } else startHidden.checked = false; }); settings.onDidChange("START_FULL_SCREEN", newValue => { if (newValue) { startFullScreen.checked = true; settings.set(`${packagejson.exeName}.START_HIDDEN`, false); } else startFullScreen.checked = false; }); }; if (restore && reduce) { if (isHidden) { restore.enabled = true; reduce.enabled = false; } else { restore.enabled = false; reduce.enabled = true; }; }; for (const event of ["show", "restore"]) { mainWindow.on(event, () => { isHidden = false; if (restore && reduce) { restore.enabled = false; reduce.enabled = true; }; }); }; for (const event of ["hide", "minimize"]) { mainWindow.on(event, () => { isHidden = true; if (restore && reduce) { restore.enabled = true; reduce.enabled = false; }; }); }; for (const [traySetting, settingName] of [ [trayMenu.getMenuItemById("start_up"), "START_UP"], [trayMenu.getMenuItemById("minimize_to_tray"), "MINIMIZE_TO_TRAY"], [trayMenu.getMenuItemById("save_window_size"), "SAVE_WINDOW_SIZE"], [trayMenu.getMenuItemById("always_on_top"), "ALWAYS_ON_TOP"], [trayMenu.getMenuItemById("discord_rich_presence"), "DISCORD_RICH_PRESENCE"] ]) { if (traySetting) settings.onDidChange(`${packagejson.exeName}.${settingName}`, newValue => traySetting.checked = newValue); }; tray.on("double-click", () => { if (isHidden) { mainWindow.show(); if (!mainWindow.isAlwaysOnTop()) { mainWindow.setAlwaysOnTop(true); mainWindow.setAlwaysOnTop(false); }; } else return mainWindow.hide(); }); tray.setToolTip(displayName); tray.setContextMenu(trayMenu); const udpateStyle = () => { mainWindow.webContents.insertCSS("::-webkit-scrollbar {display: none;}div ::-webkit-scrollbar {display: block;}.mt-auto p a {color: #808080;text-decoration: none;transition-property: all;transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);transition-duration: 200ms;}.mt-auto p a:hover {color: #0EA5E9;}footer span a {color: #808080;text-decoration: none;transition-property: all;transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);transition-duration: 200ms;}footer span a:hover {color: #0EA5E9;}"); mainWindow.webContents.executeJavaScript(`document.querySelectorAll("a").forEach(item => {item.removeAttribute("target");item.setAttribute("draggable", "false");});let replaceNavFooter = document.querySelector(".mt-auto p");if (replaceNavFooter) {replaceNavFooter.className = "font-semibold";replaceNavFooter.style.cssText = "color: white;text-align: center;";replaceNavFooter.innerHTML = "${String(getTranslation("FOOTER")).replace("#COPYLEFT#", "©").replace("#TIME#", new Date().getFullYear().toString() == packagejson.releaseYear ? packagejson.releaseYear : `${packagejson.releaseYear} - ${new Date().getFullYear()}`).replace("#NEW_LINE#", "
").replace("#NAME#", `${String(displayName)} Desktop`).replace("#CODED#", "</>").replace("#HEART#", "❤").replace("#AUTHOR#", `${String(author.name)}`).replace("#CONTRIBUTORS_START#", ``).replace("#CONTRIBUTORS_END#", "")}";};const replaceFooter = document.querySelector("footer span");if (replaceFooter) {replaceFooter.className = "font-semibold";replaceFooter.style.cssText = "color: white;text-align: center;";replaceFooter.innerHTML = "${String(getTranslation("FOOTER")).replace("#COPYLEFT#", "©").replace("#TIME#", new Date().getFullYear().toString() == packagejson.releaseYear ? packagejson.releaseYear : `${packagejson.releaseYear} - ${new Date().getFullYear()}`).replace("#NEW_LINE#", "
").replace("#NAME#", `${String(displayName)} Desktop`).replace("#CODED#", "</>").replace("#HEART#", "❤").replace("#AUTHOR#", `${String(author.name)}`).replace("#CONTRIBUTORS_START#", ``).replace("#CONTRIBUTORS_END#", "")}";};`); }; udpateStyle(); mainWindow.webContents.on("did-navigate", (event, url, httpResponseCode) => { const validateUrl = new URL(url); if (back) back.enabled = mainWindow.webContents.canGoBack(); if (forward) forward.enabled = mainWindow.webContents.canGoForward(); if (httpResponseCode != 200) { errorCode = httpResponseCode; event.preventDefault(); sendError(); } else if (validateUrl.protocol == "file:" && url.endsWith("error.html")) updateError(); else if (validateUrl.host == new URL(defaultUrl.base).host) { if (profileImport) profileImport.enabled = true; if (profileExport) profileExport.enabled = true; udpateStyle(); const pathName = validateUrl.pathname.endsWith("/") ? validateUrl.pathname.slice(0, validateUrl.pathname.lastIndexOf("/")) : validateUrl.pathname; if (pathName == "/catalogue") mainWindow.webContents.executeJavaScript("document.querySelectorAll(\".form-checkbox\").forEach(element => {if (element.checked) genresChecked.push(element.value);else genresChecked.remove(element.value);});if (genresChecked.length > 0) {$('#nav_pages').hide();$.ajax({url:\"listing_all.php\",method:\"post\",data:{query:undefined},success:function(data){$('#result_catalogue').html(data);const buttonFilter = document.getElementById(\"btnTriList\")if (buttonFilter) buttonFilter.click();}});};"); } else { if (profileImport) profileImport.enabled = false; if (profileExport) profileExport.enabled = false; }; }); if (!isHidden) { mainWindow.show(); if (!mainWindow.isAlwaysOnTop()) { mainWindow.setAlwaysOnTop(true); mainWindow.setAlwaysOnTop(false); }; }; }; }; return mainWindow.loadURL(defaultUrl.full).then(() => init(defaultUrl.full)).catch((event, code) => { errorCode = code; init(); return sendError(); }); }; electron.app.on("activate", () => { if (electron.BrowserWindow.getAllWindows().length <= 0) return createWindow(); }); return createWindow(); }); }); } else return electron.app.quit();