diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index d224beb8..c1011241 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -201,7 +201,6 @@ "action.unfollow": "Unfollow", "action.unfollow.success": "Unfollowed", "action.unfollow.error": "Error Unfollowing", - "action.relaunch.confirm": "Do you want to relaunch Cider?", "action.playNext": "Play Next", "action.playLater": "Play Later", "action.startRadio": "Start Radio", @@ -316,8 +315,6 @@ "settings.option.visual.hardwareAcceleration.description": "Requires relaunch", "settings.header.visual.hardwareAcceleration.default": "Default", "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", - "settings.option.visual.transparent": "Transparent frame", - "settings.option.visual.transparent.description": "Transparent frame (needs Theme Support , requires relaunch)", "settings.header.visual.theme": "Theme", "settings.option.visual.theme.github.download": "Install from GitHub URL", "settings.option.visual.theme.github.explore": "Explore GitHub Themes", @@ -326,6 +323,15 @@ "settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install", "settings.notyf.visual.theme.install.success": "Theme installed successfully", "settings.notyf.visual.theme.install.error": "Theme installation failed", + "settings.header.visual.plugin": "Plugin", + "settings.option.visual.plugin.github.download": "Install from GitHub URL", + "settings.option.visual.plugin.github.explore": "Explore GitHub Plugins", + "settings.header.visual.plugin.github.page": "Plugins from GitHub", + "settings.option.visual.plugin.github.install.confirm": "Are you sure you want to install {{ repo }}?", + "settings.prompt.visual.plugin.github.URL": "Enter the URL of the plugin you want to install", + "settings.prompt.visual.plugin.github.success": "Plugin installed successfully, Press OK to relaunch Cider", + "settings.notyf.visual.plugin.install.success": "Plugin installed successfully", + "settings.notyf.visual.plugin.install.error": "Plugin installation failed", "settings.option.visual.theme.default": "Cider", "settings.option.visual.theme.dark": "Dark", "settings.option.visual.showPersonalInfo": "Show Personal Info", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index 7e402929..c1011241 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -323,6 +323,15 @@ "settings.prompt.visual.theme.github.URL": "Enter the URL of the theme you want to install", "settings.notyf.visual.theme.install.success": "Theme installed successfully", "settings.notyf.visual.theme.install.error": "Theme installation failed", + "settings.header.visual.plugin": "Plugin", + "settings.option.visual.plugin.github.download": "Install from GitHub URL", + "settings.option.visual.plugin.github.explore": "Explore GitHub Plugins", + "settings.header.visual.plugin.github.page": "Plugins from GitHub", + "settings.option.visual.plugin.github.install.confirm": "Are you sure you want to install {{ repo }}?", + "settings.prompt.visual.plugin.github.URL": "Enter the URL of the plugin you want to install", + "settings.prompt.visual.plugin.github.success": "Plugin installed successfully, Press OK to relaunch Cider", + "settings.notyf.visual.plugin.install.success": "Plugin installed successfully", + "settings.notyf.visual.plugin.install.error": "Plugin installation failed", "settings.option.visual.theme.default": "Cider", "settings.option.visual.theme.dark": "Dark", "settings.option.visual.showPersonalInfo": "Show Personal Info", diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index b9dd9734..48936ec7 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -12,6 +12,7 @@ import fetch from 'electron-fetch' import {wsapi} from "./wsapi"; import {AppImageUpdater, NsisUpdater} from "electron-updater"; import {utils} from './utils'; +import {Plugins} from "./plugins"; const fileWatcher = require('chokidar'); const AdmZip = require("adm-zip"); @@ -465,7 +466,10 @@ export class BrowserWindow { }); app.get("/plugins/:plugin/*", (req: {params: {plugin: string, 0: string}}, res) => { - const plugin = req.params.plugin; + let plugin = req.params.plugin; + if(Plugins.getPluginFromMap(plugin)) { + plugin = Plugins.getPluginFromMap(plugin) + } const file = req.params[0]; const pluginPath = join(utils.getPath('plugins'), plugin); console.log(pluginPath) @@ -596,6 +600,53 @@ export class BrowserWindow { event.returnValue = process.platform; }); + ipcMain.handle("get-github-plugin", async (event, url) => { + const returnVal = { + success: true, + theme: null, + message: "" + } + try { + if (!existsSync(utils.getPath("plugins"))) { + mkdirSync(utils.getPath("plugins")); + } + if (url.endsWith("/")) url = url.slice(0, -1); + let response = await fetch( + `${url}/archive/refs/heads/main.zip` + ); + let repo = url.split("/").slice(-2).join("/"); + let apiRepo = await fetch( + `https://api.github.com/repos/${repo}` + ).then((res) => res.json()); + console.debug(`REPO ID: ${apiRepo.id}`); + // extract the files from the first folder in the zip response + let zip = new AdmZip(await response.buffer()); + let entry = zip.getEntries()[0]; + if (!existsSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id))) { + mkdirSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id)); + } + console.log(join(utils.getPath("plugins"), "gh_" + apiRepo.id)) + zip.extractEntryTo(entry, join(utils.getPath("plugins"), "gh_" + apiRepo.id), false, true); + let commit = await fetch( + `https://api.github.com/repos/${repo}/commits` + ).then((res) => res.json()); + console.debug(`COMMIT SHA: ${commit[0].sha}`); + let theme = JSON.parse( + readFileSync(join(utils.getPath("plugins"), "gh_" + apiRepo.id, "package.json"), "utf8") + ); + theme.id = apiRepo.id + theme.commit = commit[0].sha + writeFileSync( + join(utils.getPath("plugins"), "gh_" + apiRepo.id, "package.json"), + JSON.stringify(theme, null, 4), + "utf8" + ); + } catch (e) { + returnVal.success = false; + } + BrowserWindow.win.webContents.send("plugin-installed", returnVal); + }); + ipcMain.handle("get-github-theme", async (event, url) => { const returnVal = { success: true, @@ -817,7 +868,7 @@ export class BrowserWindow { BrowserWindow.win.webContents.openDevTools({mode: 'detach'}); }) - ipcMain.on('relaunchApp',(_event, _) => { + ipcMain.handle('relaunchApp',(_event, _) => { app.relaunch() app.exit() }) diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts index ddaebf7c..c3d11233 100644 --- a/src/main/base/plugins.ts +++ b/src/main/base/plugins.ts @@ -19,11 +19,20 @@ export class Plugins { private basePluginsPath = path.join(__dirname, '../plugins'); private userPluginsPath = path.join(electron.app.getPath('userData'), 'Plugins'); private readonly pluginsList: any = {}; + private static PluginMap: any = {}; constructor() { this.pluginsList = this.getPlugins(); } + public static getPluginFromMap(plugin: string): any { + if(Plugins.PluginMap[plugin]) { + return Plugins.PluginMap[plugin]; + }else{ + return plugin; + } + } + public getPlugins(): any { let plugins: any = {}; @@ -68,10 +77,12 @@ export class Plugins { else if (fs.lstatSync(path.join(this.userPluginsPath, file)).isDirectory()) { const pluginPath = path.join(this.userPluginsPath, file); if (fs.existsSync(path.join(pluginPath, 'package.json'))) { - const plugin = require(path.join(pluginPath, "index.js")); + const pluginPackage = require(path.join(pluginPath, "package.json")); + const plugin = require(path.join(pluginPath, pluginPackage.main)); if (plugins[plugin.name] || plugin.name in plugins) { console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`); } else { + Plugins.PluginMap[pluginPackage.name] = file; const pluginEnv = { app: electron.app, store: utils.getStore(), diff --git a/src/main/base/utils.ts b/src/main/base/utils.ts index 81bf8637..103f772f 100644 --- a/src/main/base/utils.ts +++ b/src/main/base/utils.ts @@ -86,6 +86,10 @@ export class utils { return bw.win } + static loadPluginFrontend(path: string): void { + + } + static loadJSFrontend(path: string): void { bw.win.webContents.executeJavaScript(fs.readFileSync(path, "utf8")); } diff --git a/src/renderer/main/ciderfrontapi.js b/src/renderer/main/ciderfrontapi.js index fc51f884..145bd770 100644 --- a/src/renderer/main/ciderfrontapi.js +++ b/src/renderer/main/ciderfrontapi.js @@ -10,6 +10,22 @@ const CiderFrontAPI = { AddMenuEntry(entry) { app.pluginMenuEntries.push(entry) app.pluginInstalled = true + }, + StyleSheets: { + Add(href) { + console.log("Adding stylesheet: " + href) + let id = uuidv4() + let link = document.createElement("link") + link.rel = "stylesheet/less" + link.type = "text/css" + link.href = href + link.setAttribute("css-id", id) + // insert the link before document.querySelector("#userTheme") in head + document.querySelector("head").insertBefore(link, document.querySelector("#userTheme")) + less.registerStylesheetsImmediately() + less.refresh(true, true, true) + return link + } } } diff --git a/src/renderer/views/pages/plugins-github.ejs b/src/renderer/views/pages/plugins-github.ejs index a6da8981..db6eb689 100644 --- a/src/renderer/views/pages/plugins-github.ejs +++ b/src/renderer/views/pages/plugins-github.ejs @@ -3,11 +3,11 @@
-

Plugins from GitHub

+

{{$root.getLz('settings.header.visual.plugin.github.page')}}

@@ -84,7 +84,7 @@ }, mounted() { this.getRepos(); - this.getInstalledThemes(); + // this.getInstalledThemes(); }, methods: { getInstalledThemes() { @@ -124,36 +124,50 @@ }, installThemeRepo(repo) { let self = this - let msg = app.stringTemplateParser(app.getLz('settings.option.visual.theme.github.install.confirm'), { + let msg = app.stringTemplateParser(app.getLz('settings.option.visual.plugin.github.install.confirm'), { repo: repo.full_name }); bootbox.confirm(msg, (res) => { if (res) { - ipcRenderer.once("theme-installed", (event, arg) => { + ipcRenderer.once("plugin-installed", (event, arg) => { if (arg.success) { - self.themes = ipcRenderer.sendSync("get-themes") - notyf.success(app.getLz('settings.notyf.visual.theme.install.success')); + self.themes = [] + notyf.success(app.getLz('settings.notyf.visual.plugin.install.success')); + bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), ()=>{ + if(ok) { + ipcRenderer.invoke("relaunchApp") + }else{ + return + } + }) } else { - notyf.error(app.getLz('settings.notyf.visual.theme.install.error')); + notyf.error(app.getLz('settings.notyf.visual.plugin.install.error')); } }); - ipcRenderer.invoke("get-github-theme", repo.html_url) + ipcRenderer.invoke("get-github-plugin", repo.html_url) } }) }, installThemeURL() { let self = this - bootbox.prompt(app.getLz('settings.prompt.visual.theme.github.URL'), (result) => { + bootbox.prompt(app.getLz('settings.prompt.visual.plugin.github.URL'), (result) => { if (result) { - ipcRenderer.once("theme-installed", (event, arg) => { + ipcRenderer.once("plugin-installed", (event, arg) => { if (arg.success) { self.themes = ipcRenderer.sendSync("get-themes") - notyf.success(app.getLz('settings.notyf.visual.theme.install.success')); + bootbox.confirm(app.getLz("settings.prompt.visual.plugin.github.success"), ()=>{ + if(ok) { + ipcRenderer.invoke("relaunchApp") + }else{ + return + } + }) + notyf.success(app.getLz('settings.notyf.visual.plugin.install.success')); } else { - notyf.error(app.getLz('settings.notyf.visual.theme.install.error')); + notyf.error(app.getLz('settings.notyf.visual.plugin.install.error')); } }); - ipcRenderer.invoke("get-github-theme", result) + ipcRenderer.invoke("get-github-plugin", result) } }); }, diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 67be8cb1..9d0a1ed4 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -662,6 +662,15 @@
+
+
+ {{$root.getLz('settings.option.visual.plugin.github.explore')}} +
+
+ +
+
+
{{$root.getLz('settings.option.experimental.unknownPlugin')}}