[MM-23067] Browser View (#1514)
* Browser-view: initial architectural changes + webpack (#1358) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * remove old webpack generated files * add assets files * more remove files and fix localurls * CR changes * Browserview settings window (#1362) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * [BrowserView] renderer (#1378) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * remove log statements * Bv menus (#1387) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * package.json * fix merge results * fix package-lock * remove debug statements * address CR requests * [MM-22691][Browserview] fix tray icon (#1403) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * fix webpack adding images to /dist so tray can render them * wait for config, fix menutray calls * remove .gitattributes from being tracked * remove unused reject * remove logs * Update webpack.config.renderer.js Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> * Browserview URLHover (#1393) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * wip * wip urlview * wip * urlview when hovering on a link * change how to detect when the mouse hovers * [BrowserView] remove remote usage, fix menus and window buttons in Win (#1418) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * fix webpack adding images to /dist so tray can render them * wait for config, fix menutray calls * remove .gitattributes from being tracked * remove unused reject * remove logs * Update webpack.config.renderer.js Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> * fix three dot menu * remove most remote usage, fix window buttons in Windows Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> * fix different errors when loading config (#1420) * [BrowserView] Native modules & registry access (#1417) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * fix webpack adding images to /dist so tray can render them * wait for config, fix menutray calls * remove .gitattributes from being tracked * restart-working native modules * setup env variables for installing native modules * [browserview] Electron notifications (#1411) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * wip * move viewmanager into windowmanager * working notifications * remove logs, switch tab on notification click * download notifications * fix tray * fix menu switch server * fix error * [MM-23078] TabBar fixes for BrowserView (#1423) * [MM-23078] TabBar fixes for BrowserView * Removing unnecessary logging * [Browserview] 4.6 and 4.7 PRs (#1424) * [MM-28620] allow navigating links to admin_console #1374 * [MM-25789] - Update default settings for new installations #1376 * [MM-27332] show window at autolaunch #1379 * Update NOTICE.txt (#1385) * Update NOTICE.txt * Update NOTICE.txt * Update NOTICE.txt * convert to markdown * md linting * Update NOTICE.md * Revert "Update NOTICE.md" This reverts commit 9381fca895c0677bcad1cf1c1071ca88afd6f486. * Revert "md linting" This reverts commit e7a68f120109d47b9849cf816d4fef79483ad22f. * Revert "convert to markdown" This reverts commit 1e7ed8a67c9c98cd0d0f3ff6cdc70782effb143d. * add missing licenses to joi and jq * Remove devDependencies Co-authored-by: Guillermo Vaya <guivaya@gmail.com> * Notification sounds, also added tab name to notification title * [MM-22013] - Allow users to specify default download locations #1383 * [MM-21835] Use URL instead of the url library #1384 * remove debug console.log statements Co-authored-by: Amy Blais <amy_blais@hotmail.com> * [MM-31266] fix access url when it's not a mm server (#1431) * [MM-31224] fix reloading servers and other tab issues (#1434) * [MM-31224] fix reloading servers and other tab issues * reload if url changes * Change the dev server port to 9001 to avoid conflict with mattermost-minio (#1437) * remove dev_web_server (#1438) * [MM-31225][MM-31217][MM-31219][Browserview] fix linux compilation + other fixes (#1433) * fix linux errors * remove registry, remove env_vars * devtools in separate window, prevent config errors * fix registry path * move dist to root when packaging * make devtools dettached to avoid browserview * remove unneeded comment * use reject in case of registry failure * fix handling results * fix application menu * make linter happy * fix missing key on apt-get (#1440) (#1442) see https://github.com/electron-userland/electron-builder/issues/5485#issuecomment-749244332 * [MM-31221][BrowserView] first modal: adding a server while in a server view (#1400) * reorder code to support webpack * start backend changes * remove simple-spellchecker * wip * first browserview run * settings window routing * wip * back to webpack * working build * back to using electron-builder * fix linting * linting errors missed * back to just 1 config * missing changes * refactor and have the settings in its own page * reminder to restore disabling window.eval * wip * wip * remove old webpack generated files * add assets files * more remove files and fix localurls * wip settings, needs fixing saving prefs * remove linting errors * remove settings as a modal * fix linting * remove view from window on destroy * restore visibility if reloaded * debug log * look for closed windows, remove managers from settings as it is a full window * restore view on configuration save * linting and debug * remove debug message * make eslint be aware of webpack aliases * some extra disable lines * move badge management to main * remove unneded import * fixing errors * wip * back to having tabs * switch tab working * wip * wip * wip * fix quitting error * back to a working config * configure retries * add darkmode * wip * add error/loading screens * fix settings while removing remote usage * wip * fix lint, get preload to load * remove unused import * wip * menus initially working as they should * update deps, show context menu * wip * wip * wip * fix forward/back menu * fix server menu * allow navigating to external urls in the browser * add defaults to menu * fix logic * set default options * remove logs * wip * wip * wip urlview * wip * urlview when hovering on a link * wip * wip * first working modal * fix config loading * upgrade electron to 10.1.5 * esc exits modals * first modal * add env variables for settings and modals devtools * adress CSS review comments * Address review comments * fix dist in prod * fix preload path on build * [MM-31987] Allow camera use for jitsi (#1443) (#1450) * [MM-31987] allow camera use for jitsi * update message for access * [MM-31261] Use manual resizing of BrowserViews on resize, maximize and full-screen (#1449) * [MM-31261] Use manual resizing of BrowserViews on resize, maximize and full-screen * Update src/main/windows/windowManager.js Co-authored-by: Guillermo Vayá <guivaya@gmail.com> Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * add own branch for testing (#1448) * add own branch for testing * remove signing for windows * add message to channel * Bv pipeline elisabeth (#1452) * Add parameter and remove schedule * Add jq * Fix adding jq * Fix adding jq * Fix adding jq * fix quotes * upload as JSON * use previous, parse json * fixes * use json Co-authored-by: Elisabeth Kulzer <elikul@elikul.de> * [MM-30144][MM-30145][MM-30146][MM-30147] Migrate auth and certificate modals to BrowserView (#1445) * WIP * WIP * WIP * WIP * WIP * [MM-30144][MM-30145] Migrate LoginModal and PermissionModal to BrowserView * [MM-30146][MM-30147] Migrate certificate modals to BrowserView * Fixed transparency on the bootstrap modals * PR feedback * Added better error reporting in case the modal promise fails * [MM-31233] Reverse maximize logic typo (#1454) * [browser view] MM-32277 bump version, exe, cache errrors (#1456) * bump version * enable msi and remove src/package* * ensure variable exists * remove cleanCache script * default expansion for env variable * add commit version, missing package-lock.json * remove duplicated command * [MM-31467] Move protocol handling over from original MattermostView into web contents handler (#1453) * WIP * WIP * [MM-31467] Move protocol handling over from original MattermostView into web contents handler * Remove log statement * [MM-32392] prevent crash when checking a URL (#1457) * [MM-31215][MM-31387] Fixes for bad tab navigation and dragging (#1461) * [MM-31387] Send to renderer on clicking server from settings window * Use different event name for sending switch server info to renderer * Have the viewManager let the renderer know when the tab has changed * Couple more fixes around tabs * Simplify URL compare logic * [MM-31650] Restore focus to active server on modal and settings window closure + other fixes (#1455) * [MM-31650] Focus active server on settings window and modal closure * Disable tabs when a modal is open * Revert to using original NewTeamModal component * fix resize (#1462) * [MM-32424] fix server devtools being hidden by browserview (#1459) * [MM-32424] fix server devtools being hidden by browserview * reverse logic * [MM-20227][MM-31388] move to roles and fix focus (#1463) * [MM-31570] update mentions/unreads/session on jewel, tray and dock (#1460) * [MM-32333] Open public links in the user's default browser (#1468) * [MM-32333] Open public links in the user's default browser * Removed commented code * [MM-31232] fix urlview present with no content (#1467) * [MM-31343] Migrate Finder to BrowserView (#1466) * WIP * WIP * WIP * [MM-31343] Migrate Finder to BrowserView * PR feedback * Removing reference to this in non-class file * use electron to handle spellchecking (#1469) * [MM-32382] Use resize event instead of will-resize for monitoring size of BV (#1470) * [MM-32570] Use OpenSans as the font for the URL preview modal (#1471) * [MM-32570] Use OpenSans as the font for the URL preview modal * Don't use bootstrap * Fix draw badge (#1477) * use canvas from window * fix errors * fix errors * safer code injection * [MM-31554] Add listener for config synchronization on the settings window (#1473) * [MM-31554] Add listener for config synchronization on the settings window * Synchronize the config if updated from outside the settings window * [MM-28541] restore deeplinking (#1475) * handle deeplinking * fix app handling deeplinking * remove outdated comment * address review comments * MM-32765_prevent crash on checking unread state (#1479) * MM-31383 make no the default when asking to add a protocol (#1481) * [MM-31340] Resize browser view and show back button when on non-team URL (#1472) * WIP * [MM-31340] Resize browser view and show back button when on non-team URL * Fixed issue where switching tabs and resizing hides the back button * Add error checking around going back in history * [MM-31399] Use webapp ESLint config in desktop app and resolve inconsistencies (#1482) * Import webapp eslint and update packages * FIrst pass with new ruleset * Allow setState * Fix rule for tests * Comment out skippeed tests, removed some TODOs and fixed some warnings * Remove errors from MainPage * Use indenting profile from webapp * Update editorconfig for new indenting * Fix indenting for class properties * Only disable no-console for renderer process and scripts * Remove rule overrides and changes * Fix merge issues * PR feedback and fixed a bad merge * [MM-25122] Use modded version of winreg that supports UTF-8 (#1488) * fix appicon path resolution (#1484) * [MM-33141] Fixed use of bad context in TeamList (#1487) * [MM-33141] Fixed use of bad context in TeamList * Refactor to pull the functions out * Remove unnecessary props * [MM-25355] Throttle notifications for Windows by channel id (#1486) * [MM-25355] Throttle notifications for Windows * Use teamId as well to key the notifications * Merge'd * Use Map instead of Set * [MM-33050] move webcontent events out of main (#1489) * wip * wip * fix webcontent events, move views to its own folder * [MM-33238] Check for admin URL when toggling back bar (#1495) * [MM-31342] fix "save image as" context menu crash (#1490) * [MM-33231] update jewel on new mentions/when read (#1493) * [MM-33231] update state properly for a purecomponent * remove unneeded comment * [MM-33032] Use `hidden` titleBarStyle value to fix macOS Catalina click issue (#1496) * [MM-32809] Remove Toggle Dark Mode menu item for Windows, enable toggling on Linux (#1494) * [MM-32809] Remove Toggle Dark Mode menu item for Windows * Just check for !win32 and !darwin * Enable correct dark mode functionality on non-macOS/non-Windows machines * [MM-33334] Restore keyboard shortcuts for menu items moved to roles (#1499) * [MM-33434] Upgrade to Electron v11, some other dependency upgrades (#1501) * [MM-33434] Upgrade to Electron v11, some other dependency upgrades * Missed a version change * context menu fix * Forgot to remove a log statement * Added resized for redundancy and upgraded to spectron 13 * Don't need resized * [MM-33542] Trigger finder cleanup on pressing close or Escape (#1502) * [MM-33542] Clear the Finder selection when closing the finder * Remove listener on close as well * Run close() on escape as well * [MM-33607] Remove old badge code, update unreads code (#1503) * [MM-33607] Remove old badge code, update unreads code * Fix 2 random lint errors * [MM-33247] Have the app handle links to other teams as a deep link (#1498) * [MM-33373] Trigger the smaller font for 99+ mentions (#1507) * [MM-32805] Merge master, migrate LoadingScreen to BrowserView (#1504) * [MM-467] Notification sounds (#1351) * Custom sounds * Trying new version * Trying new version * Some fixes * Rollback version change * Allow native sound * Increase version * Playing custom sounds :) * Fix var name * Fix * Update src/browser/js/notification.js Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * Update src/browser/js/notification.js Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * Update src/browser/js/notification.js Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * Several suggestions * Update src/browser/js/notification.js Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * Restore of version Co-authored-by: Guillermo Vayá <guivaya@gmail.com> * Clean caches on depcheck failure (#1369) Co-authored-by: Mattermod <mattermod@users.noreply.github.com> * [MM-28595] Open team links within the app (#1373) * [MM-25789] - Update default settings for new installations (#1376) * [MM-25789] - Update default settings for new installations * Update src/main.js Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * Update src/main.js Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * Fix linter Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MacBook-Pro-2.local> Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * add Russian language in the list available for spellcheck (#1375) * [MM-28620] allow navigating links to admin_console (#1374) * [MM-28620] allow navigating links to admin_console * Fix when there is not a server associated * [MM-27332] show window at autolaunch (#1379) * Bump to version 4.7.0-develop * Update NOTICE.txt (#1385) * Update NOTICE.txt * Update NOTICE.txt * Update NOTICE.txt * convert to markdown * md linting * Update NOTICE.md * Revert "Update NOTICE.md" This reverts commit 9381fca895c0677bcad1cf1c1071ca88afd6f486. * Revert "md linting" This reverts commit e7a68f120109d47b9849cf816d4fef79483ad22f. * Revert "convert to markdown" This reverts commit 1e7ed8a67c9c98cd0d0f3ff6cdc70782effb143d. * add missing licenses to joi and jq * Remove devDependencies Co-authored-by: Guillermo Vaya <guivaya@gmail.com> * [MM-9922] Hide tooltip for internal links (channels, timestamps, etc.) (#1386) * Hide tooltip for internal links (channels, timestamps, etc.) * Only hide tooltip for internal links on the *current* team * feat(spellcheck): add Ukrainian language for spellcheck (#1382) * [MM-29677] fix download complete notification not appearing (#1388) * fix soundname not existing (#1390) * [MM-29921] fix custom sound not playing when receiving a notification (#1396) * [MM-29921] fix sound notification * remove logs * Update release-process.md (#1394) * [MM-22013] - Allow users to specify default download locations (#1383) * [MM-22013] - Allow users to specify default download locations * PR comments * Add proper config prop * Update src/browser/components/SettingsPage.jsx Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * Remove string ref * Fix styling * Update styling * Disable input * Add variable for windows * Prevent dialog from opening twice Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MBP-2.fritz.box> Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MacBook-Pro-2.local> Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com> * [MM-21835] Use URL instead of the url library (#1384) Additionally, migrate all of the URL related helper functions from `src/utils/utils.js` to the new `src/utils/url.js` file and migrate tests. Issue MM-21835 Fixes #1206 * Merge Powershell files together and remove AppVeyor related code * Ensure nodejs deps are met before running script argument directly * [MM-22810] Update loading screen with new design & animation (#1409) * Update loading screen with new design & animation * add prop back in * adjust z-index for tests * tweaks to pass tests * address offline feedback - shrink initial logo size - introduce a slight delay before fading loading spinner out - fix horizontal scrollbar showing on load screen * add missing css variable * no need to remove loading icon * Apply suggestions from code review Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * Move LoadingScreen.jsx to file-only component * Rename prop for better clarity * Default prop to none and check when needed * Update import paths * Add ESDocs and remove unecessary conditional * Forgot to remove the eslint override Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> * [MM-22960] - Keep desktop app pinned to taskb bar when the app upgrades (#1397) Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MacBook-Pro-2.local> * Bump highlight.js from 9.18.1 to 9.18.5 (#1421) Bumps [highlight.js](https://github.com/highlightjs/highlight.js) from 9.18.1 to 9.18.5. - [Release notes](https://github.com/highlightjs/highlight.js/releases) - [Changelog](https://github.com/highlightjs/highlight.js/blob/9.18.5/CHANGES.md) - [Commits](https://github.com/highlightjs/highlight.js/compare/9.18.1...9.18.5) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ini from 1.3.5 to 1.3.7 (#1427) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix missing key on apt-get (#1440) see https://github.com/electron-userland/electron-builder/issues/5485#issuecomment-749244332 * [MM-31987] Allow camera use for jitsi (#1443) * [MM-31987] allow camera use for jitsi * update message for access * Created codeql analysis (#1441) Co-authored-by: Mattermod <mattermod@users.noreply.github.com> * [MM-31626] bypass gitlab browser-check for oauth login (#1439) * MM-31626 make User Agent configurable by user * add info * remove chrome from UA for gitlab.com * remove previous solution Co-authored-by: Mattermod <mattermod@users.noreply.github.com> * Add Swedish sv-SE (already in simple-spellchecker) (#1483) * Add Swedish sv-SE (already in simple-spellchecker) * Remove spaces in empty lines * Add some sv-SE test for spellchecker Co-authored-by: Peter Johansson <peter.johansson@havochvatten.se> * Add loading screen, fix reload * WIP * Migrate LoadingScreen to BrowserView * Lint fixes * Removed gitlab fix code, also returning null is bad apparently * Fix reload logic Co-authored-by: Rodrigo Villablanca <villa061004@gmail.com> Co-authored-by: Guillermo Vayá <guivaya@gmail.com> Co-authored-by: Juho Nurminen <juho.nurminen@mattermost.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> Co-authored-by: Nev Angelova <nevy.angelova@gmail.com> Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MacBook-Pro-2.local> Co-authored-by: Eugeny Fomin <github.com@jeka.ru> Co-authored-by: Amy Blais <amy_blais@hotmail.com> Co-authored-by: Nathan Bolender <nathan@nathanbolender.com> Co-authored-by: Dmitriy Danilov <daniloff200@gmail.com> Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MBP-2.fritz.box> Co-authored-by: FalseHonesty <skipboman0@gmail.com> Co-authored-by: William Gathoye <william@gathoye.be> Co-authored-by: Dean Whillier <deanwhillier@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rohitesh Gupta <srkg.gupta@gmail.com> Co-authored-by: petermcj <petermcj@gmail.com> Co-authored-by: Peter Johansson <peter.johansson@havochvatten.se> * [MM-33668] Restore tests to browser-view branch (#1506) * happy eslint * wip * wip * remove aliases * almost working tests * green tests * Revert "remove aliases" This reverts commit 803d3695538197407b45e0d8d30dc429b259b7f3. * add unit test, reconfigure package scripts, make test pass * [MM-33542] Trigger finder cleanup on pressing close or Escape (#1502) * [MM-33542] Clear the Finder selection when closing the finder * Remove listener on close as well * Run close() on escape as well * [MM-33607] Remove old badge code, update unreads code (#1503) * [MM-33607] Remove old badge code, update unreads code * Fix 2 random lint errors * fix script naming in circle * fix check deps * attempt to fix dependency-check download * remove check-deps step Co-authored-by: = <=> Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> * Cleanup of BrowserView migration, some bug fixes (#1509) * 1st round of cleanup * 2nd round of cleanup * Set constant for reload-config * Cleaned up some TODOs * store daily build to S3 (#1508) * store daily build to S3 * missing colon * fix paths * try to keep folders * remove unneeded step * change from arn to bucket name * keep organization consistent * fix indentation * fix indentation x2 Co-authored-by: = <=> * MM-33551 keep tray state between themes (#1511) Co-authored-by: = <=> * Set to version v4.7 Co-authored-by: Guillermo Vayá <guillermo.vaya@mattermost.com> Co-authored-by: Amy Blais <amy_blais@hotmail.com> Co-authored-by: Guillermo Vayá <guivaya@gmail.com> Co-authored-by: Elisabeth Kulzer <elikul@elikul.de> Co-authored-by: Rodrigo Villablanca <villa061004@gmail.com> Co-authored-by: Juho Nurminen <juho.nurminen@mattermost.com> Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Nev Angelova <nevy.angelova@gmail.com> Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MacBook-Pro-2.local> Co-authored-by: Eugeny Fomin <github.com@jeka.ru> Co-authored-by: Nathan Bolender <nathan@nathanbolender.com> Co-authored-by: Dmitriy Danilov <daniloff200@gmail.com> Co-authored-by: Nevyana Angelova <nevyangelova@Nevyanas-MBP-2.fritz.box> Co-authored-by: FalseHonesty <skipboman0@gmail.com> Co-authored-by: William Gathoye <william@gathoye.be> Co-authored-by: Dean Whillier <deanwhillier@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rohitesh Gupta <srkg.gupta@gmail.com> Co-authored-by: petermcj <petermcj@gmail.com> Co-authored-by: Peter Johansson <peter.johansson@havochvatten.se>
This commit is contained in:
@@ -3,135 +3,144 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {EventEmitter} from 'events';
|
||||
|
||||
import WindowsRegistry from 'winreg';
|
||||
import log from 'electron-log';
|
||||
import WindowsRegistry from 'winreg-utf8';
|
||||
|
||||
const REGISTRY_HIVE_LIST = [WindowsRegistry.HKLM, WindowsRegistry.HKCU];
|
||||
const BASE_REGISTRY_KEY_PATH = '\\Software\\Policies\\Mattermost';
|
||||
export const REGISTRY_READ_EVENT = 'registry-read';
|
||||
|
||||
/**
|
||||
* Handles loading config data from the Windows registry set manually or by GPO
|
||||
*/
|
||||
export default class RegistryConfig extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.initialized = false;
|
||||
this.data = {
|
||||
teams: [],
|
||||
};
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.initialized = false;
|
||||
this.data = {
|
||||
teams: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Triggers loading data from Windows registry, supports async/await
|
||||
*
|
||||
* @emits {update} emitted once all data has been loaded from the registry
|
||||
*/
|
||||
async init() {
|
||||
if (process.platform === 'win32') {
|
||||
// extract DefaultServerList from the registry
|
||||
try {
|
||||
const servers = await this.getServersListFromRegistry();
|
||||
if (servers.length) {
|
||||
this.data.teams.push(...servers);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[RegistryConfig] Nothing retrieved for \'DefaultServerList\'', error);
|
||||
}
|
||||
async init() {
|
||||
if (process.platform === 'win32') {
|
||||
// extract DefaultServerList from the registry
|
||||
try {
|
||||
const servers = await this.getServersListFromRegistry();
|
||||
if (servers.length) {
|
||||
this.data.teams.push(...servers);
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn('[RegistryConfig] Nothing retrieved for \'DefaultServerList\'', error);
|
||||
}
|
||||
|
||||
// extract EnableServerManagement from the registry
|
||||
try {
|
||||
const enableServerManagement = await this.getEnableServerManagementFromRegistry();
|
||||
if (enableServerManagement !== null) {
|
||||
this.data.enableServerManagement = enableServerManagement;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[RegistryConfig] Nothing retrieved for \'EnableServerManagement\'', error);
|
||||
}
|
||||
// extract EnableServerManagement from the registry
|
||||
try {
|
||||
const enableServerManagement = await this.getEnableServerManagementFromRegistry();
|
||||
if (enableServerManagement !== null) {
|
||||
this.data.enableServerManagement = enableServerManagement;
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn('[RegistryConfig] Nothing retrieved for \'EnableServerManagement\'', error);
|
||||
}
|
||||
|
||||
// extract EnableAutoUpdater from the registry
|
||||
try {
|
||||
const enableAutoUpdater = await this.getEnableAutoUpdatorFromRegistry();
|
||||
if (enableAutoUpdater !== null) {
|
||||
this.data.enableAutoUpdater = enableAutoUpdater;
|
||||
// extract EnableAutoUpdater from the registry
|
||||
try {
|
||||
const enableAutoUpdater = await this.getEnableAutoUpdatorFromRegistry();
|
||||
if (enableAutoUpdater !== null) {
|
||||
this.data.enableAutoUpdater = enableAutoUpdater;
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn('[RegistryConfig] Nothing retrieved for \'EnableAutoUpdater\'', error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[RegistryConfig] Nothing retrieved for \'EnableAutoUpdater\'', error);
|
||||
}
|
||||
|
||||
// this will happen wether we are on windows and load the info or not
|
||||
this.initialized = true;
|
||||
this.emit(REGISTRY_READ_EVENT, this.data);
|
||||
}
|
||||
this.initialized = true;
|
||||
this.emit('update', this.data);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Extracts a list of servers
|
||||
*/
|
||||
async getServersListFromRegistry() {
|
||||
const defaultTeams = await this.getRegistryEntry(`${BASE_REGISTRY_KEY_PATH}\\DefaultServerList`);
|
||||
return defaultTeams.flat(2).reduce((teams, team) => {
|
||||
if (team) {
|
||||
teams.push({
|
||||
name: team.name,
|
||||
url: team.value,
|
||||
order: team.order,
|
||||
});
|
||||
}
|
||||
return teams;
|
||||
}, []);
|
||||
}
|
||||
async getServersListFromRegistry() {
|
||||
const defaultServers = await this.getRegistryEntry(`${BASE_REGISTRY_KEY_PATH}\\DefaultServerList`);
|
||||
return defaultServers.flat(2).reduce((servers, server, index) => {
|
||||
if (server) {
|
||||
servers.push({
|
||||
name: server.name,
|
||||
url: server.value,
|
||||
order: server.order || index,
|
||||
});
|
||||
}
|
||||
return servers;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Determines whether server management has been enabled, disabled or isn't configured
|
||||
*/
|
||||
async getEnableServerManagementFromRegistry() {
|
||||
const entries = (await this.getRegistryEntry(BASE_REGISTRY_KEY_PATH, 'EnableServerManagement'));
|
||||
const entry = entries.pop();
|
||||
return entry ? entry === '0x1' : null;
|
||||
}
|
||||
async getEnableServerManagementFromRegistry() {
|
||||
const entries = (await this.getRegistryEntry(BASE_REGISTRY_KEY_PATH, 'EnableServerManagement'));
|
||||
const entry = entries.pop();
|
||||
return entry ? entry === '0x1' : null;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Determines whether the auto updated has been enabled, disabled or isn't configured
|
||||
*/
|
||||
async getEnableAutoUpdatorFromRegistry() {
|
||||
const entries = (await this.getRegistryEntry(BASE_REGISTRY_KEY_PATH, 'EnableAutoUpdater'));
|
||||
const entry = entries.pop();
|
||||
return entry ? entry === '0x1' : null;
|
||||
}
|
||||
async getEnableAutoUpdatorFromRegistry() {
|
||||
const entries = (await this.getRegistryEntry(BASE_REGISTRY_KEY_PATH, 'EnableAutoUpdater'));
|
||||
const entry = entries.pop();
|
||||
return entry ? entry === '0x1' : null;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Initiates retrieval of a specific key in the Windows registry
|
||||
*
|
||||
* @param {string} key Path to the registry key to return
|
||||
* @param {string} name Name of specific entry in the registry key to retrieve (optional)
|
||||
*/
|
||||
async getRegistryEntry(key, name) {
|
||||
const results = [];
|
||||
for (const hive of REGISTRY_HIVE_LIST) {
|
||||
results.push(this.getRegistryEntryValues(new WindowsRegistry({hive, key}), name));
|
||||
async getRegistryEntry(key, name) {
|
||||
const results = [];
|
||||
for (const hive of REGISTRY_HIVE_LIST) {
|
||||
results.push(this.getRegistryEntryValues(hive, key, name));
|
||||
}
|
||||
const entryValues = await Promise.all(results);
|
||||
return entryValues.filter((value) => value);
|
||||
}
|
||||
const entryValues = await Promise.all(results);
|
||||
return entryValues.filter((value) => value);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Handles actual retrieval of entries from a configured WindowsRegistry instance
|
||||
*
|
||||
* @param {WindowsRegistry} regKey A configured instance of the WindowsRegistry class
|
||||
* @param {string} name Name of the specific entry to retrieve (optional)
|
||||
*/
|
||||
getRegistryEntryValues(regKey, name) {
|
||||
return new Promise((resolve) => {
|
||||
regKey.values((error, items) => {
|
||||
if (error || !items || !items.length) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (name) { // looking for a single entry value
|
||||
const registryItem = items.find((item) => item.name === name);
|
||||
resolve(registryItem && registryItem.value ? registryItem.value : null);
|
||||
} else { // looking for an entry list
|
||||
resolve(items);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
getRegistryEntryValues(hive, key, name) {
|
||||
const registry = new WindowsRegistry({hive, key, utf8: true});
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
registry.values((error, results) => {
|
||||
if (error || !results || results.length === 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (name) { // looking for a single entry value
|
||||
const registryItem = results.find((item) => item.name === name);
|
||||
resolve(registryItem && registryItem.value ? registryItem.value : null);
|
||||
} else { // looking for an entry list
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
log.error(`There was an error accessing the registry for ${key}`);
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -18,16 +18,16 @@
|
||||
* @prop {[]} managedResources - Defines which paths are managed
|
||||
*/
|
||||
const buildConfig = {
|
||||
defaultTeams: [/*
|
||||
defaultTeams: [/*
|
||||
{
|
||||
name: 'example',
|
||||
url: 'https://example.com'
|
||||
}
|
||||
*/],
|
||||
helpLink: 'https://about.mattermost.com/default-desktop-app-documentation/',
|
||||
enableServerManagement: true,
|
||||
enableAutoUpdater: true,
|
||||
managedResources: ['trusted'],
|
||||
helpLink: 'https://about.mattermost.com/default-desktop-app-documentation/',
|
||||
enableServerManagement: true,
|
||||
enableAutoUpdater: true,
|
||||
managedResources: ['trusted'],
|
||||
};
|
||||
|
||||
export default buildConfig;
|
||||
|
@@ -7,23 +7,23 @@
|
||||
* @param {number} version - Scheme version. (Not application version)
|
||||
*/
|
||||
const defaultPreferences = {
|
||||
version: 2,
|
||||
teams: [],
|
||||
showTrayIcon: true,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: true,
|
||||
notifications: {
|
||||
flashWindow: 2,
|
||||
bounceIcon: true,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
spellCheckerLocale: 'en-US',
|
||||
darkMode: false,
|
||||
downloadLocation: `/Users/${process.env.USER || process.env.USERNAME}/Downloads`
|
||||
version: 2,
|
||||
teams: [],
|
||||
showTrayIcon: true,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: true,
|
||||
notifications: {
|
||||
flashWindow: 2,
|
||||
bounceIcon: true,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
spellCheckerLocale: 'en-US',
|
||||
darkMode: false,
|
||||
downloadLocation: `/Users/${process.env.USER || process.env.USERNAME}/Downloads`,
|
||||
};
|
||||
|
||||
export default defaultPreferences;
|
||||
|
@@ -1,397 +1,469 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import fs from 'fs';
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import {EventEmitter} from 'events';
|
||||
import {ipcMain, nativeTheme, app} from 'electron';
|
||||
import log from 'electron-log';
|
||||
|
||||
import * as Validator from '../../main/Validator';
|
||||
|
||||
import {UPDATE_TEAMS, GET_CONFIGURATION, UPDATE_CONFIGURATION, GET_LOCAL_CONFIGURATION} from 'common/communication';
|
||||
|
||||
import defaultPreferences from './defaultPreferences';
|
||||
import upgradeConfigData from './upgradePreferences';
|
||||
import buildConfig from './buildConfig';
|
||||
import RegistryConfig, {REGISTRY_READ_EVENT} from './RegistryConfig';
|
||||
|
||||
/**
|
||||
* Handles loading and merging all sources of configuration as well as saving user provided config
|
||||
*/
|
||||
export default class Config extends EventEmitter {
|
||||
constructor(configFilePath, registryConfigData = {teams: []}) {
|
||||
super();
|
||||
this.configFilePath = configFilePath;
|
||||
this.registryConfigData = registryConfigData;
|
||||
this.reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all sources of config data
|
||||
*
|
||||
* @param {boolean} synchronize determines whether or not to emit a synchronize event once config has been reloaded
|
||||
* @emits {update} emitted once all data has been loaded and merged
|
||||
* @emits {synchronize} emitted when requested by a call to method; used to notify other config instances of changes
|
||||
*/
|
||||
reload(synchronize = false) {
|
||||
this.defaultConfigData = this.loadDefaultConfigData();
|
||||
this.buildConfigData = this.loadBuildConfigData();
|
||||
|
||||
this.localConfigData = this.loadLocalConfigFile();
|
||||
this.localConfigData = this.checkForConfigUpdates(this.localConfigData);
|
||||
|
||||
this.regenerateCombinedConfigData();
|
||||
|
||||
this.emit('update', this.combinedData);
|
||||
|
||||
if (synchronize) {
|
||||
this.emit('synchronize');
|
||||
constructor(configFilePath) {
|
||||
super();
|
||||
this.configFilePath = configFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to save a single config property
|
||||
*
|
||||
* @param {string} key name of config property to be saved
|
||||
* @param {*} data value to save for provided key
|
||||
*/
|
||||
set(key, data) {
|
||||
if (key) {
|
||||
this.localConfigData[key] = data;
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
// separating constructor from init so main can setup event listeners
|
||||
init = () => {
|
||||
this.registryConfig = new RegistryConfig();
|
||||
this.registryConfig.once(REGISTRY_READ_EVENT, this.loadRegistry);
|
||||
this.registryConfig.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to save an array of config properties in one go
|
||||
*
|
||||
* @param {array} properties an array of config properties to save
|
||||
*/
|
||||
setMultiple(properties = []) {
|
||||
if (properties.length) {
|
||||
properties.forEach(({key, data}) => {
|
||||
if (key) {
|
||||
this.localConfigData[key] = data;
|
||||
/**
|
||||
* Gets the teams from registry into the config object and reload
|
||||
*
|
||||
* @param {object} registryData Team configuration from the registry and if teams can be managed by user
|
||||
*/
|
||||
|
||||
loadRegistry = (registryData) => {
|
||||
this.registryConfigData = registryData;
|
||||
this.reload();
|
||||
ipcMain.handle(GET_CONFIGURATION, this.handleGetConfiguration);
|
||||
ipcMain.handle(GET_LOCAL_CONFIGURATION, this.handleGetLocalConfiguration);
|
||||
ipcMain.handle(UPDATE_TEAMS, this.handleUpdateTeams);
|
||||
ipcMain.on(UPDATE_CONFIGURATION, this.setMultiple);
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
nativeTheme.on('updated', this.handleUpdateTheme);
|
||||
}
|
||||
});
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
}
|
||||
}
|
||||
|
||||
setRegistryConfigData(registryConfigData = {teams: []}) {
|
||||
this.registryConfigData = Object.assign({}, registryConfigData);
|
||||
this.reload();
|
||||
}
|
||||
/**
|
||||
* Reload all sources of config data
|
||||
*
|
||||
* @param {boolean} synchronize determines whether or not to emit a synchronize event once config has been reloaded
|
||||
* @emits {update} emitted once all data has been loaded and merged
|
||||
* @emits {synchronize} emitted when requested by a call to method; used to notify other config instances of changes
|
||||
*/
|
||||
reload = () => {
|
||||
this.defaultConfigData = this.loadDefaultConfigData();
|
||||
this.buildConfigData = this.loadBuildConfigData();
|
||||
this.localConfigData = this.loadLocalConfigFile();
|
||||
this.localConfigData = this.checkForConfigUpdates(this.localConfigData);
|
||||
this.regenerateCombinedConfigData();
|
||||
|
||||
/**
|
||||
* Used to replace the existing config data with new config data
|
||||
*
|
||||
* @param {object} configData a new, config data object to completely replace the existing config data
|
||||
*/
|
||||
replace(configData) {
|
||||
const newConfigData = configData;
|
||||
|
||||
this.localConfigData = Object.assign({}, this.localConfigData, newConfigData);
|
||||
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to save the current set of local config data to disk
|
||||
*
|
||||
* @emits {update} emitted once all data has been saved
|
||||
* @emits {synchronize} emitted once all data has been saved; used to notify other config instances of changes
|
||||
* @emits {error} emitted if saving local config data to file fails
|
||||
*/
|
||||
saveLocalConfigData() {
|
||||
try {
|
||||
this.writeFile(this.configFilePath, this.localConfigData, (error) => {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
this.emit('update', this.combinedData);
|
||||
this.emit('synchronize');
|
||||
});
|
||||
} catch (error) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
}
|
||||
|
||||
// getters for accessing the various config data inputs
|
||||
|
||||
get data() {
|
||||
return this.combinedData;
|
||||
}
|
||||
get localData() {
|
||||
return this.localConfigData;
|
||||
}
|
||||
get defaultData() {
|
||||
return this.defaultConfigData;
|
||||
}
|
||||
get buildData() {
|
||||
return this.buildConfigData;
|
||||
}
|
||||
get registryData() {
|
||||
return this.registryConfigData;
|
||||
}
|
||||
|
||||
// convenience getters
|
||||
|
||||
get version() {
|
||||
return this.combinedData.version;
|
||||
}
|
||||
get teams() {
|
||||
return this.combinedData.teams;
|
||||
}
|
||||
get darkMode() {
|
||||
return this.combinedData.darkMode;
|
||||
}
|
||||
get localTeams() {
|
||||
return this.localConfigData.teams;
|
||||
}
|
||||
get predefinedTeams() {
|
||||
return [...this.buildConfigData.defaultTeams, ...this.registryConfigData.teams];
|
||||
}
|
||||
get enableHardwareAcceleration() {
|
||||
return this.combinedData.enableHardwareAcceleration;
|
||||
}
|
||||
get enableServerManagement() {
|
||||
return this.combinedData.enableServerManagement;
|
||||
}
|
||||
get enableAutoUpdater() {
|
||||
return this.combinedData.enableAutoUpdater;
|
||||
}
|
||||
get autostart() {
|
||||
return this.combinedData.autostart;
|
||||
}
|
||||
get notifications() {
|
||||
return this.combinedData.notifications;
|
||||
}
|
||||
get showUnreadBadge() {
|
||||
return this.combinedData.showUnreadBadge;
|
||||
}
|
||||
get useSpellChecker() {
|
||||
return this.combinedData.useSpellChecker;
|
||||
}
|
||||
get spellCheckerLocale() {
|
||||
return this.combinedData.spellCheckerLocale;
|
||||
}
|
||||
get showTrayIcon() {
|
||||
return this.combinedData.showTrayIcon;
|
||||
}
|
||||
get trayIconTheme() {
|
||||
return this.combinedData.trayIconTheme;
|
||||
}
|
||||
get helpLink() {
|
||||
return this.combinedData.helpLink;
|
||||
}
|
||||
|
||||
// initialization/processing methods
|
||||
|
||||
/**
|
||||
* Returns a copy of the app's default config data
|
||||
*/
|
||||
loadDefaultConfigData() {
|
||||
return this.copy(defaultPreferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the app's build config data
|
||||
*/
|
||||
loadBuildConfigData() {
|
||||
return this.copy(buildConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns locally stored config data from the filesystem or returns app defaults if no file is found
|
||||
*/
|
||||
loadLocalConfigFile() {
|
||||
let configData = {};
|
||||
try {
|
||||
configData = this.readFileSync(this.configFilePath);
|
||||
|
||||
// validate based on config file version
|
||||
if (configData.version > 1) {
|
||||
configData = Validator.validateV2ConfigData(configData);
|
||||
} else {
|
||||
switch (configData.version) {
|
||||
case 1:
|
||||
configData = Validator.validateV1ConfigData(configData);
|
||||
break;
|
||||
default:
|
||||
configData = Validator.validateV0ConfigData(configData);
|
||||
/**
|
||||
* Used to save a single config property
|
||||
*
|
||||
* @param {string} key name of config property to be saved
|
||||
* @param {*} data value to save for provided key
|
||||
*/
|
||||
set = (key, data) => {
|
||||
if (key) {
|
||||
this.localConfigData[key] = data;
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
}
|
||||
}
|
||||
if (!configData) {
|
||||
throw new Error('Provided configuration file does not validate, using defaults instead.');
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Failed to load configuration file from the filesystem. Using defaults.');
|
||||
configData = this.copy(this.defaultConfigData);
|
||||
|
||||
// add default team to teams if one exists and there arent currently any teams
|
||||
if (!configData.teams.length && this.defaultConfigData.defaultTeam) {
|
||||
configData.teams.push(this.defaultConfigData.defaultTeam);
|
||||
}
|
||||
delete configData.defaultTeam;
|
||||
|
||||
this.writeFileSync(this.configFilePath, configData);
|
||||
}
|
||||
return configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if locally stored data needs to be updated and upgrades as needed
|
||||
*
|
||||
* @param {*} data locally stored data
|
||||
*/
|
||||
checkForConfigUpdates(data) {
|
||||
let configData = data;
|
||||
try {
|
||||
if (configData.version !== this.defaultConfigData.version) {
|
||||
configData = upgradeConfigData(configData);
|
||||
this.writeFileSync(this.configFilePath, configData);
|
||||
console.log(`Configuration updated to version ${this.defaultConfigData.version} successfully.`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Failed to update configuration to version ${this.defaultConfigData.version}.`);
|
||||
}
|
||||
return configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Properly combines all sources of data into a single, manageable set of all config data
|
||||
*/
|
||||
regenerateCombinedConfigData() {
|
||||
// combine all config data in the correct order
|
||||
this.combinedData = Object.assign({}, this.defaultConfigData, this.localConfigData, this.buildConfigData, this.registryConfigData);
|
||||
|
||||
// remove unecessary data pulled from default and build config
|
||||
delete this.combinedData.defaultTeam;
|
||||
delete this.combinedData.defaultTeams;
|
||||
|
||||
// IMPORTANT: properly combine teams from all sources
|
||||
let combinedTeams = [];
|
||||
|
||||
// - start by adding default teams from buildConfig, if any
|
||||
if (this.buildConfigData.defaultTeams && this.buildConfigData.defaultTeams.length) {
|
||||
combinedTeams.push(...this.buildConfigData.defaultTeams);
|
||||
}
|
||||
|
||||
// - add registry defined teams, if any
|
||||
if (this.registryConfigData.teams && this.registryConfigData.teams.length) {
|
||||
combinedTeams.push(...this.registryConfigData.teams);
|
||||
/**
|
||||
* Used to save an array of config properties in one go
|
||||
*
|
||||
* @param {array} properties an array of config properties to save
|
||||
*/
|
||||
setMultiple = (event, properties = []) => {
|
||||
if (properties.length) {
|
||||
properties.forEach(({key, data}) => {
|
||||
if (key) {
|
||||
this.localConfigData[key] = data;
|
||||
}
|
||||
});
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
}
|
||||
|
||||
return this.localConfigData; //this is the only part that changes
|
||||
}
|
||||
|
||||
// - add locally defined teams only if server management is enabled
|
||||
if (this.enableServerManagement) {
|
||||
combinedTeams.push(...this.localConfigData.teams);
|
||||
setRegistryConfigData = (registryConfigData = {teams: []}) => {
|
||||
this.registryConfigData = Object.assign({}, registryConfigData);
|
||||
this.reload();
|
||||
}
|
||||
|
||||
combinedTeams = this.filterOutDuplicateTeams(combinedTeams);
|
||||
combinedTeams = this.sortUnorderedTeams(combinedTeams);
|
||||
/**
|
||||
* Used to replace the existing config data with new config data
|
||||
*
|
||||
* @param {object} configData a new, config data object to completely replace the existing config data
|
||||
*/
|
||||
replace = (configData) => {
|
||||
const newConfigData = configData;
|
||||
|
||||
this.combinedData.teams = combinedTeams;
|
||||
this.combinedData.localTeams = this.localConfigData.teams;
|
||||
this.combinedData.buildTeams = this.buildConfigData.defaultTeams;
|
||||
this.combinedData.registryTeams = this.registryConfigData.teams;
|
||||
}
|
||||
this.localConfigData = Object.assign({}, this.localConfigData, newConfigData);
|
||||
|
||||
/**
|
||||
* Returns the provided list of teams with duplicates filtered out
|
||||
*
|
||||
* @param {array} teams array of teams to check for duplicates
|
||||
*/
|
||||
filterOutDuplicateTeams(teams) {
|
||||
let newTeams = teams;
|
||||
const uniqueURLs = new Set();
|
||||
newTeams = newTeams.filter((team) => {
|
||||
return uniqueURLs.has(team.url) ? false : uniqueURLs.add(team.url);
|
||||
});
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided array fo teams with existing teams filtered out
|
||||
* @param {array} teams array of teams to check for already defined teams
|
||||
*/
|
||||
filterOutPredefinedTeams(teams) {
|
||||
let newTeams = teams;
|
||||
|
||||
// filter out predefined teams
|
||||
newTeams = newTeams.filter((newTeam) => {
|
||||
return this.predefinedTeams.findIndex((existingTeam) => newTeam.url === existingTeam.url) === -1; // eslint-disable-line max-nested-callbacks
|
||||
});
|
||||
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a default sort order to the team list, if no order is specified.
|
||||
* @param {array} teams to sort
|
||||
*/
|
||||
sortUnorderedTeams(teams) {
|
||||
// We want to preserve the array order of teams in the config, otherwise a lot of bugs will occur
|
||||
const mappedTeams = teams.map((team, index) => ({team, originalOrder: index}));
|
||||
|
||||
// Make a best pass at interpreting sort order. If an order is not specified, assume it is 0.
|
||||
//
|
||||
const newTeams = mappedTeams.sort((x, y) => {
|
||||
if (x.team.order == null) {
|
||||
x.team.order = 0;
|
||||
}
|
||||
if (y.team.order == null) {
|
||||
y.team.order = 0;
|
||||
}
|
||||
|
||||
// once we ensured `order` exists, we can sort numerically
|
||||
return x.team.order - y.team.order;
|
||||
});
|
||||
|
||||
// Now re-number all items from 0 to (max), ensuring user's sort order is preserved. The
|
||||
// new tabbed interface requires an item with order:0 in order to raise the first tab.
|
||||
//
|
||||
newTeams.forEach((mappedTeam, i) => {
|
||||
mappedTeam.team.order = i;
|
||||
});
|
||||
|
||||
return newTeams.sort((x, y) => x.originalOrder - y.originalOrder).map((mappedTeam) => mappedTeam.team);
|
||||
}
|
||||
|
||||
// helper functions
|
||||
|
||||
readFileSync(filePath) {
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
writeFile(filePath, configData, callback) {
|
||||
if (configData.version !== this.defaultConfigData.version) {
|
||||
throw new Error('version ' + configData.version + ' is not equal to ' + this.defaultConfigData.version);
|
||||
}
|
||||
const json = JSON.stringify(configData, null, ' ');
|
||||
fs.writeFile(filePath, json, 'utf8', callback);
|
||||
}
|
||||
|
||||
writeFileSync(filePath, config) {
|
||||
if (config.version !== this.defaultConfigData.version) {
|
||||
throw new Error('version ' + config.version + ' is not equal to ' + this.defaultConfigData.version);
|
||||
this.regenerateCombinedConfigData();
|
||||
this.saveLocalConfigData();
|
||||
}
|
||||
|
||||
const dir = path.dirname(filePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
/**
|
||||
* Used to save the current set of local config data to disk
|
||||
*
|
||||
* @emits {update} emitted once all data has been saved
|
||||
* @emits {synchronize} emitted once all data has been saved; used to notify other config instances of changes
|
||||
* @emits {error} emitted if saving local config data to file fails
|
||||
*/
|
||||
saveLocalConfigData = () => {
|
||||
try {
|
||||
this.writeFile(this.configFilePath, this.localConfigData, (error) => {
|
||||
if (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
this.emit('update', this.combinedData);
|
||||
this.emit('synchronize');
|
||||
});
|
||||
} catch (error) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
}
|
||||
|
||||
const json = JSON.stringify(config, null, ' ');
|
||||
fs.writeFileSync(filePath, json, 'utf8');
|
||||
}
|
||||
// getters for accessing the various config data inputs
|
||||
|
||||
merge(base, target) {
|
||||
return Object.assign({}, base, target);
|
||||
}
|
||||
get data() {
|
||||
return this.combinedData;
|
||||
}
|
||||
get localData() {
|
||||
return this.localConfigData;
|
||||
}
|
||||
get defaultData() {
|
||||
return this.defaultConfigData;
|
||||
}
|
||||
get buildData() {
|
||||
return this.buildConfigData;
|
||||
}
|
||||
get registryData() {
|
||||
return this.registryConfigData;
|
||||
}
|
||||
|
||||
copy(data) {
|
||||
return Object.assign({}, data);
|
||||
}
|
||||
// convenience getters
|
||||
|
||||
get version() {
|
||||
return this.combinedData.version;
|
||||
}
|
||||
get teams() {
|
||||
return this.combinedData.teams;
|
||||
}
|
||||
get darkMode() {
|
||||
return this.combinedData.darkMode;
|
||||
}
|
||||
get localTeams() {
|
||||
return this.localConfigData.teams;
|
||||
}
|
||||
get predefinedTeams() {
|
||||
return [...this.buildConfigData.defaultTeams, ...this.registryConfigData.teams];
|
||||
}
|
||||
get enableHardwareAcceleration() {
|
||||
return this.combinedData.enableHardwareAcceleration;
|
||||
}
|
||||
get enableServerManagement() {
|
||||
return this.combinedData.enableServerManagement;
|
||||
}
|
||||
get enableAutoUpdater() {
|
||||
return this.combinedData.enableAutoUpdater;
|
||||
}
|
||||
get autostart() {
|
||||
return this.combinedData.autostart;
|
||||
}
|
||||
get notifications() {
|
||||
return this.combinedData.notifications;
|
||||
}
|
||||
get showUnreadBadge() {
|
||||
return this.combinedData.showUnreadBadge;
|
||||
}
|
||||
get useSpellChecker() {
|
||||
return this.combinedData.useSpellChecker;
|
||||
}
|
||||
get spellCheckerLocale() {
|
||||
return this.combinedData.spellCheckerLocale;
|
||||
}
|
||||
get showTrayIcon() {
|
||||
return this.combinedData.showTrayIcon;
|
||||
}
|
||||
get trayIconTheme() {
|
||||
return this.combinedData.trayIconTheme;
|
||||
}
|
||||
get helpLink() {
|
||||
return this.combinedData.helpLink;
|
||||
}
|
||||
|
||||
// initialization/processing methods
|
||||
|
||||
/**
|
||||
* Returns a copy of the app's default config data
|
||||
*/
|
||||
loadDefaultConfigData = () => {
|
||||
return this.copy(defaultPreferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the app's build config data
|
||||
*/
|
||||
loadBuildConfigData = () => {
|
||||
return this.copy(buildConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns locally stored config data from the filesystem or returns app defaults if no file is found
|
||||
*/
|
||||
loadLocalConfigFile = () => {
|
||||
let configData = {};
|
||||
try {
|
||||
configData = this.readFileSync(this.configFilePath);
|
||||
|
||||
// validate based on config file version
|
||||
if (configData.version > 1) {
|
||||
configData = Validator.validateV2ConfigData(configData);
|
||||
} else {
|
||||
switch (configData.version) {
|
||||
case 1:
|
||||
configData = Validator.validateV1ConfigData(configData);
|
||||
break;
|
||||
default:
|
||||
configData = Validator.validateV0ConfigData(configData);
|
||||
}
|
||||
}
|
||||
if (!configData) {
|
||||
throw new Error('Provided configuration file does not validate, using defaults instead.');
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn('Failed to load configuration file from the filesystem. Using defaults.');
|
||||
configData = this.copy(this.defaultConfigData);
|
||||
|
||||
// add default team to teams if one exists and there arent currently any teams
|
||||
if (!configData.teams.length && this.defaultConfigData.defaultTeam) {
|
||||
configData.teams.push(this.defaultConfigData.defaultTeam);
|
||||
}
|
||||
delete configData.defaultTeam;
|
||||
|
||||
this.writeFileSync(this.configFilePath, configData);
|
||||
}
|
||||
return configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if locally stored data needs to be updated and upgrades as needed
|
||||
*
|
||||
* @param {*} data locally stored data
|
||||
*/
|
||||
checkForConfigUpdates = (data) => {
|
||||
let configData = data;
|
||||
try {
|
||||
if (configData.version !== this.defaultConfigData.version) {
|
||||
configData = upgradeConfigData(configData);
|
||||
this.writeFileSync(this.configFilePath, configData);
|
||||
log.info(`Configuration updated to version ${this.defaultConfigData.version} successfully.`);
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Failed to update configuration to version ${this.defaultConfigData.version}.`);
|
||||
}
|
||||
return configData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Properly combines all sources of data into a single, manageable set of all config data
|
||||
*/
|
||||
regenerateCombinedConfigData = () => {
|
||||
// combine all config data in the correct order
|
||||
this.combinedData = Object.assign({}, this.defaultConfigData, this.localConfigData, this.buildConfigData, this.registryConfigData);
|
||||
|
||||
// remove unecessary data pulled from default and build config
|
||||
delete this.combinedData.defaultTeam;
|
||||
delete this.combinedData.defaultTeams;
|
||||
|
||||
// IMPORTANT: properly combine teams from all sources
|
||||
let combinedTeams = [];
|
||||
|
||||
// - start by adding default teams from buildConfig, if any
|
||||
if (this.buildConfigData.defaultTeams && this.buildConfigData.defaultTeams.length) {
|
||||
combinedTeams.push(...this.buildConfigData.defaultTeams);
|
||||
}
|
||||
|
||||
// - add registry defined teams, if any
|
||||
if (this.registryConfigData.teams && this.registryConfigData.teams.length) {
|
||||
combinedTeams.push(...this.registryConfigData.teams);
|
||||
}
|
||||
|
||||
// - add locally defined teams only if server management is enabled
|
||||
if (this.enableServerManagement) {
|
||||
combinedTeams.push(...this.localConfigData.teams);
|
||||
}
|
||||
|
||||
combinedTeams = this.filterOutDuplicateTeams(combinedTeams);
|
||||
combinedTeams = this.sortUnorderedTeams(combinedTeams);
|
||||
|
||||
this.combinedData.teams = combinedTeams;
|
||||
this.combinedData.localTeams = this.localConfigData.teams;
|
||||
this.combinedData.buildTeams = this.buildConfigData.defaultTeams;
|
||||
this.combinedData.registryTeams = this.registryConfigData.teams;
|
||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
||||
this.combinedData.darkMode = nativeTheme.shouldUseDarkColors;
|
||||
}
|
||||
this.combinedData.appName = app.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided list of teams with duplicates filtered out
|
||||
*
|
||||
* @param {array} teams array of teams to check for duplicates
|
||||
*/
|
||||
filterOutDuplicateTeams = (teams) => {
|
||||
let newTeams = teams;
|
||||
const uniqueURLs = new Set();
|
||||
newTeams = newTeams.filter((team) => {
|
||||
return uniqueURLs.has(team.url) ? false : uniqueURLs.add(team.url);
|
||||
});
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided array fo teams with existing teams filtered out
|
||||
* @param {array} teams array of teams to check for already defined teams
|
||||
*/
|
||||
filterOutPredefinedTeams = (teams) => {
|
||||
let newTeams = teams;
|
||||
|
||||
// filter out predefined teams
|
||||
newTeams = newTeams.filter((newTeam) => {
|
||||
return this.predefinedTeams.findIndex((existingTeam) => newTeam.url === existingTeam.url) === -1; // eslint-disable-line max-nested-callbacks
|
||||
});
|
||||
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a default sort order to the team list, if no order is specified.
|
||||
* @param {array} teams to sort
|
||||
*/
|
||||
sortUnorderedTeams = (teams) => {
|
||||
// We want to preserve the array order of teams in the config, otherwise a lot of bugs will occur
|
||||
const mappedTeams = teams.map((team, index) => ({team, originalOrder: index}));
|
||||
|
||||
// Make a best pass at interpreting sort order. If an order is not specified, assume it is 0.
|
||||
//
|
||||
const newTeams = mappedTeams.sort((x, y) => {
|
||||
if (x.team.order == null) {
|
||||
x.team.order = 0;
|
||||
}
|
||||
if (y.team.order == null) {
|
||||
y.team.order = 0;
|
||||
}
|
||||
|
||||
// once we ensured `order` exists, we can sort numerically
|
||||
return x.team.order - y.team.order;
|
||||
});
|
||||
|
||||
// Now re-number all items from 0 to (max), ensuring user's sort order is preserved. The
|
||||
// new tabbed interface requires an item with order:0 in order to raise the first tab.
|
||||
//
|
||||
newTeams.forEach((mappedTeam, i) => {
|
||||
mappedTeam.team.order = i;
|
||||
});
|
||||
|
||||
return newTeams.sort((x, y) => x.originalOrder - y.originalOrder).map((mappedTeam) => mappedTeam.team);
|
||||
}
|
||||
|
||||
// helper functions
|
||||
|
||||
readFileSync = (filePath) => {
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
writeFile = (filePath, configData, callback) => {
|
||||
if (configData.version !== this.defaultConfigData.version) {
|
||||
throw new Error('version ' + configData.version + ' is not equal to ' + this.defaultConfigData.version);
|
||||
}
|
||||
const json = JSON.stringify(configData, null, ' ');
|
||||
fs.writeFile(filePath, json, 'utf8', callback);
|
||||
}
|
||||
|
||||
writeFileSync = (filePath, config) => {
|
||||
if (config.version !== this.defaultConfigData.version) {
|
||||
throw new Error('version ' + config.version + ' is not equal to ' + this.defaultConfigData.version);
|
||||
}
|
||||
|
||||
const dir = path.dirname(filePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
const json = JSON.stringify(config, null, ' ');
|
||||
fs.writeFileSync(filePath, json, 'utf8');
|
||||
}
|
||||
|
||||
merge = (base, target) => {
|
||||
return Object.assign({}, base, target);
|
||||
}
|
||||
|
||||
copy = (data) => {
|
||||
return Object.assign({}, data);
|
||||
}
|
||||
|
||||
handleGetConfiguration = (event, option) => {
|
||||
const config = {...this.combinedData};
|
||||
if (option) {
|
||||
return config[option];
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
handleGetLocalConfiguration = (event, option) => {
|
||||
const config = {...this.localConfigData};
|
||||
config.appName = app.name;
|
||||
config.enableServerManagement = this.combinedData.enableServerManagement;
|
||||
if (option) {
|
||||
return config[option];
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
handleUpdateTeams = (event, newTeams) => {
|
||||
this.set('teams', newTeams);
|
||||
return this.combinedData.teams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects changes in darkmode if it is windows or osx, updates the config and propagates the changes
|
||||
* @emits 'darkModeChange'
|
||||
*/
|
||||
handleUpdateTheme = () => {
|
||||
if (this.combinedData.darkMode !== nativeTheme.shouldUseDarkColors) {
|
||||
this.combinedData.darkMode = nativeTheme.shouldUseDarkColors;
|
||||
this.emit('darkModeChange', this.combinedData.darkMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually toggles dark mode for OSes that don't have a native dark mode setting
|
||||
* @emits 'darkModeChange'
|
||||
*/
|
||||
toggleDarkModeManually = () => {
|
||||
this.set('darkMode', !this.combinedData.darkMode);
|
||||
this.emit('darkModeChange', this.combinedData.darkMode);
|
||||
}
|
||||
}
|
||||
|
@@ -4,26 +4,26 @@
|
||||
import defaultPreferences from './defaultPreferences';
|
||||
|
||||
const pastDefaultPreferences = {
|
||||
0: {
|
||||
url: '',
|
||||
},
|
||||
1: {
|
||||
version: 1,
|
||||
teams: [],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
0: {
|
||||
url: '',
|
||||
},
|
||||
1: {
|
||||
version: 1,
|
||||
teams: [],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
spellCheckerLocale: 'en-US',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
spellCheckerLocale: 'en-US',
|
||||
},
|
||||
};
|
||||
|
||||
pastDefaultPreferences[`${defaultPreferences.version}`] = defaultPreferences;
|
||||
|
@@ -4,39 +4,39 @@
|
||||
import pastDefaultPreferences from './pastDefaultPreferences';
|
||||
|
||||
function deepCopy(object) {
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
return JSON.parse(JSON.stringify(object));
|
||||
}
|
||||
|
||||
function upgradeV0toV1(configV0) {
|
||||
const config = deepCopy(pastDefaultPreferences['1']);
|
||||
if (config.version !== 1) {
|
||||
throw new Error('pastDefaultPreferences[\'1\'].version is not equal to 1');
|
||||
}
|
||||
config.teams.push({
|
||||
name: 'Primary team',
|
||||
url: configV0.url,
|
||||
});
|
||||
return config;
|
||||
const config = deepCopy(pastDefaultPreferences['1']);
|
||||
if (config.version !== 1) {
|
||||
throw new Error('pastDefaultPreferences[\'1\'].version is not equal to 1');
|
||||
}
|
||||
config.teams.push({
|
||||
name: 'Primary team',
|
||||
url: configV0.url,
|
||||
});
|
||||
return config;
|
||||
}
|
||||
|
||||
function upgradeV1toV2(configV1) {
|
||||
const config = deepCopy(configV1);
|
||||
config.version = 2;
|
||||
config.teams.forEach((value, index) => {
|
||||
value.order = index;
|
||||
});
|
||||
config.darkMode = false;
|
||||
return config;
|
||||
const config = deepCopy(configV1);
|
||||
config.version = 2;
|
||||
config.teams.forEach((value, index) => {
|
||||
value.order = index;
|
||||
});
|
||||
config.darkMode = false;
|
||||
return config;
|
||||
}
|
||||
|
||||
export default function upgradeToLatest(config) {
|
||||
const configVersion = config.version ? config.version : 0;
|
||||
switch (configVersion) {
|
||||
case 1:
|
||||
return upgradeToLatest(upgradeV1toV2(config));
|
||||
case 0:
|
||||
return upgradeToLatest(upgradeV0toV1(config));
|
||||
default:
|
||||
return config;
|
||||
}
|
||||
const configVersion = config.version ? config.version : 0;
|
||||
switch (configVersion) {
|
||||
case 1:
|
||||
return upgradeToLatest(upgradeV1toV2(config));
|
||||
case 0:
|
||||
return upgradeToLatest(upgradeV0toV1(config));
|
||||
default:
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user