From b54d99ff3d22c0017668199f3f7e7045660c8b1f Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Fri, 17 May 2019 22:05:53 +0200 Subject: [PATCH] allow removing shell integration (fixes #682) --- scripts/build-native.js | 2 +- terminus-core/package.json | 4 ++- .../src/services/shellIntegration.service.ts | 29 +++++++++++++++---- terminus-core/webpack.config.js | 1 + terminus-core/yarn.lock | 17 +++++++---- .../src/components/settingsTab.component.pug | 14 ++++----- .../src/components/settingsTab.component.ts | 14 +++++---- 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/scripts/build-native.js b/scripts/build-native.js index 1a71353b..f9dd24bc 100755 --- a/scripts/build-native.js +++ b/scripts/build-native.js @@ -4,7 +4,7 @@ const path = require('path') const vars = require('./vars') lifecycles = [] -for (let dir of ['app', 'terminus-ssh', 'terminus-terminal']) { +for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) { lifecycles.push([rebuild({ buildPath: path.resolve(__dirname, '../' + dir), electronVersion: vars.electronVersion, diff --git a/terminus-core/package.json b/terminus-core/package.json index 911d9aec..cf7a094c 100644 --- a/terminus-core/package.json +++ b/terminus-core/package.json @@ -27,10 +27,12 @@ "electron-updater": "^2.8.9", "ng2-dnd": "^5.0.2", "ngx-perfect-scrollbar": "^6.0.0", - "rage-edit": "^1.2.0", "shell-escape": "^0.2.0", "universal-analytics": "^0.4.17" }, + "optionalDependencies": { + "windows-native-registry": "^1.0.14" + }, "peerDependencies": { "@angular/animations": "4.0.1", "@angular/common": "4.0.1", diff --git a/terminus-core/src/services/shellIntegration.service.ts b/terminus-core/src/services/shellIntegration.service.ts index e48472c3..3245cbb3 100644 --- a/terminus-core/src/services/shellIntegration.service.ts +++ b/terminus-core/src/services/shellIntegration.service.ts @@ -1,11 +1,14 @@ import * as path from 'path' import * as fs from 'mz/fs' -import { Registry } from 'rage-edit' import { exec } from 'mz/child_process' import { Injectable } from '@angular/core' import { ElectronService } from './electron.service' import { HostAppService, Platform } from './hostApp.service' +try { + var wnr = require('windows-native-registry') // tslint:disable-line +} catch (_) { } // tslint:disable-line + @Injectable({ providedIn: 'root' }) export class ShellIntegrationService { private automatorWorkflows = ['Open Terminus here.workflow', 'Paste path into Terminus.workflow'] @@ -13,11 +16,11 @@ export class ShellIntegrationService { private automatorWorkflowsDestination: string private registryKeys = [ { - path: 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\Open Terminus here', + path: 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here', command: 'open "%V"' }, { - path: 'HKCU\\Software\\Classes\\*\\shell\\Paste path into Terminus', + path: 'Software\\Classes\\*\\shell\\Paste path into Terminus', command: 'paste "%V"' }, ] @@ -50,7 +53,7 @@ export class ShellIntegrationService { if (this.hostApp.platform === Platform.macOS) { return fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0])) } else if (this.hostApp.platform === Platform.Windows) { - return Registry.has(this.registryKeys[0].path) + return !!wnr.getRegistryKey(wnr.HK.CU, this.registryKeys[0].path) } return true } @@ -62,8 +65,22 @@ export class ShellIntegrationService { } } else if (this.hostApp.platform === Platform.Windows) { for (let registryKey of this.registryKeys) { - await Registry.set(registryKey.path, 'Icon', this.electron.app.getPath('exe')) - await Registry.set(registryKey.path + '\\command', '', this.electron.app.getPath('exe') + ' ' + registryKey.command) + wnr.createRegistryKey(wnr.HK.CU, registryKey.path) + wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command') + wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, this.electron.app.getPath('exe')) + wnr.setRegistryValue(wnr.HK.CU, registryKey.path + '\\command', '', wnr.REG.SZ, this.electron.app.getPath('exe') + ' ' + registryKey.command) + } + } + } + + async remove () { + if (this.hostApp.platform === Platform.macOS) { + for (let wf of this.automatorWorkflows) { + await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`) + } + } else if (this.hostApp.platform === Platform.Windows) { + for (let registryKey of this.registryKeys) { + wnr.deleteRegistryKey(wnr.HK.CU, registryKey.path) } } } diff --git a/terminus-core/webpack.config.js b/terminus-core/webpack.config.js index 0cd3baaf..d54acf50 100644 --- a/terminus-core/webpack.config.js +++ b/terminus-core/webpack.config.js @@ -55,6 +55,7 @@ module.exports = { 'untildify', 'winston', 'js-yaml', + 'windows-native-registry', /^rxjs/, /^@angular/, /^@ng-bootstrap/, diff --git a/terminus-core/yarn.lock b/terminus-core/yarn.lock index 2dce9227..d7a483ec 100644 --- a/terminus-core/yarn.lock +++ b/terminus-core/yarn.lock @@ -448,6 +448,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +nan@^2.13.2: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + ng2-dnd@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/ng2-dnd/-/ng2-dnd-5.0.2.tgz#862278ac7dedfa14f5783bbf34014d5d73dfefb4" @@ -486,11 +491,6 @@ qs@~6.5.1: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -rage-edit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/rage-edit/-/rage-edit-1.2.0.tgz#991860a60fef934d8a6d0f057e55786b02f94a2b" - integrity sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg== - request@2.86.0: version "2.86.0" resolved "https://registry.yarnpkg.com/request/-/request-2.86.0.tgz#2b9497f449b0a32654c081a5cf426bbfb5bf5b69" @@ -647,6 +647,13 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +windows-native-registry@^1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.14.tgz#35c742b1278473127cbfb3b76e0db3d1ef626872" + integrity sha512-C2UgyZYJYcPFjkhfNuy09CUa6wXAti4x/tLPgzudDDrqpTyczcgnBEpiablmE6j7E7ownouWTqgVcHW8HJyqhw== + dependencies: + nan "^2.13.2" + winston@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee" diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index 197262e4..5ef5ae98 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -20,14 +20,6 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') i.fas.fa-bug span Report a problem - .form-line(*ngIf='!isShellIntegrationInstalled') - .header - .title Shell integration - .description Allows quickly opening a terminal in the selected folder - button.btn.btn-primary((click)='installShellIntegration()') - i.fas.fa-check - span Install - .form-line .header .title Theme @@ -106,6 +98,12 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') step='0.01' ) + .form-line(*ngIf='hostApp.platform !== Platform.Linux') + .header + .title Shell integration + .description Allows quickly opening a terminal in the selected folder + toggle([ngModel]='isShellIntegrationInstalled', (ngModelChange)='toggleShellIntegration()') + .form-line .header .title Window frame diff --git a/terminus-settings/src/components/settingsTab.component.ts b/terminus-settings/src/components/settingsTab.component.ts index dfa514c3..d382eb3c 100644 --- a/terminus-settings/src/components/settingsTab.component.ts +++ b/terminus-settings/src/components/settingsTab.component.ts @@ -81,6 +81,15 @@ export class SettingsTabComponent extends BaseTabComponent { this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled() } + async toggleShellIntegration () { + if (!this.isShellIntegrationInstalled) { + await this.shellIntegration.install() + } else { + await this.shellIntegration.remove() + } + this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled() + } + async getRecoveryToken (): Promise { return { type: 'app:settings' } } @@ -114,11 +123,6 @@ export class SettingsTabComponent extends BaseTabComponent { } } - async installShellIntegration () { - await this.shellIntegration.install() - this.isShellIntegrationInstalled = true - } - getHotkey (id: string) { let ptr = this.config.store.hotkeys for (let token of id.split(/\./g)) {