@theia/core 1.60.0-next.43 → 1.60.0
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 +6 -6
- package/i18n/nls.cs.json +104 -8
- package/i18n/nls.de.json +104 -8
- package/i18n/nls.es.json +104 -8
- package/i18n/nls.fr.json +104 -8
- package/i18n/nls.hu.json +104 -8
- package/i18n/nls.it.json +104 -8
- package/i18n/nls.ja.json +104 -8
- package/i18n/nls.json +111 -15
- package/i18n/nls.ko.json +104 -8
- package/i18n/nls.pl.json +104 -8
- package/i18n/nls.pt-br.json +104 -8
- package/i18n/nls.ru.json +104 -8
- package/i18n/nls.tr.json +104 -8
- package/i18n/nls.zh-cn.json +104 -8
- package/i18n/nls.zh-tw.json +104 -8
- package/lib/browser/catalog.json +150 -26
- package/lib/browser/context-menu-renderer.d.ts +2 -1
- package/lib/browser/context-menu-renderer.d.ts.map +1 -1
- package/lib/browser/context-menu-renderer.js +3 -0
- package/lib/browser/context-menu-renderer.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +2 -1
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/tab-bars.d.ts +7 -30
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +49 -76
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/shell/theia-dock-panel.d.ts.map +1 -1
- package/lib/browser/shell/theia-dock-panel.js +9 -0
- package/lib/browser/shell/theia-dock-panel.js.map +1 -1
- package/lib/browser/widget-open-handler.d.ts +1 -1
- package/lib/browser/widget-open-handler.d.ts.map +1 -1
- package/lib/browser/widget-open-handler.js +2 -2
- package/lib/browser/widget-open-handler.js.map +1 -1
- package/lib/browser/widgets/widget.d.ts +3 -2
- package/lib/browser/widgets/widget.d.ts.map +1 -1
- package/lib/browser/widgets/widget.js +1 -3
- package/lib/browser/widgets/widget.js.map +1 -1
- package/lib/common/path.d.ts.map +1 -1
- package/lib/common/path.js +1 -4
- package/lib/common/path.js.map +1 -1
- package/lib/common/path.spec.js +3 -0
- package/lib/common/path.spec.js.map +1 -1
- package/lib/node/env-variables/env-variables-server.d.ts.map +1 -1
- package/lib/node/env-variables/env-variables-server.js +5 -7
- package/lib/node/env-variables/env-variables-server.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/context-menu-renderer.ts +4 -1
- package/src/browser/shell/application-shell.ts +3 -1
- package/src/browser/shell/tab-bars.ts +55 -86
- package/src/browser/shell/theia-dock-panel.ts +10 -0
- package/src/browser/style/index.css +2 -0
- package/src/browser/style/tabs.css +2 -2
- package/src/browser/style/view-container.css +1 -0
- package/src/browser/widget-open-handler.ts +2 -2
- package/src/browser/widgets/widget.ts +11 -8
- package/src/common/path.spec.ts +4 -0
- package/src/common/path.ts +1 -4
- package/src/node/env-variables/env-variables-server.ts +5 -6
|
@@ -20,7 +20,7 @@ import { VirtualElement, h, VirtualDOM, ElementInlineStyle } from '@lumino/virtu
|
|
|
20
20
|
import { Disposable, DisposableCollection, MenuPath, notEmpty, SelectionService, CommandService, nls, ArrayUtils } from '../../common';
|
|
21
21
|
import { ContextMenuRenderer } from '../context-menu-renderer';
|
|
22
22
|
import { Signal, Slot } from '@lumino/signaling';
|
|
23
|
-
import { Message
|
|
23
|
+
import { Message } from '@lumino/messaging';
|
|
24
24
|
import { ArrayExt } from '@lumino/algorithm';
|
|
25
25
|
import { ElementExt } from '@lumino/domutils';
|
|
26
26
|
import { TabBarToolbarRegistry, TabBarToolbar } from './tab-bar-toolbar';
|
|
@@ -697,9 +697,8 @@ export interface TabBarPrivateMethods {
|
|
|
697
697
|
*/
|
|
698
698
|
export class ScrollableTabBar extends TabBar<Widget> {
|
|
699
699
|
|
|
700
|
-
protected scrollBar
|
|
700
|
+
protected scrollBar: PerfectScrollbar | undefined;
|
|
701
701
|
|
|
702
|
-
protected scrollBarFactory: () => PerfectScrollbar;
|
|
703
702
|
protected pendingReveal?: Promise<void>;
|
|
704
703
|
protected isMouseOver = false;
|
|
705
704
|
protected needsRecompute = false;
|
|
@@ -712,11 +711,27 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
712
711
|
protected openTabsContainer: HTMLDivElement;
|
|
713
712
|
protected openTabsRoot: Root;
|
|
714
713
|
|
|
715
|
-
constructor(options?: TabBar.IOptions<Widget
|
|
714
|
+
constructor(options?: TabBar.IOptions<Widget>, protected readonly scrollbarOptions?: PerfectScrollbar.Options, dynamicTabOptions?: ScrollableTabBar.Options) {
|
|
716
715
|
super(options);
|
|
717
|
-
this.scrollBarFactory = () => new PerfectScrollbar(this.scrollbarHost, options);
|
|
718
716
|
this._dynamicTabOptions = dynamicTabOptions;
|
|
719
|
-
this.
|
|
717
|
+
this.topRow = document.createElement('div');
|
|
718
|
+
this.topRow.classList.add('theia-tabBar-tab-row');
|
|
719
|
+
this.node.appendChild(this.topRow);
|
|
720
|
+
|
|
721
|
+
const contentNode = this.contentNode;
|
|
722
|
+
if (!contentNode) {
|
|
723
|
+
throw new Error('tab bar does not have the content node.');
|
|
724
|
+
}
|
|
725
|
+
this.node.removeChild(contentNode);
|
|
726
|
+
this.contentContainer = document.createElement('div');
|
|
727
|
+
this.contentContainer.classList.add(ScrollableTabBar.Styles.TAB_BAR_CONTENT_CONTAINER);
|
|
728
|
+
this.contentContainer.appendChild(contentNode);
|
|
729
|
+
this.topRow.appendChild(this.contentContainer);
|
|
730
|
+
|
|
731
|
+
this.openTabsContainer = document.createElement('div');
|
|
732
|
+
this.openTabsContainer.classList.add('theia-tabBar-open-tabs');
|
|
733
|
+
this.openTabsRoot = createRoot(this.openTabsContainer);
|
|
734
|
+
this.topRow.appendChild(this.openTabsContainer);
|
|
720
735
|
}
|
|
721
736
|
|
|
722
737
|
set dynamicTabOptions(options: ScrollableTabBar.Options | undefined) {
|
|
@@ -753,39 +768,7 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
753
768
|
(this as unknown as TabBarPrivateMethods)._releaseMouse();
|
|
754
769
|
}
|
|
755
770
|
|
|
756
|
-
/**
|
|
757
|
-
* Restructures the DOM defined in Lumino.
|
|
758
|
-
*
|
|
759
|
-
* By default the tabs (`li`) are contained in the `this.contentNode` (`ul`) which is wrapped in a `div` (`this.node`).
|
|
760
|
-
* Instead of this structure, we add a container for the `this.contentNode` and for the toolbar.
|
|
761
|
-
* The scrollbar will only work for the `ul` part but it does not affect the toolbar, so it can be on the right hand-side.
|
|
762
|
-
*/
|
|
763
|
-
protected rewireDOM(): void {
|
|
764
|
-
const contentNode = this.node.getElementsByClassName(ScrollableTabBar.Styles.TAB_BAR_CONTENT)[0];
|
|
765
|
-
if (!contentNode) {
|
|
766
|
-
throw new Error(`'this.node' does not have the content as a direct child with class name '${ScrollableTabBar.Styles.TAB_BAR_CONTENT}'.`);
|
|
767
|
-
}
|
|
768
|
-
this.node.removeChild(contentNode);
|
|
769
|
-
this.contentContainer = document.createElement('div');
|
|
770
|
-
this.contentContainer.classList.add(ScrollableTabBar.Styles.TAB_BAR_CONTENT_CONTAINER);
|
|
771
|
-
this.contentContainer.appendChild(contentNode);
|
|
772
|
-
|
|
773
|
-
this.topRow = document.createElement('div');
|
|
774
|
-
this.topRow.classList.add('theia-tabBar-tab-row');
|
|
775
|
-
this.topRow.appendChild(this.contentContainer);
|
|
776
|
-
|
|
777
|
-
this.openTabsContainer = document.createElement('div');
|
|
778
|
-
this.openTabsContainer.classList.add('theia-tabBar-open-tabs');
|
|
779
|
-
this.openTabsRoot = createRoot(this.openTabsContainer);
|
|
780
|
-
this.topRow.appendChild(this.openTabsContainer);
|
|
781
|
-
|
|
782
|
-
this.node.appendChild(this.topRow);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
771
|
protected override onAfterAttach(msg: Message): void {
|
|
786
|
-
if (!this.scrollBar) {
|
|
787
|
-
this.scrollBar = this.scrollBarFactory();
|
|
788
|
-
}
|
|
789
772
|
this.node.addEventListener('mouseenter', () => { this.isMouseOver = true; });
|
|
790
773
|
this.node.addEventListener('mouseleave', () => {
|
|
791
774
|
this.isMouseOver = false;
|
|
@@ -795,14 +778,12 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
795
778
|
});
|
|
796
779
|
|
|
797
780
|
super.onAfterAttach(msg);
|
|
781
|
+
this.scrollBar = new PerfectScrollbar(this.contentContainer, this.scrollbarOptions);
|
|
798
782
|
}
|
|
799
783
|
|
|
800
784
|
protected override onBeforeDetach(msg: Message): void {
|
|
801
785
|
super.onBeforeDetach(msg);
|
|
802
|
-
|
|
803
|
-
this.scrollBar.destroy();
|
|
804
|
-
this.scrollBar = undefined;
|
|
805
|
-
}
|
|
786
|
+
this.scrollBar?.destroy();
|
|
806
787
|
}
|
|
807
788
|
|
|
808
789
|
protected override onUpdateRequest(msg: Message): void {
|
|
@@ -826,7 +807,7 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
826
807
|
} else {
|
|
827
808
|
this.needsRecompute = false;
|
|
828
809
|
if (this.orientation === 'horizontal') {
|
|
829
|
-
let availableWidth = this.
|
|
810
|
+
let availableWidth = this.contentNode.clientWidth;
|
|
830
811
|
let effectiveWidth = availableWidth;
|
|
831
812
|
if (!this.openTabsContainer.classList.contains('lm-mod-hidden')) {
|
|
832
813
|
availableWidth += this.openTabsContainer.getBoundingClientRect().width;
|
|
@@ -890,7 +871,7 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
890
871
|
window.requestAnimationFrame(() => {
|
|
891
872
|
const tab = this.contentNode.children[index] as HTMLElement;
|
|
892
873
|
if (tab && this.isVisible) {
|
|
893
|
-
const parent = this.
|
|
874
|
+
const parent = this.contentNode;
|
|
894
875
|
if (this.orientation === 'horizontal') {
|
|
895
876
|
const scroll = parent.scrollLeft;
|
|
896
877
|
const left = tab.offsetLeft;
|
|
@@ -924,25 +905,6 @@ export class ScrollableTabBar extends TabBar<Widget> {
|
|
|
924
905
|
this.pendingReveal = result;
|
|
925
906
|
return result;
|
|
926
907
|
}
|
|
927
|
-
|
|
928
|
-
/**
|
|
929
|
-
* Overrides the `contentNode` property getter in LuminoJS' TabBar.
|
|
930
|
-
*/
|
|
931
|
-
// @ts-expect-error TS2611 `TabBar<T>.contentNode` is declared as `readonly contentNode` but is implemented as a getter.
|
|
932
|
-
get contentNode(): HTMLUListElement {
|
|
933
|
-
return this.node.getElementsByClassName(ToolbarAwareTabBar.Styles.TAB_BAR_CONTENT)[0] as HTMLUListElement;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
/**
|
|
937
|
-
* Overrides the scrollable host from the parent class.
|
|
938
|
-
*/
|
|
939
|
-
protected get scrollbarHost(): HTMLElement {
|
|
940
|
-
return this.tabBarContainer;
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
protected get tabBarContainer(): HTMLElement {
|
|
944
|
-
return this.node.getElementsByClassName(ToolbarAwareTabBar.Styles.TAB_BAR_CONTENT_CONTAINER)[0] as HTMLElement;
|
|
945
|
-
}
|
|
946
908
|
}
|
|
947
909
|
|
|
948
910
|
export namespace ScrollableTabBar {
|
|
@@ -953,7 +915,6 @@ export namespace ScrollableTabBar {
|
|
|
953
915
|
}
|
|
954
916
|
export namespace Styles {
|
|
955
917
|
|
|
956
|
-
export const TAB_BAR_CONTENT = 'lm-TabBar-content';
|
|
957
918
|
export const TAB_BAR_CONTENT_CONTAINER = 'lm-TabBar-content-container';
|
|
958
919
|
|
|
959
920
|
}
|
|
@@ -978,32 +939,54 @@ export class ToolbarAwareTabBar extends ScrollableTabBar {
|
|
|
978
939
|
protected toolbar: TabBarToolbar | undefined;
|
|
979
940
|
protected breadcrumbsContainer: HTMLElement;
|
|
980
941
|
protected readonly breadcrumbsRenderer: BreadcrumbsRenderer;
|
|
942
|
+
protected dockPanel: TheiaDockPanel;
|
|
981
943
|
|
|
982
944
|
constructor(
|
|
983
945
|
protected readonly tabBarToolbarRegistry: TabBarToolbarRegistry,
|
|
984
946
|
protected readonly tabBarToolbarFactory: () => TabBarToolbar,
|
|
985
947
|
protected readonly breadcrumbsRendererFactory: BreadcrumbsRendererFactory,
|
|
986
|
-
options?: TabBar.IOptions<Widget
|
|
948
|
+
options?: TabBar.IOptions<Widget>,
|
|
949
|
+
scrollbarOptions?: PerfectScrollbar.Options,
|
|
987
950
|
dynamicTabOptions?: ScrollableTabBar.Options
|
|
988
951
|
) {
|
|
989
|
-
super(options, dynamicTabOptions);
|
|
952
|
+
super(options, scrollbarOptions, dynamicTabOptions);
|
|
953
|
+
|
|
990
954
|
this.breadcrumbsRenderer = this.breadcrumbsRendererFactory();
|
|
991
|
-
this.
|
|
955
|
+
this.breadcrumbsContainer = document.createElement('div');
|
|
956
|
+
this.breadcrumbsContainer.classList.add('theia-tabBar-breadcrumb-row');
|
|
957
|
+
this.breadcrumbsContainer.appendChild(this.breadcrumbsRenderer.host);
|
|
958
|
+
this.node.appendChild(this.breadcrumbsContainer);
|
|
959
|
+
|
|
992
960
|
this.toolbar = this.tabBarToolbarFactory();
|
|
993
961
|
this.toDispose.push(this.tabBarToolbarRegistry.onDidChange(() => this.update()));
|
|
994
962
|
this.toDispose.push(this.breadcrumbsRenderer);
|
|
963
|
+
|
|
964
|
+
if (!this.breadcrumbsRenderer.active) {
|
|
965
|
+
this.breadcrumbsContainer.style.setProperty('display', 'none');
|
|
966
|
+
} else {
|
|
967
|
+
this.node.classList.add('theia-tabBar-multirow');
|
|
968
|
+
}
|
|
995
969
|
this.toDispose.push(this.breadcrumbsRenderer.onDidChangeActiveState(active => {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
970
|
+
if (active) {
|
|
971
|
+
this.breadcrumbsContainer.style.removeProperty('display');
|
|
972
|
+
this.node.classList.add('theia-tabBar-multirow');
|
|
973
|
+
} else {
|
|
974
|
+
this.breadcrumbsContainer.style.setProperty('display', 'none');
|
|
975
|
+
this.node.classList.remove('theia-tabBar-multirow');
|
|
976
|
+
}
|
|
977
|
+
if (this.dockPanel) {
|
|
978
|
+
this.dockPanel.fit();
|
|
999
979
|
}
|
|
1000
980
|
}));
|
|
1001
|
-
this.node.classList.toggle('theia-tabBar-multirow', this.breadcrumbsRenderer.active);
|
|
1002
981
|
const handler = () => this.updateBreadcrumbs();
|
|
1003
982
|
this.currentChanged.connect(handler);
|
|
1004
983
|
this.toDispose.push(Disposable.create(() => this.currentChanged.disconnect(handler)));
|
|
1005
984
|
}
|
|
1006
985
|
|
|
986
|
+
setDockPanel(panel: TheiaDockPanel): void {
|
|
987
|
+
this.dockPanel = panel;
|
|
988
|
+
}
|
|
989
|
+
|
|
1007
990
|
protected async updateBreadcrumbs(): Promise<void> {
|
|
1008
991
|
const current = this.currentTitle?.owner;
|
|
1009
992
|
const uri = NavigatableWidget.is(current) ? current.getResourceUri() : undefined;
|
|
@@ -1062,20 +1045,6 @@ export class ToolbarAwareTabBar extends ScrollableTabBar {
|
|
|
1062
1045
|
protected isOver(event: Event, element: Element): boolean {
|
|
1063
1046
|
return element && event.target instanceof Element && element.contains(event.target);
|
|
1064
1047
|
}
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* Restructures the DOM defined in Lumino.
|
|
1068
|
-
*
|
|
1069
|
-
* By default the tabs (`li`) are contained in the `this.contentNode` (`ul`) which is wrapped in a `div` (`this.node`).
|
|
1070
|
-
* Instead of this structure, we add a container for the `this.contentNode` and for the toolbar.
|
|
1071
|
-
* The scrollbar will only work for the `ul` part but it does not affect the toolbar, so it can be on the right hand-side.
|
|
1072
|
-
*/
|
|
1073
|
-
protected addBreadcrumbs(): void {
|
|
1074
|
-
this.breadcrumbsContainer = document.createElement('div');
|
|
1075
|
-
this.breadcrumbsContainer.classList.add('theia-tabBar-breadcrumb-row');
|
|
1076
|
-
this.breadcrumbsContainer.appendChild(this.breadcrumbsRenderer.host);
|
|
1077
|
-
this.node.appendChild(this.breadcrumbsContainer);
|
|
1078
|
-
}
|
|
1079
1048
|
}
|
|
1080
1049
|
|
|
1081
1050
|
/**
|
|
@@ -1256,7 +1225,7 @@ export class SideTabBar extends ScrollableTabBar {
|
|
|
1256
1225
|
return;
|
|
1257
1226
|
}
|
|
1258
1227
|
|
|
1259
|
-
if ((newOverflowingTabs.length !== this.tabsOverflowData?.titles.length ?? 0) ||
|
|
1228
|
+
if ((newOverflowingTabs.length !== (this.tabsOverflowData?.titles.length ?? 0)) ||
|
|
1260
1229
|
newOverflowingTabs.find((newTitle, i) => newTitle !== this.tabsOverflowData?.titles[i]) !== undefined) {
|
|
1261
1230
|
this.tabsOverflowData = { titles: newOverflowingTabs, startIndex };
|
|
1262
1231
|
this.tabsOverflowChanged.emit(this.tabsOverflowData);
|
|
@@ -21,6 +21,7 @@ import { Disposable, DisposableCollection } from '../../common/disposable';
|
|
|
21
21
|
import { UnsafeWidgetUtilities } from '../widgets';
|
|
22
22
|
import { CorePreferences } from '../core-preferences';
|
|
23
23
|
import { Emitter, Event, environment } from '../../common';
|
|
24
|
+
import { ToolbarAwareTabBar } from './tab-bars';
|
|
24
25
|
|
|
25
26
|
export const MAXIMIZED_CLASS = 'theia-maximized';
|
|
26
27
|
export const ACTIVE_TABBAR_CLASS = 'theia-tabBar-active';
|
|
@@ -63,6 +64,15 @@ export class TheiaDockPanel extends DockPanel {
|
|
|
63
64
|
this.markAsCurrent(args.currentTitle || undefined);
|
|
64
65
|
super['_onCurrentChanged'](sender, args);
|
|
65
66
|
};
|
|
67
|
+
|
|
68
|
+
this['_createTabBar'] = () => {
|
|
69
|
+
// necessary for https://github.com/eclipse-theia/theia/issues/15273
|
|
70
|
+
const tabBar = super['_createTabBar']();
|
|
71
|
+
if (tabBar instanceof ToolbarAwareTabBar) {
|
|
72
|
+
tabBar.setDockPanel(this);
|
|
73
|
+
}
|
|
74
|
+
return tabBar;
|
|
75
|
+
};
|
|
66
76
|
this['_onTabActivateRequested'] = (sender: TabBar<Widget>, args: TabBar.ITabActivateRequestedArgs<Widget>) => {
|
|
67
77
|
this.markAsCurrent(args.title);
|
|
68
78
|
super['_onTabActivateRequested'](sender, args);
|
|
@@ -221,6 +221,8 @@ blockquote {
|
|
|
221
221
|
|
|
222
222
|
.lm-Widget {
|
|
223
223
|
font-size: var(--theia-ui-font-size1);
|
|
224
|
+
/** We override the contain of lm-Widget to make sure Monaco autocomplete etc. is correctly applied */
|
|
225
|
+
contain: none !important;
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
.lm-Widget.lm-mod-hidden {
|
|
@@ -459,7 +459,7 @@
|
|
|
459
459
|
}
|
|
460
460
|
|
|
461
461
|
.theia-tabBar-breadcrumb-row {
|
|
462
|
-
|
|
462
|
+
width: 100%;
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
.lm-TabBar.theia-tabBar-multirow[data-orientation="horizontal"] {
|
|
@@ -470,7 +470,7 @@
|
|
|
470
470
|
.lm-TabBar[data-orientation="horizontal"] .theia-tabBar-tab-row {
|
|
471
471
|
display: flex;
|
|
472
472
|
flex-flow: row nowrap;
|
|
473
|
-
|
|
473
|
+
width: 100%;
|
|
474
474
|
}
|
|
475
475
|
|
|
476
476
|
.lm-TabBar[data-orientation="vertical"] .theia-tabBar-tab-row {
|
|
@@ -90,10 +90,10 @@ export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHan
|
|
|
90
90
|
*/
|
|
91
91
|
async open(uri: URI, options?: WidgetOpenerOptions): Promise<W> {
|
|
92
92
|
const widget = await this.getOrCreateWidget(uri, options);
|
|
93
|
-
await this.doOpen(widget, options);
|
|
93
|
+
await this.doOpen(widget, uri, options);
|
|
94
94
|
return widget;
|
|
95
95
|
}
|
|
96
|
-
protected async doOpen(widget: W, options?: WidgetOpenerOptions): Promise<void> {
|
|
96
|
+
protected async doOpen(widget: W, uri: URI, options?: WidgetOpenerOptions): Promise<void> {
|
|
97
97
|
const op: WidgetOpenerOptions = {
|
|
98
98
|
mode: 'activate',
|
|
99
99
|
...options
|
|
@@ -207,10 +207,11 @@ export class BaseWidget extends Widget implements PreviewableWidget {
|
|
|
207
207
|
this.toDisposeOnDetach.push(addEventListener(element, type, listener, useCapture));
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
protected addKeyListener<K extends keyof HTMLElementEventMap>(
|
|
210
|
+
protected addKeyListener<K extends keyof HTMLElementEventMap = never>(
|
|
211
211
|
element: HTMLElement,
|
|
212
212
|
keysOrKeyCodes: KeyCode.Predicate | KeysOrKeyCodes,
|
|
213
|
-
action:
|
|
213
|
+
action: EventHandler<K | 'keydown'>,
|
|
214
|
+
...additionalEventTypes: K[]): void {
|
|
214
215
|
this.toDisposeOnDetach.push(addKeyListener(element, keysOrKeyCodes, action, ...additionalEventTypes));
|
|
215
216
|
}
|
|
216
217
|
|
|
@@ -259,6 +260,8 @@ export function createIconButton(...classNames: string[]): HTMLSpanElement {
|
|
|
259
260
|
|
|
260
261
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
261
262
|
export type EventListener<K extends keyof HTMLElementEventMap> = (this: HTMLElement, event: HTMLElementEventMap[K]) => any;
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
264
|
+
export type EventHandler<K extends keyof HTMLElementEventMap> = (event: HTMLElementEventMap[K]) => any;
|
|
262
265
|
export interface EventListenerObject<K extends keyof HTMLElementEventMap> {
|
|
263
266
|
handleEvent(evt: HTMLElementEventMap[K]): void;
|
|
264
267
|
}
|
|
@@ -277,10 +280,12 @@ export function addEventListener<K extends keyof HTMLElementEventMap>(
|
|
|
277
280
|
);
|
|
278
281
|
}
|
|
279
282
|
|
|
280
|
-
export function addKeyListener<K extends keyof HTMLElementEventMap>(
|
|
283
|
+
export function addKeyListener<K extends keyof HTMLElementEventMap = never>(
|
|
281
284
|
element: HTMLElement,
|
|
282
285
|
keysOrKeyCodes: KeyCode.Predicate | KeysOrKeyCodes,
|
|
283
|
-
action:
|
|
286
|
+
action: EventHandler<K | 'keydown'>,
|
|
287
|
+
...additionalEventTypes: K[]): Disposable {
|
|
288
|
+
type HandledEvent = Parameters<typeof action>[0];
|
|
284
289
|
|
|
285
290
|
const toDispose = new DisposableCollection();
|
|
286
291
|
const keyCodePredicate = (() => {
|
|
@@ -293,7 +298,7 @@ export function addKeyListener<K extends keyof HTMLElementEventMap>(
|
|
|
293
298
|
toDispose.push(addEventListener(element, 'keydown', e => {
|
|
294
299
|
const kc = KeyCode.createKeyCode(e);
|
|
295
300
|
if (keyCodePredicate(kc)) {
|
|
296
|
-
const result = action(e);
|
|
301
|
+
const result = action(e as HandledEvent);
|
|
297
302
|
if (typeof result !== 'boolean' || result) {
|
|
298
303
|
e.stopPropagation();
|
|
299
304
|
e.preventDefault();
|
|
@@ -302,9 +307,7 @@ export function addKeyListener<K extends keyof HTMLElementEventMap>(
|
|
|
302
307
|
}));
|
|
303
308
|
for (const type of additionalEventTypes) {
|
|
304
309
|
toDispose.push(addEventListener(element, type, e => {
|
|
305
|
-
|
|
306
|
-
const event = (type as any)['keydown'];
|
|
307
|
-
const result = action(event);
|
|
310
|
+
const result = action(e as HandledEvent);
|
|
308
311
|
if (typeof result !== 'boolean' || result) {
|
|
309
312
|
e.stopPropagation();
|
|
310
313
|
e.preventDefault();
|
package/src/common/path.spec.ts
CHANGED
|
@@ -271,6 +271,10 @@ describe('Path', () => {
|
|
|
271
271
|
});
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
+
it('Should not produce joined paths with double initial //', () => {
|
|
275
|
+
expect(new Path('/').join('/something/absolute').toString()).eq('/something/absolute');
|
|
276
|
+
});
|
|
277
|
+
|
|
274
278
|
const linuxHome = '/home/test-user';
|
|
275
279
|
const windowsHome = '/C:/Users/test-user';
|
|
276
280
|
|
package/src/common/path.ts
CHANGED
|
@@ -215,10 +215,7 @@ export class Path {
|
|
|
215
215
|
if (!relativePath) {
|
|
216
216
|
return this;
|
|
217
217
|
}
|
|
218
|
-
|
|
219
|
-
return new Path(this.raw + relativePath);
|
|
220
|
-
}
|
|
221
|
-
return new Path(this.raw + Path.separator + relativePath);
|
|
218
|
+
return new Path(this.raw + Path.separator + relativePath).normalize();
|
|
222
219
|
}
|
|
223
220
|
|
|
224
221
|
/**
|
|
@@ -55,19 +55,18 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
|
|
|
55
55
|
const dataFolderPath = join(BackendApplicationPath, 'data');
|
|
56
56
|
const userDataPath = join(dataFolderPath, 'user-data');
|
|
57
57
|
const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath);
|
|
58
|
+
let theiaConfigDir: string;
|
|
58
59
|
if (dataFolderExists) {
|
|
59
60
|
const userDataExists = this.pathExistenceCache[userDataPath] ??= await pathExists(userDataPath);
|
|
60
|
-
if (userDataExists) {
|
|
61
|
-
process.env.THEIA_CONFIG_DIR = userDataPath;
|
|
62
|
-
} else {
|
|
61
|
+
if (!userDataExists) {
|
|
63
62
|
await mkdir(userDataPath);
|
|
64
|
-
process.env.THEIA_CONFIG_DIR = userDataPath;
|
|
65
63
|
this.pathExistenceCache[userDataPath] = true;
|
|
66
64
|
}
|
|
65
|
+
theiaConfigDir = userDataPath;
|
|
67
66
|
} else {
|
|
68
|
-
|
|
67
|
+
theiaConfigDir = join(homedir(), BackendApplicationConfigProvider.get().configurationFolder);
|
|
69
68
|
}
|
|
70
|
-
return FileUri.create(
|
|
69
|
+
return FileUri.create(theiaConfigDir).toString();
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
async getExecPath(): Promise<string> {
|