mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-13 07:59:59 +00:00
wip
This commit is contained in:
parent
2e81a1657e
commit
2edcd5b57a
@ -9,6 +9,7 @@ exports.builtinPlugins = [
|
|||||||
'terminus-settings',
|
'terminus-settings',
|
||||||
'terminus-terminal',
|
'terminus-terminal',
|
||||||
'terminus-community-color-schemes',
|
'terminus-community-color-schemes',
|
||||||
|
'terminus-plugin-manager',
|
||||||
]
|
]
|
||||||
exports.version = appInfo.version
|
exports.version = appInfo.version
|
||||||
exports.electronVersion = pkgInfo.devDependencies.electron
|
exports.electronVersion = pkgInfo.devDependencies.electron
|
||||||
|
@ -40,21 +40,9 @@ title-bar(
|
|||||||
)
|
)
|
||||||
i.fa([class]='"fa fa-" + button.icon')
|
i.fa([class]='"fa fa-" + button.icon')
|
||||||
|
|
||||||
.btn-group.window-controls(
|
window-controls(
|
||||||
*ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
|
*ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
|
||||||
)
|
)
|
||||||
button.btn.btn-secondary.btn-minimize.btn-tab-bar(
|
|
||||||
(click)='hostApp.minimize()',
|
|
||||||
)
|
|
||||||
i.fa.fa-window-minimize
|
|
||||||
button.btn.btn-secondary.btn-maximize.btn-tab-bar(
|
|
||||||
(click)='hostApp.toggleMaximize()',
|
|
||||||
)
|
|
||||||
i.fa.fa-window-maximize
|
|
||||||
button.btn.btn-secondary.btn-close.btn-tab-bar(
|
|
||||||
(click)='hostApp.quit()',
|
|
||||||
)
|
|
||||||
i.fa.fa-close
|
|
||||||
|
|
||||||
start-page(*ngIf='ready && app.tabs.length == 0')
|
start-page(*ngIf='ready && app.tabs.length == 0')
|
||||||
|
|
||||||
|
@ -46,17 +46,6 @@ $tab-border-radius: 4px;
|
|||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
&.btn-minimize {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.btn-minimize, &.btn-maximize {
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.btn-close {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&>.tabs {
|
&>.tabs {
|
||||||
@ -71,13 +60,13 @@ $tab-border-radius: 4px;
|
|||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-controls {
|
|
||||||
flex: 0 0 none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.inset {
|
&.inset {
|
||||||
padding-left: 85px;
|
padding-left: 85px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window-controls {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-content {
|
.tabs-content {
|
||||||
|
@ -1,7 +1,2 @@
|
|||||||
.title((dblclick)='hostApp.toggleMaximize()') Terminus
|
.title((dblclick)='hostApp.toggleMaximize()') Terminus
|
||||||
button.btn.btn-secondary.btn-minimize((click)='hostApp.minimize()')
|
window-controls
|
||||||
i.fa.fa-window-minimize
|
|
||||||
button.btn.btn-secondary.btn-maximize((click)='hostApp.toggleMaximize()')
|
|
||||||
i.fa.fa-window-maximize
|
|
||||||
button.btn.btn-secondary.btn-close((click)='hostApp.quit()')
|
|
||||||
i.fa.fa-close
|
|
||||||
|
@ -11,26 +11,6 @@ $titlebar-height: 30px;
|
|||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
flex: none;
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
border-radius: 0;
|
|
||||||
font-size: 8px;
|
|
||||||
width: 40px;
|
|
||||||
padding: 0;
|
|
||||||
line-height: $titlebar-height;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&:not(:hover):not(:active) {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-close {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.inset {
|
&.inset {
|
||||||
flex-basis: 36px;
|
flex-basis: 36px;
|
||||||
|
|
||||||
@ -39,7 +19,7 @@ $titlebar-height: 30px;
|
|||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
window-controls {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
terminus-core/src/components/windowControls.component.pug
Normal file
15
terminus-core/src/components/windowControls.component.pug
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
button.btn.btn-secondary.btn-minimize(
|
||||||
|
(click)='hostApp.minimize()',
|
||||||
|
)
|
||||||
|
svg(version='1.1', width='10', height='10')
|
||||||
|
path(d='M 0,5 10,5 10,6 0,6 Z')
|
||||||
|
button.btn.btn-secondary.btn-maximize(
|
||||||
|
(click)='hostApp.toggleMaximize()',
|
||||||
|
)
|
||||||
|
svg(version='1.1', width='10', height='10')
|
||||||
|
path(d='M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z')
|
||||||
|
button.btn.btn-secondary.btn-close(
|
||||||
|
(click)='hostApp.quit()',
|
||||||
|
)
|
||||||
|
svg(version='1.1', width='10', height='10')
|
||||||
|
path(d='M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z')
|
23
terminus-core/src/components/windowControls.component.scss
Normal file
23
terminus-core/src/components/windowControls.component.scss
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: none;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 0;
|
||||||
|
font-size: 8px;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:not(:hover):not(:active) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
11
terminus-core/src/components/windowControls.component.ts
Normal file
11
terminus-core/src/components/windowControls.component.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core'
|
||||||
|
import { HostAppService } from '../services/hostApp.service'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'window-controls',
|
||||||
|
template: require('./windowControls.component.pug'),
|
||||||
|
styles: [require('./windowControls.component.scss')],
|
||||||
|
})
|
||||||
|
export class WindowControlsComponent {
|
||||||
|
constructor (private hostApp: HostAppService) { }
|
||||||
|
}
|
@ -11,7 +11,6 @@ import { ElectronService } from './services/electron.service'
|
|||||||
import { HostAppService } from './services/hostApp.service'
|
import { HostAppService } from './services/hostApp.service'
|
||||||
import { LogService } from './services/log.service'
|
import { LogService } from './services/log.service'
|
||||||
import { HotkeysService, AppHotkeyProvider } from './services/hotkeys.service'
|
import { HotkeysService, AppHotkeyProvider } from './services/hotkeys.service'
|
||||||
import { NotifyService } from './services/notify.service'
|
|
||||||
import { QuitterService } from './services/quitter.service'
|
import { QuitterService } from './services/quitter.service'
|
||||||
import { DockingService } from './services/docking.service'
|
import { DockingService } from './services/docking.service'
|
||||||
import { TabRecoveryService } from './services/tabRecovery.service'
|
import { TabRecoveryService } from './services/tabRecovery.service'
|
||||||
@ -22,6 +21,7 @@ import { TabBodyComponent } from './components/tabBody.component'
|
|||||||
import { StartPageComponent } from './components/startPage.component'
|
import { StartPageComponent } from './components/startPage.component'
|
||||||
import { TabHeaderComponent } from './components/tabHeader.component'
|
import { TabHeaderComponent } from './components/tabHeader.component'
|
||||||
import { TitleBarComponent } from './components/titleBar.component'
|
import { TitleBarComponent } from './components/titleBar.component'
|
||||||
|
import { WindowControlsComponent } from './components/windowControls.component'
|
||||||
|
|
||||||
import { HotkeyProvider } from './api/hotkeyProvider'
|
import { HotkeyProvider } from './api/hotkeyProvider'
|
||||||
import { ConfigProvider } from './api/configProvider'
|
import { ConfigProvider } from './api/configProvider'
|
||||||
@ -40,7 +40,6 @@ const PROVIDERS = [
|
|||||||
HostAppService,
|
HostAppService,
|
||||||
HotkeysService,
|
HotkeysService,
|
||||||
LogService,
|
LogService,
|
||||||
NotifyService,
|
|
||||||
TabRecoveryService,
|
TabRecoveryService,
|
||||||
ThemesService,
|
ThemesService,
|
||||||
QuitterService,
|
QuitterService,
|
||||||
@ -65,6 +64,7 @@ const PROVIDERS = [
|
|||||||
TabBodyComponent,
|
TabBodyComponent,
|
||||||
TabHeaderComponent,
|
TabHeaderComponent,
|
||||||
TitleBarComponent,
|
TitleBarComponent,
|
||||||
|
WindowControlsComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export default class AppModule {
|
export default class AppModule {
|
||||||
|
@ -91,9 +91,13 @@ export class HotkeysService {
|
|||||||
value.forEach(item => {
|
value.forEach(item => {
|
||||||
item = (typeof item === 'string') ? [item] : item
|
item = (typeof item === 'string') ? [item] : item
|
||||||
|
|
||||||
this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => {
|
try {
|
||||||
this.globalHotkey.emit()
|
this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => {
|
||||||
})
|
this.globalHotkey.emit()
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Could not register the global hotkey:', err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core'
|
|
||||||
import { ToasterService } from 'angular2-toaster'
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class NotifyService {
|
|
||||||
constructor (
|
|
||||||
private toaster: ToasterService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
pop (options) {
|
|
||||||
this.toaster.pop(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
info (title: string, body: string = null) {
|
|
||||||
return this.pop({
|
|
||||||
type: 'info',
|
|
||||||
title, body,
|
|
||||||
timeout: 4000,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
success (title: string, body: string = null) {
|
|
||||||
return this.pop({
|
|
||||||
type: 'success',
|
|
||||||
title, body,
|
|
||||||
timeout: 4000,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
warning (title: string, body: string = null) {
|
|
||||||
return this.pop({
|
|
||||||
type: 'warning',
|
|
||||||
title, body,
|
|
||||||
timeout: 4000,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
error (title: string, body: string = null) {
|
|
||||||
return this.pop({
|
|
||||||
type: 'error',
|
|
||||||
title, body,
|
|
||||||
timeout: 4000,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -76,10 +76,20 @@ $list-group-bg: $body-bg2;
|
|||||||
|
|
||||||
title-bar {
|
title-bar {
|
||||||
background: $body-bg2;
|
background: $body-bg2;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
window-controls {
|
||||||
&:hover { background: $button-hover-bg !important; }
|
svg {
|
||||||
&:active { background: $button-active-bg !important; }
|
transition: 0.25s fill;
|
||||||
|
fill: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover svg {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-close:hover {
|
||||||
|
background: #8a2828;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.0",
|
||||||
"awesome-typescript-loader": "3.1.2",
|
"awesome-typescript-loader": "3.1.2",
|
||||||
"css-loader": "^0.28.0",
|
"css-loader": "^0.28.0",
|
||||||
|
"ngx-pipes": "^1.6.1",
|
||||||
"pug": "^2.0.0-beta11",
|
"pug": "^2.0.0-beta11",
|
||||||
"pug-loader": "^2.3.0",
|
"pug-loader": "^2.3.0",
|
||||||
"raw-loader": "^0.5.1",
|
"raw-loader": "^0.5.1",
|
||||||
|
@ -2,63 +2,81 @@
|
|||||||
strong Error in {{erroredPlugin}}:
|
strong Error in {{erroredPlugin}}:
|
||||||
pre {{errorMessage}}
|
pre {{errorMessage}}
|
||||||
|
|
||||||
|
button.btn.btn-outline-info.btn-sm.pull-right((click)='openPluginsFolder()')
|
||||||
|
i.fa.fa-folder
|
||||||
|
span Plugins folder
|
||||||
|
|
||||||
h3 Installed
|
h3 Installed
|
||||||
|
|
||||||
.list-group
|
.list-group
|
||||||
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
|
ng-container(*ngFor='let plugin of pluginManager.installedPlugins|orderBy:"name"')
|
||||||
.list-group-item.flex-column.align-items-start(*ngIf='knownUpgrades[plugin.name]')
|
.list-group-item.flex-column.align-items-start(*ngIf='knownUpgrades[plugin.name]')
|
||||||
.d-flex.w-100
|
.d-flex.w-100
|
||||||
h5.mr-auto.mb-0 {{plugin.name}}
|
.mr-auto.d-flex.flex-column
|
||||||
|
strong {{plugin.name}}
|
||||||
|
small.text-muted.mb-0 {{plugin.description}}
|
||||||
p.mb-0.mr-3 {{plugin.version}}
|
p.mb-0.mr-3 {{plugin.version}}
|
||||||
button.btn.btn-outline-primary(
|
button.btn.btn-outline-primary(
|
||||||
|
*ngIf='npmInstalled',
|
||||||
(click)='upgradePlugin(plugin)',
|
(click)='upgradePlugin(plugin)',
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
[disabled]='busy[plugin.name] != undefined'
|
||||||
)
|
)
|
||||||
i.fa.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
|
i.fa.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
|
||||||
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
||||||
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
||||||
small.text-muted.mb-0 {{plugin.description}}
|
|
||||||
|
|
||||||
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
|
ng-container(*ngFor='let plugin of pluginManager.installedPlugins|orderBy:"name"')
|
||||||
.list-group-item.flex-column.align-items-start(*ngIf='!knownUpgrades[plugin.name]')
|
.list-group-item.flex-column.align-items-start(*ngIf='!knownUpgrades[plugin.name]')
|
||||||
.d-flex.w-100
|
.d-flex.w-100
|
||||||
h5.mr-auto.mb-0 {{plugin.name}}
|
.mr-auto.d-flex.flex-column
|
||||||
|
strong {{plugin.name}}
|
||||||
|
small.text-muted.mb-0 {{plugin.description}}
|
||||||
p.mb-0.mr-3 {{plugin.version}}
|
p.mb-0.mr-3 {{plugin.version}}
|
||||||
button.btn.btn-outline-danger(
|
button.btn.btn-outline-danger(
|
||||||
(click)='uninstallPlugin(plugin)',
|
(click)='uninstallPlugin(plugin)',
|
||||||
*ngIf='!plugin.isBuiltin',
|
*ngIf='!plugin.isBuiltin && npmInstalled',
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
[disabled]='busy[plugin.name] != undefined'
|
||||||
)
|
)
|
||||||
i.fa.fa-fw.fa-trash-o(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
|
i.fa.fa-fw.fa-trash-o(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
|
||||||
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
|
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
|
||||||
small.text-muted.mb-0 {{plugin.description}}
|
|
||||||
|
.text-center.mt-5(*ngIf='npmMissing')
|
||||||
|
h4 NPM not installed
|
||||||
|
p.mb-2 The Node Package Manager is required to install Terminus plugins.
|
||||||
|
.btn-group
|
||||||
|
button.btn.btn-outline-primary((click)='downloadNPM()')
|
||||||
|
i.fa.fa-download
|
||||||
|
span Download NPM
|
||||||
|
button.btn.btn-outline-info((click)='checkNPM()')
|
||||||
|
i.fa.fa-refresh
|
||||||
|
span Try again
|
||||||
|
|
||||||
|
div(*ngIf='npmInstalled')
|
||||||
|
h3.mt-4 Available
|
||||||
|
|
||||||
|
.input-group.mb-4
|
||||||
|
.input-group-addon
|
||||||
|
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
|
||||||
|
i.fa.fa-fw.fa-search(*ngIf='availablePluginsReady')
|
||||||
|
input.form-control(
|
||||||
|
type='text',
|
||||||
|
'[(ngModel)]'='_1',
|
||||||
|
(ngModelChange)='searchAvailable(_1)',
|
||||||
|
placeholder='Search plugins'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
h3.mt-4 Available
|
.list-group(*ngIf='availablePlugins$')
|
||||||
|
ng-container(*ngFor='let plugin of (availablePlugins$|async|orderBy:"name")')
|
||||||
.input-group.mb-4
|
.list-group-item.flex-column.align-items-start(*ngIf='!isAlreadyInstalled(plugin)')
|
||||||
.input-group-addon
|
.d-flex.w-100
|
||||||
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
|
.mr-auto.d-flex.flex-column
|
||||||
i.fa.fa-fw.fa-search(*ngIf='availablePluginsReady')
|
strong {{plugin.name}}
|
||||||
input.form-control(
|
small.text-muted.mb-0 {{plugin.description}}
|
||||||
type='text',
|
p.mb-0.mr-3 {{plugin.version}}
|
||||||
'[(ngModel)]'='_1',
|
button.btn.btn-outline-primary(
|
||||||
(ngModelChange)='searchAvailable(_1)',
|
(click)='installPlugin(plugin)',
|
||||||
placeholder='Search plugins'
|
[disabled]='busy[plugin.name] != undefined'
|
||||||
)
|
)
|
||||||
|
i.fa.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
|
||||||
|
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
||||||
.list-group(*ngIf='availablePlugins$')
|
|
||||||
ng-container(*ngFor='let plugin of (availablePlugins$|async)')
|
|
||||||
.list-group-item.flex-column.align-items-start(*ngIf='!isAlreadyInstalled(plugin)')
|
|
||||||
.d-flex.w-100
|
|
||||||
h5.mr-auto.mb-0 {{plugin.name}}
|
|
||||||
p.mb-0.mr-3 {{plugin.version}}
|
|
||||||
button.btn.btn-outline-primary(
|
|
||||||
(click)='installPlugin(plugin)',
|
|
||||||
[disabled]='busy[plugin.name] != undefined'
|
|
||||||
)
|
|
||||||
i.fa.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
|
|
||||||
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
|
|
||||||
span Install
|
|
||||||
small.text-muted.mb-0 {{plugin.description}}
|
|
||||||
|
@ -2,7 +2,7 @@ import { BehaviorSubject, Observable } from 'rxjs'
|
|||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
|
|
||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
import { ConfigService } from 'terminus-core'
|
import { ConfigService, HostAppService } from 'terminus-core'
|
||||||
import { IPluginInfo, PluginManagerService } from '../services/pluginManager.service'
|
import { IPluginInfo, PluginManagerService } from '../services/pluginManager.service'
|
||||||
|
|
||||||
enum BusyState { Installing, Uninstalling }
|
enum BusyState { Installing, Uninstalling }
|
||||||
@ -20,9 +20,12 @@ export class PluginsSettingsTabComponent {
|
|||||||
@Input() busy: {[id: string]: BusyState} = {}
|
@Input() busy: {[id: string]: BusyState} = {}
|
||||||
@Input() erroredPlugin: string
|
@Input() erroredPlugin: string
|
||||||
@Input() errorMessage: string
|
@Input() errorMessage: string
|
||||||
|
@Input() npmInstalled = false
|
||||||
|
@Input() npmMissing = false
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
|
private hostApp: HostAppService,
|
||||||
public pluginManager: PluginManagerService
|
public pluginManager: PluginManagerService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@ -42,6 +45,20 @@ export class PluginsSettingsTabComponent {
|
|||||||
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
|
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.checkNPM()
|
||||||
|
}
|
||||||
|
|
||||||
|
openPluginsFolder (): void {
|
||||||
|
this.hostApp.getShell().openItem(this.pluginManager.userPluginsPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadNPM (): void {
|
||||||
|
this.hostApp.getShell().openExternal('https://nodejs.org/en/download/current/')
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkNPM () {
|
||||||
|
this.npmInstalled = await this.pluginManager.isNPMInstalled()
|
||||||
|
this.npmMissing = !this.npmInstalled
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAvailable (query: string) {
|
searchAvailable (query: string) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { BrowserModule } from '@angular/platform-browser'
|
import { BrowserModule } from '@angular/platform-browser'
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
|
import { NgPipesModule } from 'ngx-pipes'
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
|
||||||
import { SettingsTabProvider } from 'terminus-settings'
|
import { SettingsTabProvider } from 'terminus-settings'
|
||||||
@ -14,6 +15,7 @@ import { PluginsSettingsTabProvider } from './settings'
|
|||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
NgbModule,
|
NgbModule,
|
||||||
|
NgPipesModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true },
|
{ provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true },
|
||||||
|
@ -22,6 +22,7 @@ export class PluginManagerService {
|
|||||||
builtinPluginsPath: string = (window as any).builtinPluginsPath
|
builtinPluginsPath: string = (window as any).builtinPluginsPath
|
||||||
userPluginsPath: string = (window as any).userPluginsPath
|
userPluginsPath: string = (window as any).userPluginsPath
|
||||||
installedPlugins: IPluginInfo[] = (window as any).installedPlugins
|
installedPlugins: IPluginInfo[] = (window as any).installedPlugins
|
||||||
|
npmBinary = 'npm'
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
log: LogService,
|
log: LogService,
|
||||||
@ -29,6 +30,15 @@ export class PluginManagerService {
|
|||||||
this.logger = log.create('pluginManager')
|
this.logger = log.create('pluginManager')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async isNPMInstalled (): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await exec(`${this.npmBinary} -v`)
|
||||||
|
return true
|
||||||
|
} catch (_) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listAvailable (query?: string): Observable<IPluginInfo[]> {
|
listAvailable (query?: string): Observable<IPluginInfo[]> {
|
||||||
return Observable
|
return Observable
|
||||||
.fromPromise(
|
.fromPromise(
|
||||||
@ -45,14 +55,14 @@ export class PluginManagerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async installPlugin (plugin: IPluginInfo) {
|
async installPlugin (plugin: IPluginInfo) {
|
||||||
let result = await exec(`npm --prefix "${this.userPluginsPath}" install ${plugin.packageName}@${plugin.version}`)
|
let result = await exec(`${this.npmBinary} --prefix "${this.userPluginsPath}" install ${plugin.packageName}@${plugin.version}`)
|
||||||
console.log(result)
|
console.log(result)
|
||||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||||
this.installedPlugins.push(plugin)
|
this.installedPlugins.push(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
async uninstallPlugin (plugin: IPluginInfo) {
|
async uninstallPlugin (plugin: IPluginInfo) {
|
||||||
await exec(`npm --prefix "${this.userPluginsPath}" remove ${plugin.packageName}`)
|
await exec(`${this.npmBinary} --prefix "${this.userPluginsPath}" remove ${plugin.packageName}`)
|
||||||
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
"build": "webpack --progress --color --display-modules",
|
"build": "webpack --progress --color --display-modules",
|
||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
},
|
},
|
||||||
"files": ["dist"],
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
"author": "Eugene Pankov",
|
"author": "Eugene Pankov",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -17,7 +19,7 @@
|
|||||||
"@types/webpack-env": "1.13.0",
|
"@types/webpack-env": "1.13.0",
|
||||||
"awesome-typescript-loader": "3.1.2",
|
"awesome-typescript-loader": "3.1.2",
|
||||||
"css-loader": "^0.28.0",
|
"css-loader": "^0.28.0",
|
||||||
"ng2-filter-pipe": "^0.1.7",
|
"ngx-pipes": "^1.6.1",
|
||||||
"node-sass": "^4.5.2",
|
"node-sass": "^4.5.2",
|
||||||
"pug": "^2.0.0-beta3",
|
"pug": "^2.0.0-beta3",
|
||||||
"pug-loader": "^2.3.0",
|
"pug-loader": "^2.3.0",
|
||||||
|
@ -13,7 +13,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
|||||||
|
|
||||||
provide (): IToolbarButton[] {
|
provide (): IToolbarButton[] {
|
||||||
return [{
|
return [{
|
||||||
icon: 'cog',
|
icon: 'sliders',
|
||||||
title: 'Settings',
|
title: 'Settings',
|
||||||
weight: 10,
|
weight: 10,
|
||||||
click: () => {
|
click: () => {
|
||||||
|
@ -149,14 +149,14 @@ ngb-tabset.vertical(type='tabs')
|
|||||||
template(ngbTabTitle)
|
template(ngbTabTitle)
|
||||||
| Hotkeys
|
| Hotkeys
|
||||||
template(ngbTabContent)
|
template(ngbTabContent)
|
||||||
input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter.name')
|
input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter')
|
||||||
.form-group
|
.form-group
|
||||||
table.hotkeys-table
|
table.hotkeys-table
|
||||||
tr
|
tr
|
||||||
th Name
|
th Name
|
||||||
th ID
|
th ID
|
||||||
th Hotkey
|
th Hotkey
|
||||||
tr(*ngFor='let hotkey of hotkeyDescriptions|filterBy:hotkeyFilter')
|
tr(*ngFor='let hotkey of hotkeyDescriptions|filterBy:["name"]:hotkeyFilter')
|
||||||
td {{hotkey.name}}
|
td {{hotkey.name}}
|
||||||
td {{hotkey.id}}
|
td {{hotkey.id}}
|
||||||
td
|
td
|
||||||
|
@ -12,7 +12,7 @@ import { SettingsTabProvider } from '../api'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SettingsTabComponent extends BaseTabComponent {
|
export class SettingsTabComponent extends BaseTabComponent {
|
||||||
hotkeyFilter = { name: null }
|
hotkeyFilter = ''
|
||||||
private hotkeyDescriptions: IHotkeyDescription[]
|
private hotkeyDescriptions: IHotkeyDescription[]
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
|
@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
|
|||||||
import { BrowserModule } from '@angular/platform-browser'
|
import { BrowserModule } from '@angular/platform-browser'
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { Ng2FilterPipeModule } from 'ng2-filter-pipe'
|
import { NgPipesModule } from 'ngx-pipes'
|
||||||
|
|
||||||
import { ToolbarButtonProvider, TabRecoveryProvider } from 'terminus-core'
|
import { ToolbarButtonProvider, TabRecoveryProvider } from 'terminus-core'
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
NgbModule,
|
NgbModule,
|
||||||
Ng2FilterPipeModule,
|
NgPipesModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||||
|
@ -29,7 +29,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ test: /schemes\/.*$/, use: "raw-loader" },
|
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.css$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.css$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user