mirror of
https://github.com/A-Star100/simpliplay-desktop.git
synced 2025-09-18 06:39:44 +00:00
Added new add-on system
Addons can do anything, from changing the look and feel of the app, adding new features, and even add references to your favorite characters!
This commit is contained in:
parent
d91778b7ea
commit
416e9e7bac
@ -207,7 +207,94 @@ if (appMenu && !appMenu.submenu.items.some(item => item.label === 'Check for Upd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu.setApplicationMenu(menu);
|
const loadedAddons = new Map(); // key: addon filepath, value: MenuItem
|
||||||
|
|
||||||
|
const newMenuItems = menu ? [...menu.items] : [];
|
||||||
|
|
||||||
|
let addonsMenu;
|
||||||
|
|
||||||
|
// Check if Add-ons menu already exists
|
||||||
|
const existingAddonsMenuItem = newMenuItems.find(item => item.label === 'Add-ons');
|
||||||
|
|
||||||
|
if (existingAddonsMenuItem) {
|
||||||
|
addonsMenu = existingAddonsMenuItem.submenu;
|
||||||
|
} else {
|
||||||
|
addonsMenu = new Menu();
|
||||||
|
|
||||||
|
// "Load Add-on" menu item
|
||||||
|
addonsMenu.append(new MenuItem({
|
||||||
|
label: 'Load Add-on',
|
||||||
|
accelerator: 'CommandOrControl+Shift+A',
|
||||||
|
click: async () => {
|
||||||
|
const result = await dialog.showOpenDialog(mainWindow, {
|
||||||
|
title: 'Load Add-on',
|
||||||
|
filters: [{ name: 'JavaScript Files', extensions: ['simpliplay'] }],
|
||||||
|
properties: ['openFile'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.canceled && result.filePaths.length > 0) {
|
||||||
|
const filePath = result.filePaths[0];
|
||||||
|
const fileName = path.basename(filePath);
|
||||||
|
const fileURL = pathToFileURL(filePath).href;
|
||||||
|
|
||||||
|
// Check if an addon with the same filename is already loaded
|
||||||
|
const alreadyLoaded = [...loadedAddons.keys()].some(
|
||||||
|
loadedPath => path.basename(loadedPath) === fileName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (alreadyLoaded) {
|
||||||
|
await dialog.showMessageBox(mainWindow, {
|
||||||
|
type: 'error',
|
||||||
|
title: 'Add-on Load Error',
|
||||||
|
message: `An add-on named "${fileName}" is already loaded.`,
|
||||||
|
buttons: ['OK']
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loadedAddons.has(filePath)) {
|
||||||
|
mainWindow.webContents.send('load-addon', fileURL);
|
||||||
|
|
||||||
|
const addonMenuItem = new MenuItem({
|
||||||
|
label: fileName,
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: true,
|
||||||
|
click: (menuItem) => {
|
||||||
|
if (menuItem.checked) {
|
||||||
|
mainWindow.webContents.send('load-addon', fileURL);
|
||||||
|
} else {
|
||||||
|
mainWindow.webContents.send('unload-addon', fileURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!addonsMenu.items.some(item => item.type === 'separator')) {
|
||||||
|
addonsMenu.append(new MenuItem({ type: 'separator' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
addonsMenu.append(addonMenuItem);
|
||||||
|
loadedAddons.set(filePath, addonMenuItem);
|
||||||
|
|
||||||
|
// Rebuild the menu after adding the new addon item
|
||||||
|
Menu.setApplicationMenu(Menu.buildFromTemplate(newMenuItems));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Add the Add-ons menu only once here:
|
||||||
|
newMenuItems.push(new MenuItem({ label: 'Add-ons', submenu: addonsMenu }));
|
||||||
|
|
||||||
|
// Set the application menu after adding Add-ons menu
|
||||||
|
Menu.setApplicationMenu(Menu.buildFromTemplate(newMenuItems));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Re-apply the full menu if you add newMenuItems outside of the if above
|
||||||
|
//Menu.setApplicationMenu(Menu.buildFromTemplate(newMenuItems));
|
||||||
|
|
||||||
|
|
||||||
|
//Menu.setApplicationMenu(menu);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setupShortcuts = () => {
|
const setupShortcuts = () => {
|
||||||
@ -334,4 +421,4 @@ app.on("window-all-closed", () => {
|
|||||||
|
|
||||||
app.on("will-quit", () => {
|
app.on("will-quit", () => {
|
||||||
globalShortcut.unregisterAll();
|
globalShortcut.unregisterAll();
|
||||||
});
|
});
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "SimpliPlay",
|
"name": "SimpliPlay",
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"description": "SimpliPlay - The mission to make media playback accessible on every device, anywhere, anytime.",
|
"description": "SimpliPlay - The mission to make media playback accessible on every device, anywhere, anytime.",
|
||||||
"main": "./main.js",
|
"main": "./main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -2,9 +2,9 @@ const { contextBridge, ipcRenderer } = require("electron");
|
|||||||
|
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
contextBridge.exposeInMainWorld("electron", {
|
||||||
receive: (channel, callback) => {
|
receive: (channel, callback) => {
|
||||||
const validChannels = ["play-media"]; // ✅ Only allow specific, safe channels
|
const validChannels = ["play-media", "load-addon", "unload-addon"];
|
||||||
if (validChannels.includes(channel)) {
|
if (validChannels.includes(channel)) {
|
||||||
ipcRenderer.removeAllListeners(channel); // ✅ Prevent duplicate listeners
|
ipcRenderer.removeAllListeners(channel); // Prevent multiple callbacks
|
||||||
ipcRenderer.on(channel, (_event, ...args) => callback(...args));
|
ipcRenderer.on(channel, (_event, ...args) => callback(...args));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -34,8 +34,37 @@ function isSafeURL(fileURL) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load addon script dynamically
|
||||||
|
function loadAddon(fileURL) {
|
||||||
|
// Avoid duplicate scripts
|
||||||
|
if (document.querySelector(`script[data-addon="${fileURL}"]`)) return;
|
||||||
|
|
||||||
// ✅ Listen for "play-media" event from main process securely
|
const script = document.createElement('script');
|
||||||
|
script.src = fileURL;
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.async = false; // optional, depends on your needs
|
||||||
|
script.setAttribute('data-addon', fileURL);
|
||||||
|
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
console.log(`addon loaded: ${fileURL}`)
|
||||||
|
alert("Addon loaded successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload addon script by removing the <script> tag
|
||||||
|
function unloadAddon(fileURL) {
|
||||||
|
const script = document.querySelector(`script[data-addon="${fileURL}"]`);
|
||||||
|
if (script) {
|
||||||
|
script.remove();
|
||||||
|
console.log(`addon unloaded: ${fileURL}`)
|
||||||
|
alert("Addon unloaded successfully");
|
||||||
|
} else {
|
||||||
|
console.warn(`No addon script found for: ${fileURL}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ✅ Listen for events from main process securely
|
||||||
window.electron.receive("play-media", (fileURL) => {
|
window.electron.receive("play-media", (fileURL) => {
|
||||||
if (isSafeURL(fileURL)) {
|
if (isSafeURL(fileURL)) {
|
||||||
clearSubtitles()
|
clearSubtitles()
|
||||||
@ -52,3 +81,19 @@ window.electron.receive("play-media", (fileURL) => {
|
|||||||
console.warn("Blocked unsafe media URL:", fileURL);
|
console.warn("Blocked unsafe media URL:", fileURL);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Listen for load-addon message
|
||||||
|
window.electron.receive("load-addon", (fileURL) => {
|
||||||
|
if (isSafeURL(fileURL)) {
|
||||||
|
loadAddon(fileURL);
|
||||||
|
} else {
|
||||||
|
console.warn("Blocked unsafe script URL:", fileURL);
|
||||||
|
alert("There was an issue loading your addon: it may be unsafe");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for unload-addon message
|
||||||
|
window.electron.receive("unload-addon", (fileURL) => {
|
||||||
|
unloadAddon(fileURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user