@theia/core 1.24.0-next.21 → 1.24.0-next.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/browser/common-frontend-contribution.d.ts +13 -3
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +63 -4
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +4 -1
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/save-resource-service.d.ts +31 -0
- package/lib/browser/save-resource-service.d.ts.map +1 -0
- package/lib/browser/save-resource-service.js +52 -0
- package/lib/browser/save-resource-service.js.map +1 -0
- package/lib/browser/saveable.d.ts +1 -0
- package/lib/browser/saveable.d.ts.map +1 -1
- package/lib/browser/saveable.js +6 -0
- package/lib/browser/saveable.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +4 -0
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +37 -1
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/side-panel-handler.d.ts +1 -0
- package/lib/browser/shell/side-panel-handler.d.ts.map +1 -1
- package/lib/browser/shell/side-panel-handler.js +7 -2
- package/lib/browser/shell/side-panel-handler.js.map +1 -1
- package/lib/browser/shell/tab-bars.d.ts +4 -2
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +16 -2
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +5 -1
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/widgets/widget.d.ts +6 -1
- package/lib/browser/widgets/widget.d.ts.map +1 -1
- package/lib/browser/widgets/widget.js +30 -1
- package/lib/browser/widgets/widget.js.map +1 -1
- package/lib/electron-main/theia-electron-window.d.ts +0 -4
- package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
- package/lib/electron-main/theia-electron-window.js +0 -21
- package/lib/electron-main/theia-electron-window.js.map +1 -1
- package/package.json +3 -3
- package/src/browser/common-frontend-contribution.ts +73 -8
- package/src/browser/frontend-application-module.ts +5 -1
- package/src/browser/save-resource-service.ts +45 -0
- package/src/browser/saveable.ts +5 -0
- package/src/browser/shell/application-shell.ts +45 -1
- package/src/browser/shell/side-panel-handler.ts +8 -2
- package/src/browser/shell/tab-bars.ts +17 -2
- package/src/browser/style/tabs.css +12 -2
- package/src/browser/view-container.ts +4 -2
- package/src/browser/widgets/widget.ts +29 -1
- package/src/electron-main/theia-electron-window.ts +1 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theia-electron-window.d.ts","sourceRoot":"","sources":["../../src/electron-main/theia-electron-window.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAoF,UAAU,EAAE,MAAM,gDAAgD,CAAC;AAC9J,OAAO,EAAE,aAAa,EAAE,+BAA+B,
|
|
1
|
+
{"version":3,"file":"theia-electron-window.d.ts","sourceRoot":"","sources":["../../src/electron-main/theia-electron-window.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAoF,UAAU,EAAE,MAAM,gDAAgD,CAAC;AAC9J,OAAO,EAAE,aAAa,EAAE,+BAA+B,EAAW,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEvH,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,KAAK,EAAa,MAAM,WAAW,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,+BAA+B;IAC9E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,yBAAyB,eAAsC,CAAC;AAE7E,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AACzE,oBAAY,uBAAuB,GAAG,yBAAyB,CAAC;AAEhE,qBACa,mBAAmB;IACO,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IACxD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,8BAA8B,CAAC;IAEnG,SAAS,CAAC,iBAAiB,gBAAuB;IAElD,IAAI,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,CAE5B;IAED,SAAS,CAAC,QAAQ,CAAC,SAAS,uBAAoD;IAEhF,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC;IACjC,IAAI,MAAM,IAAI,aAAa,CAE1B;IAED,SAAS,CAAC,gBAAgB,UAAS;IACnC,SAAS,CAAC,gBAAgB,EAAE,wBAAwB,CAAU;IAG9D,SAAS,CAAC,IAAI,IAAI,IAAI;IAUtB;;OAEG;IACH,SAAS,CAAC,iBAAiB,IAAI,IAAI;IAInC,SAAS,CAAC,oBAAoB,IAAI,IAAI;IAetC,SAAS,CAAC,aAAa,IAAI,IAAI;IAK/B,KAAK,CAAC,MAAM,GAAE,UAA6B,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9D,SAAS,CAAC,MAAM,IAAI,IAAI;cAOR,iBAAiB,CAAC,cAAc,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBtG,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB/D,SAAS,CAAC,qBAAqB,IAAI,IAAI;IAQvC,SAAS,CAAC,qBAAqB,IAAI,IAAI;IAQvC,SAAS,CAAC,oBAAoB,IAAI,IAAI;IAQtC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO;IAI5C,OAAO,IAAI,IAAI;CAGlB;AAED,MAAM,WAAW,0BAA0B;IACvC,CAAC,OAAO,EAAE,yBAAyB,EAAE,MAAM,EAAE,yBAAyB,GAAG,mBAAmB,CAAC;CAChG;AAED,eAAO,MAAM,0BAA0B,eAAuC,CAAC"}
|
|
@@ -50,7 +50,6 @@ let TheiaElectronWindow = class TheiaElectronWindow {
|
|
|
50
50
|
this._window = new electron_1.BrowserWindow(this.options);
|
|
51
51
|
this._window.setMenuBarVisibility(false);
|
|
52
52
|
this.attachReadyToShow();
|
|
53
|
-
this.attachGlobalShortcuts();
|
|
54
53
|
this.restoreMaximizedState();
|
|
55
54
|
this.attachCloseListeners();
|
|
56
55
|
this.trackApplicationState();
|
|
@@ -80,26 +79,6 @@ let TheiaElectronWindow = class TheiaElectronWindow {
|
|
|
80
79
|
this.closeIsConfirmed = true;
|
|
81
80
|
this._window.close();
|
|
82
81
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Catch certain keybindings to prevent reloading the window using keyboard shortcuts.
|
|
85
|
-
*/
|
|
86
|
-
attachGlobalShortcuts() {
|
|
87
|
-
var _a;
|
|
88
|
-
const handler = ((_a = this.config.electron) === null || _a === void 0 ? void 0 : _a.disallowReloadKeybinding)
|
|
89
|
-
? () => { }
|
|
90
|
-
: () => this.reload();
|
|
91
|
-
const accelerators = ['CmdOrCtrl+R', 'F5'];
|
|
92
|
-
(0, event_utils_1.createDisposableListener)(this._window, 'focus', () => {
|
|
93
|
-
for (const accelerator of accelerators) {
|
|
94
|
-
electron_1.globalShortcut.register(accelerator, handler);
|
|
95
|
-
}
|
|
96
|
-
}, this.toDispose);
|
|
97
|
-
(0, event_utils_1.createDisposableListener)(this._window, 'blur', () => {
|
|
98
|
-
for (const accelerator of accelerators) {
|
|
99
|
-
electron_1.globalShortcut.unregister(accelerator);
|
|
100
|
-
}
|
|
101
|
-
}, this.toDispose);
|
|
102
|
-
}
|
|
103
82
|
close(reason = electron_messages_1.StopReason.Close) {
|
|
104
83
|
return this.handleStopRequest(() => this.doCloseWindow(), reason);
|
|
105
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theia-electron-window.js","sourceRoot":"","sources":["../../src/electron-main/theia-electron-window.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;;;;;;;;;;;;AAIhF,sFAA8J;AAC9J,
|
|
1
|
+
{"version":3,"file":"theia-electron-window.js","sourceRoot":"","sources":["../../src/electron-main/theia-electron-window.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/core",
|
|
3
|
-
"version": "1.24.0-next.
|
|
3
|
+
"version": "1.24.0-next.26+3da6276f571",
|
|
4
4
|
"description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
|
|
5
5
|
"main": "lib/common/index.js",
|
|
6
6
|
"typings": "lib/common/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@phosphor/virtualdom": "1",
|
|
18
18
|
"@phosphor/widgets": "1",
|
|
19
19
|
"@primer/octicons-react": "^9.0.0",
|
|
20
|
-
"@theia/application-package": "1.24.0-next.
|
|
20
|
+
"@theia/application-package": "1.24.0-next.26+3da6276f571",
|
|
21
21
|
"@types/body-parser": "^1.16.4",
|
|
22
22
|
"@types/cookie": "^0.3.3",
|
|
23
23
|
"@types/dompurify": "^2.2.2",
|
|
@@ -190,5 +190,5 @@
|
|
|
190
190
|
"nyc": {
|
|
191
191
|
"extends": "../../configs/nyc.json"
|
|
192
192
|
},
|
|
193
|
-
"gitHead": "
|
|
193
|
+
"gitHead": "3da6276f571891af259a3357acb94731e2abf1b0"
|
|
194
194
|
}
|
|
@@ -27,11 +27,11 @@ import { SelectionService } from '../common/selection-service';
|
|
|
27
27
|
import { MessageService } from '../common/message-service';
|
|
28
28
|
import { OpenerService, open } from '../browser/opener-service';
|
|
29
29
|
import { ApplicationShell } from './shell/application-shell';
|
|
30
|
-
import { SHELL_TABBAR_CONTEXT_CLOSE, SHELL_TABBAR_CONTEXT_COPY, SHELL_TABBAR_CONTEXT_SPLIT } from './shell/tab-bars';
|
|
30
|
+
import { SHELL_TABBAR_CONTEXT_CLOSE, SHELL_TABBAR_CONTEXT_COPY, SHELL_TABBAR_CONTEXT_PIN, SHELL_TABBAR_CONTEXT_SPLIT } from './shell/tab-bars';
|
|
31
31
|
import { AboutDialog } from './about-dialog';
|
|
32
32
|
import * as browser from './browser';
|
|
33
33
|
import URI from '../common/uri';
|
|
34
|
-
import { ContextKeyService } from './context-key-service';
|
|
34
|
+
import { ContextKey, ContextKeyService } from './context-key-service';
|
|
35
35
|
import { OS, isOSX, isWindows } from '../common/os';
|
|
36
36
|
import { ResourceContextKey } from './resource-context-key';
|
|
37
37
|
import { UriSelection } from '../common/selection';
|
|
@@ -50,7 +50,7 @@ import { EncodingRegistry } from './encoding-registry';
|
|
|
50
50
|
import { UTF8 } from '../common/encodings';
|
|
51
51
|
import { EnvVariablesServer } from '../common/env-variables';
|
|
52
52
|
import { AuthenticationService } from './authentication-service';
|
|
53
|
-
import { FormatType, Saveable } from './saveable';
|
|
53
|
+
import { FormatType, Saveable, SaveOptions } from './saveable';
|
|
54
54
|
import { QuickInputService, QuickPick, QuickPickItem } from './quick-input';
|
|
55
55
|
import { AsyncLocalizationProvider } from '../common/i18n/localization';
|
|
56
56
|
import { nls } from '../common/nls';
|
|
@@ -59,6 +59,8 @@ import { ConfirmDialog, confirmExit, Dialog } from './dialogs';
|
|
|
59
59
|
import { WindowService } from './window/window-service';
|
|
60
60
|
import { FrontendApplicationConfigProvider } from './frontend-application-config-provider';
|
|
61
61
|
import { DecorationStyle } from './decoration-style';
|
|
62
|
+
import { isPinned, Title, togglePinned, Widget } from './widgets';
|
|
63
|
+
import { SaveResourceService } from './save-resource-service';
|
|
62
64
|
|
|
63
65
|
export namespace CommonMenus {
|
|
64
66
|
|
|
@@ -241,6 +243,16 @@ export namespace CommonCommands {
|
|
|
241
243
|
category: VIEW_CATEGORY,
|
|
242
244
|
label: 'Toggle Status Bar Visibility'
|
|
243
245
|
});
|
|
246
|
+
export const PIN_TAB = Command.toDefaultLocalizedCommand({
|
|
247
|
+
id: 'workbench.action.pinEditor',
|
|
248
|
+
category: VIEW_CATEGORY,
|
|
249
|
+
label: 'Pin Editor'
|
|
250
|
+
});
|
|
251
|
+
export const UNPIN_TAB = Command.toDefaultLocalizedCommand({
|
|
252
|
+
id: 'workbench.action.unpinEditor',
|
|
253
|
+
category: VIEW_CATEGORY,
|
|
254
|
+
label: 'Unpin Editor'
|
|
255
|
+
});
|
|
244
256
|
export const TOGGLE_MAXIMIZED = Command.toLocalizedCommand({
|
|
245
257
|
id: 'core.toggleMaximized',
|
|
246
258
|
category: VIEW_CATEGORY,
|
|
@@ -327,7 +339,8 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
327
339
|
@inject(MessageService) protected readonly messageService: MessageService,
|
|
328
340
|
@inject(OpenerService) protected readonly openerService: OpenerService,
|
|
329
341
|
@inject(AboutDialog) protected readonly aboutDialog: AboutDialog,
|
|
330
|
-
@inject(AsyncLocalizationProvider) protected readonly localizationProvider: AsyncLocalizationProvider
|
|
342
|
+
@inject(AsyncLocalizationProvider) protected readonly localizationProvider: AsyncLocalizationProvider,
|
|
343
|
+
@inject(SaveResourceService) protected readonly saveResourceService: SaveResourceService,
|
|
331
344
|
) { }
|
|
332
345
|
|
|
333
346
|
@inject(ContextKeyService)
|
|
@@ -372,6 +385,8 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
372
385
|
@inject(WindowService)
|
|
373
386
|
protected readonly windowService: WindowService;
|
|
374
387
|
|
|
388
|
+
protected pinnedKey: ContextKey<boolean>;
|
|
389
|
+
|
|
375
390
|
async configure(app: FrontendApplication): Promise<void> {
|
|
376
391
|
const configDirUri = await this.environments.getConfigDirUri();
|
|
377
392
|
// Global settings
|
|
@@ -385,6 +400,10 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
385
400
|
this.contextKeyService.createKey<boolean>('isWindows', OS.type() === OS.Type.Windows);
|
|
386
401
|
this.contextKeyService.createKey<boolean>('isWeb', !this.isElectron());
|
|
387
402
|
|
|
403
|
+
this.pinnedKey = this.contextKeyService.createKey<boolean>('activeEditorIsPinned', false);
|
|
404
|
+
this.updatePinnedKey();
|
|
405
|
+
this.shell.onDidChangeActiveWidget(() => this.updatePinnedKey());
|
|
406
|
+
|
|
388
407
|
this.initResourceContextKeys();
|
|
389
408
|
this.registerCtrlWHandling();
|
|
390
409
|
|
|
@@ -427,6 +446,13 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
427
446
|
}
|
|
428
447
|
}
|
|
429
448
|
|
|
449
|
+
protected updatePinnedKey(): void {
|
|
450
|
+
const activeTab = this.shell.findTabBar();
|
|
451
|
+
const pinningTarget = activeTab && this.shell.findTitle(activeTab);
|
|
452
|
+
const value = pinningTarget && isPinned(pinningTarget);
|
|
453
|
+
this.pinnedKey.set(value);
|
|
454
|
+
}
|
|
455
|
+
|
|
430
456
|
protected updateThemePreference(preferenceName: 'workbench.colorTheme' | 'workbench.iconTheme'): void {
|
|
431
457
|
const inspect = this.preferenceService.inspect<string | null>(preferenceName);
|
|
432
458
|
const workspaceValue = inspect && inspect.workspaceValue;
|
|
@@ -636,6 +662,16 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
636
662
|
label: nls.localizeByDefault('Toggle Menu Bar'),
|
|
637
663
|
order: '0'
|
|
638
664
|
});
|
|
665
|
+
registry.registerMenuAction(SHELL_TABBAR_CONTEXT_PIN, {
|
|
666
|
+
commandId: CommonCommands.PIN_TAB.id,
|
|
667
|
+
label: nls.localizeByDefault('Pin'),
|
|
668
|
+
order: '7'
|
|
669
|
+
});
|
|
670
|
+
registry.registerMenuAction(SHELL_TABBAR_CONTEXT_PIN, {
|
|
671
|
+
commandId: CommonCommands.UNPIN_TAB.id,
|
|
672
|
+
label: nls.localizeByDefault('Unpin'),
|
|
673
|
+
order: '8'
|
|
674
|
+
});
|
|
639
675
|
registry.registerMenuAction(CommonMenus.HELP, {
|
|
640
676
|
commandId: CommonCommands.ABOUT_COMMAND.id,
|
|
641
677
|
label: CommonCommands.ABOUT_COMMAND.label,
|
|
@@ -855,10 +891,10 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
855
891
|
});
|
|
856
892
|
|
|
857
893
|
commandRegistry.registerCommand(CommonCommands.SAVE, {
|
|
858
|
-
execute: () => this.
|
|
894
|
+
execute: () => this.save({ formatType: FormatType.ON })
|
|
859
895
|
});
|
|
860
896
|
commandRegistry.registerCommand(CommonCommands.SAVE_WITHOUT_FORMATTING, {
|
|
861
|
-
execute: () => this.
|
|
897
|
+
execute: () => this.save({ formatType: FormatType.OFF })
|
|
862
898
|
});
|
|
863
899
|
commandRegistry.registerCommand(CommonCommands.SAVE_ALL, {
|
|
864
900
|
execute: () => this.shell.saveAll({ formatType: FormatType.DIRTY })
|
|
@@ -877,16 +913,30 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
877
913
|
commandRegistry.registerCommand(CommonCommands.SELECT_ICON_THEME, {
|
|
878
914
|
execute: () => this.selectIconTheme()
|
|
879
915
|
});
|
|
880
|
-
|
|
916
|
+
commandRegistry.registerCommand(CommonCommands.PIN_TAB, new CurrentWidgetCommandAdapter(this.shell, {
|
|
917
|
+
isEnabled: title => Boolean(title && !isPinned(title)),
|
|
918
|
+
execute: title => this.togglePinned(title),
|
|
919
|
+
}));
|
|
920
|
+
commandRegistry.registerCommand(CommonCommands.UNPIN_TAB, new CurrentWidgetCommandAdapter(this.shell, {
|
|
921
|
+
isEnabled: title => Boolean(title && isPinned(title)),
|
|
922
|
+
execute: title => this.togglePinned(title),
|
|
923
|
+
}));
|
|
881
924
|
commandRegistry.registerCommand(CommonCommands.CONFIGURE_DISPLAY_LANGUAGE, {
|
|
882
925
|
execute: () => this.configureDisplayLanguage()
|
|
883
926
|
});
|
|
884
927
|
}
|
|
885
928
|
|
|
886
|
-
|
|
929
|
+
protected isElectron(): boolean {
|
|
887
930
|
return environment.electron.is();
|
|
888
931
|
}
|
|
889
932
|
|
|
933
|
+
protected togglePinned(title?: Title<Widget>): void {
|
|
934
|
+
if (title) {
|
|
935
|
+
togglePinned(title);
|
|
936
|
+
this.updatePinnedKey();
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
890
940
|
registerKeybindings(registry: KeybindingRegistry): void {
|
|
891
941
|
if (supportCut) {
|
|
892
942
|
registry.registerKeybinding({
|
|
@@ -996,10 +1046,25 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
|
|
|
996
1046
|
{
|
|
997
1047
|
command: CommonCommands.SELECT_COLOR_THEME.id,
|
|
998
1048
|
keybinding: 'ctrlcmd+k ctrlcmd+t'
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
command: CommonCommands.PIN_TAB.id,
|
|
1052
|
+
keybinding: 'ctrlcmd+k shift+enter',
|
|
1053
|
+
when: '!activeEditorIsPinned'
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
command: CommonCommands.UNPIN_TAB.id,
|
|
1057
|
+
keybinding: 'ctrlcmd+k shift+enter',
|
|
1058
|
+
when: 'activeEditorIsPinned'
|
|
999
1059
|
}
|
|
1000
1060
|
);
|
|
1001
1061
|
}
|
|
1002
1062
|
|
|
1063
|
+
protected async save(options?: SaveOptions): Promise<void> {
|
|
1064
|
+
const widget = this.shell.currentWidget;
|
|
1065
|
+
this.saveResourceService.save(widget, options);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1003
1068
|
protected async openAbout(): Promise<void> {
|
|
1004
1069
|
this.aboutDialog.open();
|
|
1005
1070
|
}
|
|
@@ -120,6 +120,7 @@ import {
|
|
|
120
120
|
import { RendererHost } from './widgets';
|
|
121
121
|
import { TooltipService, TooltipServiceImpl } from './tooltip-service';
|
|
122
122
|
import { bindFrontendStopwatch, bindBackendStopwatch } from './performance';
|
|
123
|
+
import { SaveResourceService } from './save-resource-service';
|
|
123
124
|
|
|
124
125
|
export { bindResourceProvider, bindMessageService, bindPreferenceService };
|
|
125
126
|
|
|
@@ -171,7 +172,8 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo
|
|
|
171
172
|
const tabBarDecoratorService = container.get(TabBarDecoratorService);
|
|
172
173
|
const iconThemeService = container.get(IconThemeService);
|
|
173
174
|
const selectionService = container.get(SelectionService);
|
|
174
|
-
|
|
175
|
+
const commandService = container.get<CommandService>(CommandService);
|
|
176
|
+
return new TabBarRenderer(contextMenuRenderer, tabBarDecoratorService, iconThemeService, selectionService, commandService);
|
|
175
177
|
});
|
|
176
178
|
|
|
177
179
|
bindContributionProvider(bind, TabBarDecorator);
|
|
@@ -394,4 +396,6 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo
|
|
|
394
396
|
|
|
395
397
|
bindFrontendStopwatch(bind);
|
|
396
398
|
bindBackendStopwatch(bind);
|
|
399
|
+
|
|
400
|
+
bind(SaveResourceService).toSelf().inSingletonScope();
|
|
397
401
|
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (C) 2022 Arm and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
*
|
|
8
|
+
* This Source Code may also be made available under the following Secondary
|
|
9
|
+
* Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
* with the GNU Classpath Exception which is available at
|
|
12
|
+
* https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
*
|
|
14
|
+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
********************************************************************************/
|
|
16
|
+
|
|
17
|
+
import { injectable } from 'inversify';
|
|
18
|
+
import { Saveable, SaveOptions } from './saveable';
|
|
19
|
+
import { Widget } from './widgets';
|
|
20
|
+
|
|
21
|
+
@injectable()
|
|
22
|
+
export class SaveResourceService {
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Indicate if the document can be saved ('Save' command should be disable if not).
|
|
26
|
+
*/
|
|
27
|
+
canSave(saveable: Saveable): boolean {
|
|
28
|
+
// By default, we never allow a document to be saved if it is untitled.
|
|
29
|
+
return Saveable.isDirty(saveable) && !Saveable.isUntitled(saveable);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Saves the document.
|
|
34
|
+
*
|
|
35
|
+
* This function is called only if `canSave` returns true, which means the document is not untitled
|
|
36
|
+
* and is thus saveable.
|
|
37
|
+
*/
|
|
38
|
+
async save(widget: Widget | undefined, options?: SaveOptions): Promise<void> {
|
|
39
|
+
const saveable = Saveable.get(widget);
|
|
40
|
+
if (saveable && this.canSave(saveable)) {
|
|
41
|
+
await saveable.save(options);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
package/src/browser/saveable.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { MaybePromise } from '../common/types';
|
|
|
21
21
|
import { Key } from './keyboard/keys';
|
|
22
22
|
import { AbstractDialog } from './dialogs';
|
|
23
23
|
import { waitForClosed } from './widgets';
|
|
24
|
+
import { URI } from 'vscode-uri';
|
|
24
25
|
|
|
25
26
|
export interface Saveable {
|
|
26
27
|
readonly dirty: boolean;
|
|
@@ -65,6 +66,10 @@ export namespace Saveable {
|
|
|
65
66
|
return !!arg && ('dirty' in arg) && ('onDirtyChanged' in arg);
|
|
66
67
|
}
|
|
67
68
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
export function isUntitled(arg: any): boolean {
|
|
70
|
+
return !!arg && ('uri' in arg) && URI.parse((arg as { uri: string; }).uri).scheme === 'untitled';
|
|
71
|
+
}
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
73
|
export function get(arg: any): Saveable | undefined {
|
|
69
74
|
if (is(arg)) {
|
|
70
75
|
return arg;
|
|
@@ -596,8 +596,10 @@ export class ApplicationShell extends Widget {
|
|
|
596
596
|
return {
|
|
597
597
|
version: applicationShellLayoutVersion,
|
|
598
598
|
mainPanel: this.mainPanel.saveLayout(),
|
|
599
|
+
mainPanelPinned: this.getPinnedMainWidgets(),
|
|
599
600
|
bottomPanel: {
|
|
600
601
|
config: this.bottomPanel.saveLayout(),
|
|
602
|
+
pinned: this.getPinnedBottomWidgets(),
|
|
601
603
|
size: this.bottomPanel.isVisible ? this.getBottomPanelSize() : this.bottomPanelState.lastPanelSize,
|
|
602
604
|
expanded: this.isExpanded('bottom')
|
|
603
605
|
},
|
|
@@ -607,6 +609,28 @@ export class ApplicationShell extends Widget {
|
|
|
607
609
|
};
|
|
608
610
|
}
|
|
609
611
|
|
|
612
|
+
// Get an array corresponding to main panel widgets' pinned state.
|
|
613
|
+
getPinnedMainWidgets(): boolean[] {
|
|
614
|
+
const pinned: boolean[] = [];
|
|
615
|
+
|
|
616
|
+
toArray(this.mainPanel.widgets()).forEach((a, i) => {
|
|
617
|
+
pinned[i] = a.title.className.indexOf('theia-mod-pinned') >= 0;
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
return pinned;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Get an array corresponding to bottom panel widgets' pinned state.
|
|
624
|
+
getPinnedBottomWidgets(): boolean[] {
|
|
625
|
+
const pinned: boolean[] = [];
|
|
626
|
+
|
|
627
|
+
toArray(this.bottomPanel.widgets()).forEach((a, i) => {
|
|
628
|
+
pinned[i] = a.title.className.indexOf('theia-mod-pinned') >= 0;
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
return pinned;
|
|
632
|
+
}
|
|
633
|
+
|
|
610
634
|
/**
|
|
611
635
|
* Compute the current height of the bottom panel. This implementation assumes that the container
|
|
612
636
|
* of the bottom panel is a `SplitPanel`.
|
|
@@ -639,7 +663,7 @@ export class ApplicationShell extends Widget {
|
|
|
639
663
|
* Apply a shell layout that has been previously created with `getLayoutData`.
|
|
640
664
|
*/
|
|
641
665
|
async setLayoutData(layoutData: ApplicationShell.LayoutData): Promise<void> {
|
|
642
|
-
const { mainPanel, bottomPanel, leftPanel, rightPanel, activeWidgetId } = layoutData;
|
|
666
|
+
const { mainPanel, mainPanelPinned, bottomPanel, leftPanel, rightPanel, activeWidgetId } = layoutData;
|
|
643
667
|
if (leftPanel) {
|
|
644
668
|
this.leftPanelHandler.setLayoutData(leftPanel);
|
|
645
669
|
this.registerWithFocusTracker(leftPanel);
|
|
@@ -663,6 +687,15 @@ export class ApplicationShell extends Widget {
|
|
|
663
687
|
} else {
|
|
664
688
|
this.collapseBottomPanel();
|
|
665
689
|
}
|
|
690
|
+
const widgets = toArray(this.bottomPanel.widgets());
|
|
691
|
+
if (bottomPanel.pinned && bottomPanel.pinned.length === widgets.length) {
|
|
692
|
+
widgets.forEach((a, i) => {
|
|
693
|
+
if (bottomPanel.pinned![i]) {
|
|
694
|
+
a.title.className += ' theia-mod-pinned';
|
|
695
|
+
a.title.closable = false;
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
}
|
|
666
699
|
this.refreshBottomPanelToggleButton();
|
|
667
700
|
}
|
|
668
701
|
// Proceed with the main panel once all others are set up
|
|
@@ -670,6 +703,15 @@ export class ApplicationShell extends Widget {
|
|
|
670
703
|
if (mainPanel) {
|
|
671
704
|
this.mainPanel.restoreLayout(mainPanel);
|
|
672
705
|
this.registerWithFocusTracker(mainPanel.main);
|
|
706
|
+
const widgets = toArray(this.mainPanel.widgets());
|
|
707
|
+
if (mainPanelPinned && mainPanelPinned.length === widgets.length) {
|
|
708
|
+
widgets.forEach((a, i) => {
|
|
709
|
+
if (mainPanelPinned[i]) {
|
|
710
|
+
a.title.className += ' theia-mod-pinned';
|
|
711
|
+
a.title.closable = false;
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
}
|
|
673
715
|
}
|
|
674
716
|
if (activeWidgetId) {
|
|
675
717
|
this.activateWidget(activeWidgetId);
|
|
@@ -1954,6 +1996,7 @@ export namespace ApplicationShell {
|
|
|
1954
1996
|
export interface LayoutData {
|
|
1955
1997
|
version?: string | ApplicationShellLayoutVersion,
|
|
1956
1998
|
mainPanel?: DockPanel.ILayoutConfig;
|
|
1999
|
+
mainPanelPinned?: boolean[];
|
|
1957
2000
|
bottomPanel?: BottomPanelLayoutData;
|
|
1958
2001
|
leftPanel?: SidePanel.LayoutData;
|
|
1959
2002
|
rightPanel?: SidePanel.LayoutData;
|
|
@@ -1967,6 +2010,7 @@ export namespace ApplicationShell {
|
|
|
1967
2010
|
config?: DockPanel.ILayoutConfig;
|
|
1968
2011
|
size?: number;
|
|
1969
2012
|
expanded?: boolean;
|
|
2013
|
+
pinned?: boolean[];
|
|
1970
2014
|
}
|
|
1971
2015
|
|
|
1972
2016
|
/**
|
|
@@ -272,7 +272,8 @@ export class SidePanelHandler {
|
|
|
272
272
|
const items = toArray(map(this.tabBar.titles, title => <SidePanel.WidgetItem>{
|
|
273
273
|
widget: title.owner,
|
|
274
274
|
rank: SidePanelHandler.rankProperty.get(title.owner),
|
|
275
|
-
expanded: title === currentTitle
|
|
275
|
+
expanded: title === currentTitle,
|
|
276
|
+
pinned: title.className.indexOf('theia-mod-pinned') >= 0
|
|
276
277
|
}));
|
|
277
278
|
// eslint-disable-next-line no-null/no-null
|
|
278
279
|
const size = currentTitle !== null ? this.getPanelSize() : this.state.lastPanelSize;
|
|
@@ -288,7 +289,7 @@ export class SidePanelHandler {
|
|
|
288
289
|
|
|
289
290
|
let currentTitle: Title<Widget> | undefined;
|
|
290
291
|
if (layoutData.items) {
|
|
291
|
-
for (const { widget, rank, expanded } of layoutData.items) {
|
|
292
|
+
for (const { widget, rank, expanded, pinned } of layoutData.items) {
|
|
292
293
|
if (widget) {
|
|
293
294
|
if (rank) {
|
|
294
295
|
SidePanelHandler.rankProperty.set(widget, rank);
|
|
@@ -296,6 +297,10 @@ export class SidePanelHandler {
|
|
|
296
297
|
if (expanded) {
|
|
297
298
|
currentTitle = widget.title;
|
|
298
299
|
}
|
|
300
|
+
if (pinned) {
|
|
301
|
+
widget.title.className += ' theia-mod-pinned';
|
|
302
|
+
widget.title.closable = false;
|
|
303
|
+
}
|
|
299
304
|
// Add the widgets directly to the tab bar in the same order as they are stored
|
|
300
305
|
this.tabBar.addTab(widget.title);
|
|
301
306
|
}
|
|
@@ -725,6 +730,7 @@ export namespace SidePanel {
|
|
|
725
730
|
/** Can be undefined in case the widget could not be restored. */
|
|
726
731
|
widget?: Widget;
|
|
727
732
|
expanded?: boolean;
|
|
733
|
+
pinned?: boolean;
|
|
728
734
|
}
|
|
729
735
|
|
|
730
736
|
export interface State {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import PerfectScrollbar from 'perfect-scrollbar';
|
|
18
18
|
import { TabBar, Title, Widget } from '@phosphor/widgets';
|
|
19
19
|
import { VirtualElement, h, VirtualDOM, ElementInlineStyle } from '@phosphor/virtualdom';
|
|
20
|
-
import { Disposable, DisposableCollection, MenuPath, notEmpty, SelectionService } from '../../common';
|
|
20
|
+
import { Disposable, DisposableCollection, MenuPath, notEmpty, SelectionService, CommandService } from '../../common';
|
|
21
21
|
import { ContextMenuRenderer } from '../context-menu-renderer';
|
|
22
22
|
import { Signal, Slot } from '@phosphor/signaling';
|
|
23
23
|
import { Message, MessageLoop } from '@phosphor/messaging';
|
|
@@ -31,6 +31,7 @@ import { IconThemeService } from '../icon-theme-service';
|
|
|
31
31
|
import { BreadcrumbsRenderer, BreadcrumbsRendererFactory } from '../breadcrumbs/breadcrumbs-renderer';
|
|
32
32
|
import { NavigatableWidget } from '../navigatable-types';
|
|
33
33
|
import { IDragEvent } from '@phosphor/dragdrop';
|
|
34
|
+
import { PINNED_CLASS } from '../widgets/widget';
|
|
34
35
|
|
|
35
36
|
/** The class name added to hidden content nodes, which are required to render vertical side bars. */
|
|
36
37
|
const HIDDEN_CONTENT_CLASS = 'theia-TabBar-hidden-content';
|
|
@@ -87,6 +88,7 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
87
88
|
protected readonly decoratorService?: TabBarDecoratorService,
|
|
88
89
|
protected readonly iconThemeService?: IconThemeService,
|
|
89
90
|
protected readonly selectionService?: SelectionService,
|
|
91
|
+
protected readonly commandService?: CommandService
|
|
90
92
|
) {
|
|
91
93
|
super();
|
|
92
94
|
if (this.decoratorService) {
|
|
@@ -162,7 +164,10 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
162
164
|
this.renderLabel(data, isInSidePanel),
|
|
163
165
|
this.renderBadge(data, isInSidePanel)
|
|
164
166
|
),
|
|
165
|
-
|
|
167
|
+
h.div({
|
|
168
|
+
className: 'p-TabBar-tabCloseIcon action-item',
|
|
169
|
+
onclick: this.handleCloseClickEvent
|
|
170
|
+
})
|
|
166
171
|
);
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -467,6 +472,16 @@ export class TabBarRenderer extends TabBar.Renderer {
|
|
|
467
472
|
}
|
|
468
473
|
};
|
|
469
474
|
|
|
475
|
+
protected handleCloseClickEvent = (event: MouseEvent) => {
|
|
476
|
+
if (this.tabBar && event.currentTarget instanceof HTMLElement) {
|
|
477
|
+
const id = event.currentTarget.parentElement!.id;
|
|
478
|
+
const title = this.tabBar.titles.find(t => this.createTabId(t) === id);
|
|
479
|
+
if (title?.closable === false && title?.className.includes(PINNED_CLASS) && this.commandService) {
|
|
480
|
+
this.commandService.executeCommand('workbench.action.unpinEditor', event);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
|
|
470
485
|
protected handleDblClickEvent = (event: MouseEvent) => {
|
|
471
486
|
if (this.tabBar && event.currentTarget instanceof HTMLElement) {
|
|
472
487
|
const id = event.currentTarget.id;
|
|
@@ -235,7 +235,8 @@ body.theia-editor-highlightModifiedTabs
|
|
|
235
235
|
height: inherit;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable > .p-TabBar-tabCloseIcon
|
|
238
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable > .p-TabBar-tabCloseIcon,
|
|
239
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned > .p-TabBar-tabCloseIcon {
|
|
239
240
|
padding: 2px;
|
|
240
241
|
margin-top: 2px;
|
|
241
242
|
margin-left: 4px;
|
|
@@ -258,7 +259,8 @@ body.theia-editor-highlightModifiedTabs
|
|
|
258
259
|
background-color: rgba(50%, 50%, 50%, 0.2);
|
|
259
260
|
}
|
|
260
261
|
|
|
261
|
-
.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable
|
|
262
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable,
|
|
263
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned {
|
|
262
264
|
padding-right: 4px;
|
|
263
265
|
}
|
|
264
266
|
|
|
@@ -272,6 +274,14 @@ body.theia-editor-highlightModifiedTabs
|
|
|
272
274
|
content: "\ea71";
|
|
273
275
|
}
|
|
274
276
|
|
|
277
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned > .p-TabBar-tabCloseIcon:before {
|
|
278
|
+
content: "\eba0";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned.theia-mod-dirty > .p-TabBar-tabCloseIcon:before {
|
|
282
|
+
content: "\ebb2";
|
|
283
|
+
}
|
|
284
|
+
|
|
275
285
|
.p-TabBar-tabIcon.no-icon {
|
|
276
286
|
display: none !important;
|
|
277
287
|
}
|
|
@@ -18,7 +18,7 @@ import { interfaces, injectable, inject, postConstruct } from 'inversify';
|
|
|
18
18
|
import { IIterator, toArray, find, some, every, map, ArrayExt } from '@phosphor/algorithm';
|
|
19
19
|
import {
|
|
20
20
|
Widget, EXPANSION_TOGGLE_CLASS, COLLAPSED_CLASS, CODICON_TREE_ITEM_CLASSES, MessageLoop, Message, SplitPanel,
|
|
21
|
-
BaseWidget, addEventListener, SplitLayout, LayoutItem, PanelLayout, addKeyListener, waitForRevealed, UnsafeWidgetUtilities, DockPanel
|
|
21
|
+
BaseWidget, addEventListener, SplitLayout, LayoutItem, PanelLayout, addKeyListener, waitForRevealed, UnsafeWidgetUtilities, DockPanel, PINNED_CLASS
|
|
22
22
|
} from './widgets';
|
|
23
23
|
import { Event as CommonEvent, Emitter } from '../common/event';
|
|
24
24
|
import { Disposable, DisposableCollection } from '../common/disposable';
|
|
@@ -276,7 +276,9 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
|
|
|
276
276
|
if (title.iconClass) {
|
|
277
277
|
this.title.iconClass = title.iconClass;
|
|
278
278
|
}
|
|
279
|
-
if (title.
|
|
279
|
+
if (this.title.className.includes(PINNED_CLASS)) {
|
|
280
|
+
this.title.closable &&= false;
|
|
281
|
+
} else if (title.closeable !== undefined) {
|
|
280
282
|
this.title.closable = title.closeable;
|
|
281
283
|
}
|
|
282
284
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
18
|
|
|
19
19
|
import { injectable, decorate, unmanaged } from 'inversify';
|
|
20
|
-
import { Widget } from '@phosphor/widgets';
|
|
20
|
+
import { Title, Widget } from '@phosphor/widgets';
|
|
21
21
|
import { Message, MessageLoop } from '@phosphor/messaging';
|
|
22
22
|
import { Emitter, Event, Disposable, DisposableCollection, MaybePromise } from '../../common';
|
|
23
23
|
import { KeyCode, KeysOrKeyCodes } from '../keyboard/keys';
|
|
@@ -52,6 +52,7 @@ export const BUSY_CLASS = 'theia-mod-busy';
|
|
|
52
52
|
export const CODICON_LOADING_CLASSES = codiconArray('loading');
|
|
53
53
|
export const SELECTED_CLASS = 'theia-mod-selected';
|
|
54
54
|
export const FOCUS_CLASS = 'theia-mod-focus';
|
|
55
|
+
export const PINNED_CLASS = 'theia-mod-pinned';
|
|
55
56
|
export const DEFAULT_SCROLL_OPTIONS: PerfectScrollbar.Options = {
|
|
56
57
|
suppressScrollX: true,
|
|
57
58
|
minScrollbarLength: 35,
|
|
@@ -353,3 +354,30 @@ function waitForVisible(widget: Widget, visible: boolean, attached?: boolean): P
|
|
|
353
354
|
waitFor();
|
|
354
355
|
});
|
|
355
356
|
}
|
|
357
|
+
|
|
358
|
+
export function isPinned(title: Title<Widget>): boolean {
|
|
359
|
+
const pinnedState = !title.closable && title.className.includes(PINNED_CLASS);
|
|
360
|
+
return pinnedState;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function unpin(title: Title<Widget>): void {
|
|
364
|
+
title.closable = true;
|
|
365
|
+
title.className = title.className.replace(PINNED_CLASS, '').trim();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function pin(title: Title<Widget>): void {
|
|
369
|
+
title.closable = false;
|
|
370
|
+
if (!title.className.includes(PINNED_CLASS)) {
|
|
371
|
+
title.className += ` ${PINNED_CLASS}`;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function togglePinned(title?: Title<Widget>): void {
|
|
376
|
+
if (title) {
|
|
377
|
+
if (isPinned(title)) {
|
|
378
|
+
unpin(title);
|
|
379
|
+
} else {
|
|
380
|
+
pin(title);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|