From c803adccc14dd510633876120a2695969940c411 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 3 Jun 2021 14:03:04 -0400 Subject: [PATCH 01/12] feat: Remove header brand icon padding on windows OS only --- addons/api/mirage/scenarios/ipc.js | 7 +++++++ ui/desktop/app/routes/application.js | 9 +++++++++ ui/desktop/app/styles/app.scss | 4 ++++ ui/desktop/app/templates/application.hbs | 3 +-- ui/desktop/electron-app/src/index.js | 2 ++ ui/desktop/electron-app/src/ipc/handlers.js | 6 ++++++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index 73eaca8f0..7e20ddaa1 100644 --- a/addons/api/mirage/scenarios/ipc.js +++ b/addons/api/mirage/scenarios/ipc.js @@ -60,6 +60,13 @@ export default function initializeMockIPC(server) { session_id: newSession.id, }; } + + /** + * Check for browser running on windows OS + */ + isWindowsOS() { + return Boolean(window.navigator.userAgent.match(/(windows)/i)); + } } /** diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js index 27493eb33..14ee34db3 100644 --- a/ui/desktop/app/routes/application.js +++ b/ui/desktop/app/routes/application.js @@ -43,6 +43,15 @@ export default class ApplicationRoute extends Route { }); } + /** + * Add windows OS config on controller + */ + async setupController(controller, model) { + super.setupController(controller, model); + const isWindowsOS = await this.ipc.invoke('isWindowsOS'); + this.controllerFor('application').set('isWindowsOS', isWindowsOS); + } + // =actions /** diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index 70706535e..f504cf50a 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -124,6 +124,10 @@ padding-left: sizing.rems(l) * 3; position: relative; + &.header-shrink { + padding-left: 0; + } + .logotype { display: none; } diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 6407a15d2..3a470f935 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -3,9 +3,8 @@ - + - {{#if this.session.isAuthenticated}} {{outlet 'header-nav'}} diff --git a/ui/desktop/electron-app/src/index.js b/ui/desktop/electron-app/src/index.js index 1f220eb85..a251097a5 100644 --- a/ui/desktop/electron-app/src/index.js +++ b/ui/desktop/electron-app/src/index.js @@ -21,6 +21,7 @@ const sessionManager = require('./services/session-manager.js'); const menu = require('./config/menu.js'); const appUpdater = require('./helpers/app-updater.js'); +const { isWindows } = require('./helpers/platform.js'); const isDev = require('electron-is-dev'); // Register the custom file protocol @@ -115,6 +116,7 @@ app.on('ready', async () => { width: 1280, height: 760, titleBarStyle: 'hiddenInset', + frame: !isWindows(), webPreferences: { partition, sandbox: true, diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js index 529fc34a5..ebc4074d7 100644 --- a/ui/desktop/electron-app/src/ipc/handlers.js +++ b/ui/desktop/electron-app/src/ipc/handlers.js @@ -5,6 +5,7 @@ const boundaryCli = require('../cli/index.js'); const sessionManager = require('../services/session-manager.js'); const runtimeSettings = require('../services/runtime-settings.js'); const sanitizer = require('../utils/sanitizer.js'); +const { isWindows } = require('../helpers/platform.js'); /** * Returns the current runtime origin, which is used by the main thread to @@ -64,3 +65,8 @@ handle('connect', ({ target_id, token, host_id }) => * Cancel an established boundary session spawned process. */ handle('stop', ({ session_id }) => sessionManager.stopById(session_id)); + +/** + * Check whether platform is windows + */ +handle('isWindowsOS', () => isWindows()); From 76291896c309ed8f5883b8d6ed2c750320bee130 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 3 Jun 2021 14:28:44 -0400 Subject: [PATCH 02/12] feat: Add window action buttons for windows OS only --- ui/desktop/app/templates/application.hbs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 3a470f935..eca93a021 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -9,8 +9,16 @@ {{outlet 'header-nav'}} + {{/if}} - + + {{#if this.isWindowsOS}} + + + + {{/if}} + + {{#if this.session.isAuthenticated}} - - - {{/if}} + {{/if}} + From 873965d7b71d3e9d7dab26bc33808da7b3a01ddf Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Fri, 4 Jun 2021 12:21:08 -0400 Subject: [PATCH 03/12] feat: Hook in browser actions into electon's BrowserWindow --- addons/api/mirage/scenarios/ipc.js | 8 ++++++++ ui/desktop/app/routes/application.js | 15 +++++++++++++++ ui/desktop/app/styles/app.scss | 7 +++++++ ui/desktop/app/templates/application.hbs | 12 +++++++++--- ui/desktop/electron-app/src/ipc/handlers.js | 20 +++++++++++++++++++- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index 7e20ddaa1..971da832e 100644 --- a/addons/api/mirage/scenarios/ipc.js +++ b/addons/api/mirage/scenarios/ipc.js @@ -67,6 +67,14 @@ export default function initializeMockIPC(server) { isWindowsOS() { return Boolean(window.navigator.userAgent.match(/(windows)/i)); } + + /** + * Do nothing when attempting to minimize, toggle fullscreen, + * and close a browser window + */ + minimizeWindow() {} + closeWindow() {} + toggleFullScreenWindow() {} } /** diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js index 14ee34db3..979684714 100644 --- a/ui/desktop/app/routes/application.js +++ b/ui/desktop/app/routes/application.js @@ -125,4 +125,19 @@ export default class ApplicationRoute extends Route { rootEl.classList.remove('rose-theme-light'); } } + + @action + minimize() { + this.ipc.invoke('minimizeWindow'); + } + + @action + toggleFullScreen() { + this.ipc.invoke('toggleFullscreenWindow'); + } + + @action + close() { + this.ipc.invoke('closeWindow'); + } } diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index f504cf50a..e1c78ae11 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -120,10 +120,17 @@ .rose-header { -webkit-app-region: drag; + -webkit-user-select: none; min-height: sizing.rems(l) * 2; padding-left: sizing.rems(l) * 3; position: relative; + .rose-header-brand, .rose-header-nav, + .rose-header-utilities .rose-dropdown, + .rose-header-utilities button { + -webkit-app-region: no-drag; + } + &.header-shrink { padding-left: 0; } diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index eca93a021..b7728f596 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -13,9 +13,15 @@ {{#if this.isWindowsOS}} - - - + + + {{/if}} {{#if this.session.isAuthenticated}} diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js index ebc4074d7..5fef2534b 100644 --- a/ui/desktop/electron-app/src/ipc/handlers.js +++ b/ui/desktop/electron-app/src/ipc/handlers.js @@ -1,4 +1,4 @@ -const { shell } = require('electron'); +const { shell, BrowserWindow } = require('electron'); const isDev = require('electron-is-dev'); const handle = require('./ipc-handler.js'); const boundaryCli = require('../cli/index.js'); @@ -70,3 +70,21 @@ handle('stop', ({ session_id }) => sessionManager.stopById(session_id)); * Check whether platform is windows */ handle('isWindowsOS', () => isWindows()); + +/** + * Minimize window + */ +handle('minimizeWindow', () => BrowserWindow.getFocusedWindow().minimize()); + +/** + * Toggle fullscreen window + */ +handle('toggleFullscreenWindow', () => { + const window = BrowserWindow.getFocusedWindow(); + window.isMaximized() ? window.unmaximize() : window.maximize(); +}); + +/** + * Close window + */ +handle('closeWindow', () => BrowserWindow.getFocusedWindow().close()); From 196d01aae2d7bbbb78a50ce20d7388371176fed8 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sat, 5 Jun 2021 22:11:47 -0400 Subject: [PATCH 04/12] fix: Fix cli path on windows to launch connect shell --- ui/desktop/electron-app/src/cli/index.js | 11 ++--------- ui/desktop/electron-app/src/cli/path.js | 11 +++++++++++ ui/desktop/electron-app/src/helpers/spawn-promise.js | 10 +++++----- 3 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 ui/desktop/electron-app/src/cli/path.js diff --git a/ui/desktop/electron-app/src/cli/index.js b/ui/desktop/electron-app/src/cli/index.js index 99092ffe3..9af290e0e 100644 --- a/ui/desktop/electron-app/src/cli/index.js +++ b/ui/desktop/electron-app/src/cli/index.js @@ -1,16 +1,9 @@ -const path = require('path'); -const { isWindows } = require('../helpers/platform.js'); const { spawnSync } = require('../helpers/spawn-promise.js'); - -const cliPath = async () => { - let name = 'boundary'; - if (isWindows()) name = 'boundary.exe'; - return path.resolve(__dirname, '..', 'cli', name); -}; +const { path } = require('./path.js'); module.exports = { // Check boundary cli existence - exists: () => Boolean(cliPath()), + exists: () => Boolean(path()), // Returns JSON-formatted version information from the CLI version: () => { diff --git a/ui/desktop/electron-app/src/cli/path.js b/ui/desktop/electron-app/src/cli/path.js new file mode 100644 index 000000000..4e452b0f0 --- /dev/null +++ b/ui/desktop/electron-app/src/cli/path.js @@ -0,0 +1,11 @@ +const path = require('path'); +const { isWindows } = require('../helpers/platform.js'); + +module.exports = { + // Returns boundary cli path + path: () => { + let name = 'boundary'; + if (isWindows()) name = 'boundary.exe'; + return path.resolve(__dirname, '..', '..', 'cli', name); + } +}; diff --git a/ui/desktop/electron-app/src/helpers/spawn-promise.js b/ui/desktop/electron-app/src/helpers/spawn-promise.js index b8ff5d980..af2da4ab3 100644 --- a/ui/desktop/electron-app/src/helpers/spawn-promise.js +++ b/ui/desktop/electron-app/src/helpers/spawn-promise.js @@ -1,8 +1,7 @@ -const path = require('path'); +const { path } = require('../cli/path.js'); const { spawn, spawnSync } = require('child_process'); const jsonify = require('../utils/jsonify.js'); - -const boundaryPath = path.resolve(__dirname, '..', '..', 'cli', 'boundary'); +const { isWindows } = require('../helpers/platform.js'); // You can throw exceptions, or allow them to occur, and this is supported. // Exceptions thrown in this way will be returned to the UI as an @@ -29,7 +28,7 @@ module.exports = { */ spawnAsyncJSONPromise(command) { return new Promise((resolve, reject) => { - const childProcess = spawn(boundaryPath, command); + const childProcess = spawn(path(), command, { shell: isWindows() }); let outputStream = ''; let errorStream = ''; @@ -56,6 +55,7 @@ module.exports = { }; childProcess.stderr.on('error', processError); + childProcess.stderr.on('data', processError); }); }, @@ -66,7 +66,7 @@ module.exports = { * @return {string} */ spawnSync(command) { - const childProcess = spawnSync(boundaryPath, command); + const childProcess = spawnSync(path(), command, { shell: isWindows() }); const rawOutput = childProcess.output.toString(); return rawOutput; }, From fefae2b73d381ea2969eac68f5a74bf924cf641a Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 02:12:39 -0400 Subject: [PATCH 05/12] fix: Fix scrollbars and window minimize/close actions for win --- addons/api/mirage/scenarios/ipc.js | 9 +++- ui/desktop/app/routes/application.js | 9 ++-- ui/desktop/app/styles/app.scss | 47 ++++++++++++++++----- ui/desktop/app/templates/application.hbs | 24 ++++++----- ui/desktop/electron-app/src/index.js | 23 +++++----- ui/desktop/electron-app/src/ipc/handlers.js | 15 ++++--- 6 files changed, 84 insertions(+), 43 deletions(-) diff --git a/addons/api/mirage/scenarios/ipc.js b/addons/api/mirage/scenarios/ipc.js index 971da832e..f8fdf6fde 100644 --- a/addons/api/mirage/scenarios/ipc.js +++ b/addons/api/mirage/scenarios/ipc.js @@ -62,7 +62,14 @@ export default function initializeMockIPC(server) { } /** - * Check for browser running on windows OS + * Check for browsers running on mac OS + */ + isMacOS() { + return Boolean(window.navigator.userAgent.match(/(macintosh)/i)); + } + + /** + * Check for browsers running on windows OS */ isWindowsOS() { return Boolean(window.navigator.userAgent.match(/(windows)/i)); diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js index 979684714..c80f5873e 100644 --- a/ui/desktop/app/routes/application.js +++ b/ui/desktop/app/routes/application.js @@ -44,12 +44,11 @@ export default class ApplicationRoute extends Route { } /** - * Add windows OS config on controller + * Add OS config on controller */ - async setupController(controller, model) { - super.setupController(controller, model); - const isWindowsOS = await this.ipc.invoke('isWindowsOS'); - this.controllerFor('application').set('isWindowsOS', isWindowsOS); + async setupController(controller, ...args) { + controller.set('isMacOS', await this.ipc.invoke('isMacOS')); + controller.set('isWindowsOS', await this.ipc.invoke('isWindowsOS')); } // =actions diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index e1c78ae11..4cf316805 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -29,13 +29,34 @@ .rose-layout-global-body { max-height: 100vh; - overflow: hidden; + overflow: auto; + + main { + flex-grow: 1; + overflow: auto; + } } .rose-layout-sidebar-sidebar, .rose-layout-sidebar-body { overflow-y: scroll; } + + // Windows OS specific overflow. + &.layout-scroll { + .rose-layout-global-body { + overflow-y: auto; + + main { + overflow: unset; + } + } + + .rose-layout-sidebar-sidebar, + .rose-layout-sidebar-body { + overflow-y: unset; + } + } } .rose-nav-sidebar { @@ -122,7 +143,6 @@ -webkit-app-region: drag; -webkit-user-select: none; min-height: sizing.rems(l) * 2; - padding-left: sizing.rems(l) * 3; position: relative; .rose-header-brand, .rose-header-nav, @@ -131,8 +151,20 @@ -webkit-app-region: no-drag; } - &.header-shrink { - padding-left: 0; + &.header-cushion { + padding-left: sizing.rems(l) * 3; + } + + .utilities-actions { + display: flex; + justify-content: center; + + button { + background: transparent; + border: transparent; + color: var(--white); + margin: sizing.rems(xs); + } } .logotype { @@ -225,13 +257,6 @@ white-space: nowrap; } -.rose-layout-global .rose-layout-global-body { - main { - flex-grow: 1; - overflow: auto; - } -} - .branded-card { border: 1px solid var(--ui-border-subtler-1); border-radius: sizing.rems(xxxs); diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index b7728f596..c57d7a85f 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -1,9 +1,9 @@ {{page-title (app-name)}} - + - + {{#if this.session.isAuthenticated}} @@ -13,15 +13,17 @@ {{#if this.isWindowsOS}} - - - + + + + + {{/if}} {{#if this.session.isAuthenticated}} diff --git a/ui/desktop/electron-app/src/index.js b/ui/desktop/electron-app/src/index.js index a251097a5..3e84acb11 100644 --- a/ui/desktop/electron-app/src/index.js +++ b/ui/desktop/electron-app/src/index.js @@ -197,16 +197,19 @@ app.on('before-quit', (event) => { detail: 'Close sessions before quitting?', }; - dialog.showMessageBox(dialogOpts).then((returnValue) => { - switch (returnValue.response) { - case 0: - sessionManager.stopAll(); - break; - default: - event.preventDefault(); - break; - } - }); + const buttonId = dialog.showMessageBoxSync(null, dialogOpts); + buttonId === 0 ? sessionManager.stopAll() : event.preventDefault(); + + // console.log(returnValue.response); + // switch (returnValue.response) { + // case 0: + // sessionManager.stopAll(); + // break; + // default: + // event.preventDefault(); + // break; + // } + // }); } }); diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js index 5fef2534b..d5aac6fb4 100644 --- a/ui/desktop/electron-app/src/ipc/handlers.js +++ b/ui/desktop/electron-app/src/ipc/handlers.js @@ -1,11 +1,11 @@ -const { shell, BrowserWindow } = require('electron'); +const { app, shell, BrowserWindow } = require('electron'); const isDev = require('electron-is-dev'); const handle = require('./ipc-handler.js'); const boundaryCli = require('../cli/index.js'); const sessionManager = require('../services/session-manager.js'); const runtimeSettings = require('../services/runtime-settings.js'); const sanitizer = require('../utils/sanitizer.js'); -const { isWindows } = require('../helpers/platform.js'); +const { isMac, isWindows } = require('../helpers/platform.js'); /** * Returns the current runtime origin, which is used by the main thread to @@ -67,7 +67,12 @@ handle('connect', ({ target_id, token, host_id }) => handle('stop', ({ session_id }) => sessionManager.stopById(session_id)); /** - * Check whether platform is windows + * Check for MacOS OS + */ +handle('isMacOS', () => isMac()); + +/** + * Check for Windows OS */ handle('isWindowsOS', () => isWindows()); @@ -85,6 +90,6 @@ handle('toggleFullscreenWindow', () => { }); /** - * Close window + * Quit app */ -handle('closeWindow', () => BrowserWindow.getFocusedWindow().close()); +handle('closeWindow', () => app.quit()); From c5b00614284201891428e5a5bf9c509ef3319aa6 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 02:47:00 -0400 Subject: [PATCH 06/12] feat: Use tree-kill module to kill sessions on Windows --- ui/desktop/electron-app/package.json | 3 ++- ui/desktop/electron-app/src/models/session.js | 14 ++++++++++++-- ui/desktop/electron-app/yarn.lock | 5 +++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ui/desktop/electron-app/package.json b/ui/desktop/electron-app/package.json index dc7c51310..4091e61a2 100644 --- a/ui/desktop/electron-app/package.json +++ b/ui/desktop/electron-app/package.json @@ -28,7 +28,8 @@ "lookpath": "^1.1.0", "node-html-parser": "^3.1.3", "semver": "^7.3.5", - "shell-quote": "^1.7.2" + "shell-quote": "^1.7.2", + "tree-kill": "^1.2.2" }, "devDependencies": { "@electron-forge/cli": "6.0.0-beta.54", diff --git a/ui/desktop/electron-app/src/models/session.js b/ui/desktop/electron-app/src/models/session.js index a59316f7f..e3deb4d1a 100644 --- a/ui/desktop/electron-app/src/models/session.js +++ b/ui/desktop/electron-app/src/models/session.js @@ -1,5 +1,7 @@ -const { spawnAsyncJSONPromise } = require('../helpers/spawn-promise.js'); +const treeKill = require('tree-kill'); const sanitizer = require('../utils/sanitizer.js'); +const { isWindows } = require('../helpers/platform.js'); +const { spawnAsyncJSONPromise } = require('../helpers/spawn-promise.js'); class Session { #id; @@ -60,10 +62,18 @@ class Session { */ stop() { return new Promise((resolve, reject) => { + debugger; if (this.isRunning) { this.#process.on('close', () => resolve()); this.#process.on('error', (e) => reject(e)); - this.#process.kill(); + /** + * On Windows OS, a spawned process uses cmd.exe to initiate a session. + * Hence, captured process.pid corresponds to cmd.exe instead of session. + * To avoid orphaned session processes and due to lack of node support + * to handle killing processes cleanly in this scenario, + * kill entire dependent process tree on Windows. + */ + isWindows() ? treeKill(this.#process.pid) : this.#process.kill(); } else { // Do nothing when process isn't running resolve(); diff --git a/ui/desktop/electron-app/yarn.lock b/ui/desktop/electron-app/yarn.lock index 3cc17e24f..03995b2ed 100644 --- a/ui/desktop/electron-app/yarn.lock +++ b/ui/desktop/electron-app/yarn.lock @@ -3590,6 +3590,11 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" From 3ffe70cf5dffbf456bf3a2bc37b1657554c50c45 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 02:58:42 -0400 Subject: [PATCH 07/12] fix: Ignore app updater for windows Ignore app updater for windows until first release. Use version packaged at build time in app updater. --- ui/desktop/electron-app/src/helpers/app-updater.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui/desktop/electron-app/src/helpers/app-updater.js b/ui/desktop/electron-app/src/helpers/app-updater.js index 9808931f3..d36d18fff 100644 --- a/ui/desktop/electron-app/src/helpers/app-updater.js +++ b/ui/desktop/electron-app/src/helpers/app-updater.js @@ -4,12 +4,12 @@ const https = require('https'); const semver = require('semver'); const { parse } = require('node-html-parser'); const { autoUpdater, dialog } = require('electron'); -// TODO: Pickup app release version from config file -// const { releaseVersion } = require('../config/forge.config.js'); +const { isWindows } = require('../helpers/platform.js'); +const config = require('../../config/config.js'); +let currentVersion = config.releaseVersion; const debug = process.env.DEBUG_APP_UPDATER; const releasesUrl = 'https://releases.hashicorp.com/boundary-desktop/'; -let currentVersion = '1.0.0'; if (debug && process.env.APP_UPDATER_CURRENT_VERSION) { currentVersion = process.env.APP_UPDATER_CURRENT_VERSION; } @@ -124,6 +124,9 @@ const displayDownloadPrompt = (version, url) => { **/ module.exports = { run: async ({ suppressNoUpdatePrompt } = {}) => { + // Do nothing on Windows - yet + if (isWindows()) return; + let latestVersion; if (debug) { latestVersion = process.env.APP_UPDATER_LATEST_VERSION_TAG; From 243f1656448f1fa551a2e086dc640190dadc7373 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 10:15:34 -0400 Subject: [PATCH 08/12] chore: clean yarn.lock --- yarn.lock | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/yarn.lock b/yarn.lock index d337a2651..71fff24f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7643,7 +7643,7 @@ debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: dependencies: ms "^2.1.1" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -12410,7 +12410,7 @@ import-lazy@^4.0.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -14099,11 +14099,6 @@ lodash._baseflatten@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -14112,16 +14107,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*, lodash._bindcallback@^3.0.0: +lodash._bindcallback@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - lodash._createassigner@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" @@ -14131,19 +14121,12 @@ lodash._createassigner@^3.0.0: lodash._isiterateecall "^3.0.0" lodash.restparam "^3.0.0" -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: +lodash._getnative@^3.0.0: version "3.9.1" resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= @@ -14361,7 +14344,7 @@ lodash.pick@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= -lodash.restparam@*, lodash.restparam@^3.0.0: +lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= From 820843c51dd339b60842b99d14f0a94083cb1c05 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 11:29:23 -0400 Subject: [PATCH 09/12] chore: Fix desktop tests --- ui/desktop/app/routes/application.js | 2 +- ui/desktop/app/styles/app.scss | 5 ++- ui/desktop/app/templates/application.hbs | 23 ++++++++--- ui/desktop/electron-app/src/index.js | 11 ------ .../tests/acceptance/authentication-test.js | 38 ++----------------- ui/desktop/tests/acceptance/projects-test.js | 38 ++----------------- ui/desktop/tests/acceptance/targets-test.js | 38 ++----------------- ui/desktop/tests/helpers/window-mock-ipc.js | 2 + 8 files changed, 33 insertions(+), 124 deletions(-) diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js index c80f5873e..66790a728 100644 --- a/ui/desktop/app/routes/application.js +++ b/ui/desktop/app/routes/application.js @@ -46,7 +46,7 @@ export default class ApplicationRoute extends Route { /** * Add OS config on controller */ - async setupController(controller, ...args) { + async setupController(controller) { controller.set('isMacOS', await this.ipc.invoke('isMacOS')); controller.set('isWindowsOS', await this.ipc.invoke('isWindowsOS')); } diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index 4cf316805..0e74f0a64 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -141,11 +141,12 @@ .rose-header { -webkit-app-region: drag; - -webkit-user-select: none; min-height: sizing.rems(l) * 2; position: relative; + -webkit-user-select: none; - .rose-header-brand, .rose-header-nav, + .rose-header-brand, + .rose-header-nav, .rose-header-utilities .rose-dropdown, .rose-header-utilities button { -webkit-app-region: no-drag; diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index c57d7a85f..2bdaa0da2 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -1,9 +1,16 @@ {{page-title (app-name)}} - + - + {{#if this.session.isAuthenticated}} @@ -14,13 +21,19 @@ {{#if this.isWindowsOS}} - - - diff --git a/ui/desktop/electron-app/src/index.js b/ui/desktop/electron-app/src/index.js index 3e84acb11..1c9c7f6e2 100644 --- a/ui/desktop/electron-app/src/index.js +++ b/ui/desktop/electron-app/src/index.js @@ -199,17 +199,6 @@ app.on('before-quit', (event) => { const buttonId = dialog.showMessageBoxSync(null, dialogOpts); buttonId === 0 ? sessionManager.stopAll() : event.preventDefault(); - - // console.log(returnValue.response); - // switch (returnValue.response) { - // case 0: - // sessionManager.stopAll(); - // break; - // default: - // event.preventDefault(); - // break; - // } - // }); } }); diff --git a/ui/desktop/tests/acceptance/authentication-test.js b/ui/desktop/tests/acceptance/authentication-test.js index 514d1d2b7..c030a22c3 100644 --- a/ui/desktop/tests/acceptance/authentication-test.js +++ b/ui/desktop/tests/acceptance/authentication-test.js @@ -19,14 +19,12 @@ import { authenticateSession, invalidateSession, } from 'ember-simple-auth/test-support'; +import WindowMockIPC from '../helpers/window-mock-ipc'; module('Acceptance | authentication', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); - let mockIPC; - let messageHandler; - const instances = { scopes: { global: null, @@ -102,41 +100,11 @@ module('Acceptance | authentication', function (hooks) { urls.targets = `${urls.projects}/targets`; urls.sessions = `${urls.projects}/sessions`; - class MockIPC { - origin = null; - - invoke(method, payload) { - return this[method](payload); - } - - getOrigin() { - return this.origin; - } - - setOrigin(origin) { - this.origin = origin; - return this.origin; - } - } - - mockIPC = new MockIPC(); - messageHandler = async function (event) { - if (event.origin !== window.location.origin) return; - const { method, payload } = event.data; - if (method) { - const response = await mockIPC.invoke(method, payload); - event.ports[0].postMessage(response); - } - }; - - window.addEventListener('message', messageHandler); + // Mock the postMessage interface used by IPC. + this.owner.register('service:browser/window', WindowMockIPC); setDefaultOrigin(this); }); - hooks.afterEach(function () { - window.removeEventListener('message', messageHandler); - }); - test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) { assert.expect(2); await visit(urls.index); diff --git a/ui/desktop/tests/acceptance/projects-test.js b/ui/desktop/tests/acceptance/projects-test.js index d7978c12f..38d54b480 100644 --- a/ui/desktop/tests/acceptance/projects-test.js +++ b/ui/desktop/tests/acceptance/projects-test.js @@ -18,14 +18,12 @@ import { authenticateSession, invalidateSession, } from 'ember-simple-auth/test-support'; +import WindowMockIPC from '../helpers/window-mock-ipc'; module('Acceptance | projects', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); - let mockIPC; - let messageHandler; - const instances = { scopes: { global: null, @@ -103,41 +101,11 @@ module('Acceptance | projects', function (hooks) { urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`; urls.projects = `${urls.scopes.org}/projects`; - class MockIPC { - origin = null; - - invoke(method, payload) { - return this[method](payload); - } - - getOrigin() { - return this.origin; - } - - setOrigin(origin) { - this.origin = origin; - return this.origin; - } - } - - mockIPC = new MockIPC(); - messageHandler = async function (event) { - if (event.origin !== window.location.origin) return; - const { method, payload } = event.data; - if (method) { - const response = await mockIPC.invoke(method, payload); - event.ports[0].postMessage(response); - } - }; - - window.addEventListener('message', messageHandler); + // Mock the postMessage interface used by IPC. + this.owner.register('service:browser/window', WindowMockIPC); setDefaultOrigin(this); }); - hooks.afterEach(function () { - window.removeEventListener('message', messageHandler); - }); - test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) { invalidateSession(); assert.expect(2); diff --git a/ui/desktop/tests/acceptance/targets-test.js b/ui/desktop/tests/acceptance/targets-test.js index 9d735dbb1..85881b7ec 100644 --- a/ui/desktop/tests/acceptance/targets-test.js +++ b/ui/desktop/tests/acceptance/targets-test.js @@ -19,14 +19,12 @@ import { authenticateSession, invalidateSession, } from 'ember-simple-auth/test-support'; +import WindowMockIPC from '../helpers/window-mock-ipc'; module('Acceptance | targets', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); - let mockIPC; - let messageHandler; - const instances = { scopes: { global: null, @@ -106,41 +104,11 @@ module('Acceptance | targets', function (hooks) { urls.projects = `${urls.scopes.org}/projects`; urls.targets = `${urls.projects}/targets`; - class MockIPC { - origin = null; - - invoke(method, payload) { - return this[method](payload); - } - - getOrigin() { - return this.origin; - } - - setOrigin(origin) { - this.origin = origin; - return this.origin; - } - } - - mockIPC = new MockIPC(); - messageHandler = async function (event) { - if (event.origin !== window.location.origin) return; - const { method, payload } = event.data; - if (method) { - const response = await mockIPC.invoke(method, payload); - event.ports[0].postMessage(response); - } - }; - - window.addEventListener('message', messageHandler); + // Mock the postMessage interface used by IPC. + this.owner.register('service:browser/window', WindowMockIPC); setDefaultOrigin(this); }); - hooks.afterEach(function () { - window.removeEventListener('message', messageHandler); - }); - test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) { invalidateSession(); assert.expect(2); diff --git a/ui/desktop/tests/helpers/window-mock-ipc.js b/ui/desktop/tests/helpers/window-mock-ipc.js index 9d191d87a..18195accb 100644 --- a/ui/desktop/tests/helpers/window-mock-ipc.js +++ b/ui/desktop/tests/helpers/window-mock-ipc.js @@ -17,6 +17,8 @@ class MockIPC { } resetOrigin() {} + isMacOS() {} + isWindowsOS() {} } /** From 2acd555966b788c4e6e0d4c660864d42a8f47978 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Sun, 6 Jun 2021 11:58:57 -0400 Subject: [PATCH 10/12] docs: Update changelog for next release --- ui/desktop/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ui/desktop/CHANGELOG.md b/ui/desktop/CHANGELOG.md index 42bd5a07d..af8dfdc28 100644 --- a/ui/desktop/CHANGELOG.md +++ b/ui/desktop/CHANGELOG.md @@ -2,6 +2,16 @@ Canonical reference for changes, improvements, and bugfixes for Boundary Desktop. +## Next + +### New + +- Add Windows 10 support for client. ([PR](https://github.com/hashicorp/boundary-ui/pull/581)) + +### Bug Fixes + +- Client will show update available prompt when a new version is released. ([PR](https://github.com/hashicorp/boundary-ui/pull/566)) + ## v1.0.1 [CLI 0.2.2] (2021.05.19) ### New From 374a13cd077f19fed6541bd4fe9bcff48718d75c Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Mon, 7 Jun 2021 11:53:15 -0400 Subject: [PATCH 11/12] fix: Remove debugger statement --- ui/desktop/electron-app/src/models/session.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/desktop/electron-app/src/models/session.js b/ui/desktop/electron-app/src/models/session.js index e3deb4d1a..0b95a338b 100644 --- a/ui/desktop/electron-app/src/models/session.js +++ b/ui/desktop/electron-app/src/models/session.js @@ -62,7 +62,6 @@ class Session { */ stop() { return new Promise((resolve, reject) => { - debugger; if (this.isRunning) { this.#process.on('close', () => resolve()); this.#process.on('error', (e) => reject(e)); From 530cd0298ad0828d9a7619afaf9b5fa35e08b3b0 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Mon, 7 Jun 2021 14:18:07 -0400 Subject: [PATCH 12/12] chore: Simplify Windows styles and cli name population --- ui/desktop/app/styles/app.scss | 18 +++++------- ui/desktop/app/templates/application.hbs | 35 ++++++++++++------------ ui/desktop/electron-app/src/cli/path.js | 3 +- 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index 0e74f0a64..d6654da5b 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -42,7 +42,6 @@ overflow-y: scroll; } - // Windows OS specific overflow. &.layout-scroll { .rose-layout-global-body { overflow-y: auto; @@ -156,16 +155,13 @@ padding-left: sizing.rems(l) * 3; } - .utilities-actions { - display: flex; - justify-content: center; - - button { - background: transparent; - border: transparent; - color: var(--white); - margin: sizing.rems(xs); - } + .button-window-minimize, + .button-window-fullscreen, + .button-window-close { + background: transparent; + border: transparent; + color: var(--white); + margin: sizing.rems(xs); } .logotype { diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 2bdaa0da2..262aefcb2 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -20,23 +20,24 @@ {{#if this.isWindowsOS}} - - - - - + + + {{/if}} {{#if this.session.isAuthenticated}} diff --git a/ui/desktop/electron-app/src/cli/path.js b/ui/desktop/electron-app/src/cli/path.js index 4e452b0f0..1bb7aef86 100644 --- a/ui/desktop/electron-app/src/cli/path.js +++ b/ui/desktop/electron-app/src/cli/path.js @@ -4,8 +4,7 @@ const { isWindows } = require('../helpers/platform.js'); module.exports = { // Returns boundary cli path path: () => { - let name = 'boundary'; - if (isWindows()) name = 'boundary.exe'; + const name = isWindows() ? 'boundary.exe' : 'boundary'; return path.resolve(__dirname, '..', '..', 'cli', name); } };