diff --git a/apps/electron/src/external.js b/apps/electron/src/external.js index 992c72135..81bcbbf4f 100644 --- a/apps/electron/src/external.js +++ b/apps/electron/src/external.js @@ -17,6 +17,7 @@ const env = process.env.NODE_ENV || 'production'; const isProduction = env === 'production'; const isMac = process.platform === 'darwin'; const isWindows = process.platform === 'win32'; +const isLinux = process.platform === 'linux'; const releaseTag = `v${version}`; @@ -43,6 +44,32 @@ const getServerUrl = (port) => `http://localhost:${port}`; /** Resolves URL path to download resources */ const downloadPath = '/data/db/'; +/** + * @description Returns public path depending on OS + * This is the correct path for the app running in production mode + */ +function getAppDataPath() { + if (isMac) { + return path.join(process.env.HOME, 'Library', 'Application Support', 'Ontime'); + } + + if (isWindows) { + return path.join(process.env.APPDATA, 'Ontime'); + } + + if (isLinux) { + return path.join(process.env.HOME, '.Ontime'); + } + + return ''; +} + +const projectsPath = path.join(getAppDataPath(), 'projects'); +const corruptProjectsPath = path.join(getAppDataPath(), 'corrupt files'); +const crashLogPath = path.join(getAppDataPath(), 'crash logs'); +const stylesPath = path.join(getAppDataPath(), 'styles'); +const externalPath = path.join(getAppDataPath(), 'external'); + /** path to tray icon */ const trayIcon = path.join(__dirname, electronConfig.assets.pathToAssets, 'background.png'); /** path to app icon directory */ @@ -60,6 +87,11 @@ module.exports = { nodePath, getClientUrl, getServerUrl, + projectsPath, + corruptProjectsPath, + crashLogPath, + stylesPath, + externalPath, downloadPath, trayIcon, appIcon, diff --git a/apps/electron/src/menu/applicationMenu.js b/apps/electron/src/menu/applicationMenu.js index 9936bb624..9916ec625 100644 --- a/apps/electron/src/menu/applicationMenu.js +++ b/apps/electron/src/menu/applicationMenu.js @@ -1,6 +1,18 @@ const { Menu, shell } = require('electron'); -const { linkToGitHub, linkToDocs, linkToDiscord, isMac, releaseTag, downloadPath } = require('../external'); +const { + linkToGitHub, + linkToDocs, + linkToDiscord, + isMac, + releaseTag, + projectsPath, + corruptProjectsPath, + crashLogPath, + stylesPath, + externalPath, + downloadPath, +} = require('../external'); /** * Creates the application menu @@ -81,6 +93,18 @@ function makeFileMenu(serverUrl, redirectWindow, download) { label: 'Download project', click: downloadProject, }, + { type: 'separator' }, + { + label: 'Open directory', + submenu: [ + makeItemOpenInDesktop('Projects', projectsPath), + makeItemOpenInDesktop('Corrupted projects', corruptProjectsPath), + makeItemOpenInDesktop('Crash logs', crashLogPath), + makeItemOpenInDesktop('CSS override', stylesPath), + makeItemOpenInDesktop('External', externalPath), + ], + }, + { type: 'separator' }, { role: isMac ? 'close' : 'quit' }, ], }; @@ -95,20 +119,20 @@ function makeViewMenu(clientUrl) { return { label: 'Views', submenu: [ - makeItemOpenInShell('Public', `${clientUrl}/public`), - makeItemOpenInShell('Lower Thirds', `${clientUrl}/lower`), + makeItemOpenInBrowser('Public', `${clientUrl}/public`), + makeItemOpenInBrowser('Lower Thirds', `${clientUrl}/lower`), { type: 'separator' }, - makeItemOpenInShell('Timer', `${clientUrl}/timer`), - makeItemOpenInShell('Minimal Timer', `${clientUrl}/minimal`), - makeItemOpenInShell('Clock', `${clientUrl}/clock`), - makeItemOpenInShell('Backstage', `${clientUrl}/backstage`), - makeItemOpenInShell('Timeline (beta)', `${clientUrl}/timeline`), - makeItemOpenInShell('Studio Clock', `${clientUrl}/studio`), - makeItemOpenInShell('Countdown', `${clientUrl}/countdown`), + makeItemOpenInBrowser('Timer', `${clientUrl}/timer`), + makeItemOpenInBrowser('Minimal Timer', `${clientUrl}/minimal`), + makeItemOpenInBrowser('Clock', `${clientUrl}/clock`), + makeItemOpenInBrowser('Backstage', `${clientUrl}/backstage`), + makeItemOpenInBrowser('Timeline (beta)', `${clientUrl}/timeline`), + makeItemOpenInBrowser('Studio Clock', `${clientUrl}/studio`), + makeItemOpenInBrowser('Countdown', `${clientUrl}/countdown`), { type: 'separator' }, - makeItemOpenInShell('Editor', `${clientUrl}/editor`), - makeItemOpenInShell('Cuesheet', `${clientUrl}/cuesheet`), - makeItemOpenInShell('Operator', `${clientUrl}/op`), + makeItemOpenInBrowser('Editor', `${clientUrl}/editor`), + makeItemOpenInBrowser('Cuesheet', `${clientUrl}/cuesheet`), + makeItemOpenInBrowser('Operator', `${clientUrl}/op`), { type: 'separator' }, { role: 'forceReload' }, @@ -238,9 +262,9 @@ function makeHelpMenu(redirectWindow) { { type: 'separator', }, - makeItemOpenInShell('See on github', linkToGitHub), - makeItemOpenInShell('Online documentation', linkToDocs), - makeItemOpenInShell('Join us on Discord', linkToDiscord), + makeItemOpenInBrowser('See on github', linkToGitHub), + makeItemOpenInBrowser('Online documentation', linkToDocs), + makeItemOpenInBrowser('Join us on Discord', linkToDiscord), ], }; } @@ -251,7 +275,7 @@ function makeHelpMenu(redirectWindow) { * @param {string} url * @returns {object} - MenuItem */ -function makeItemOpenInShell(label, url) { +function makeItemOpenInBrowser(label, url) { return { label: `${label} ↗`, click: async () => { @@ -264,4 +288,23 @@ function makeItemOpenInShell(label, url) { }; } +/** + * Utility function to open a file in the OS explorer / finder + * @param {string} label + * @param {string} path + * @returns {object} - MenuItem + */ +function makeItemOpenInDesktop(label, path) { + return { + label, + click: () => { + try { + shell.openPath(path); + } catch (_error) { + /** unhandled error */ + } + }, + }; +} + module.exports = { getApplicationMenu };