chrome-devtools-frontend 1.0.1701636 → 1.0.1703574
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/eslint.config.mjs +3 -1
- package/front_end/core/common/ParsedURL.ts +5 -1
- package/front_end/core/host/UserMetricsEnums.ts +2 -1
- package/front_end/core/root/ExperimentNames.ts +1 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -7
- package/front_end/core/text_utils/Markdown.ts +73 -0
- package/front_end/core/text_utils/text_utils.ts +2 -0
- package/front_end/devtools_compatibility.js +2 -1
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +6 -4
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +6 -0
- package/front_end/generated/protocol.ts +22 -3
- package/front_end/models/ai_assistance/AiAgent2.ts +13 -1
- package/front_end/models/ai_assistance/AiConversation.ts +1 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +13 -19
- package/front_end/models/change_tracker/ChangeTracker.ts +5 -64
- package/front_end/models/comment_manager/CD4ABridge.ts +5 -0
- package/front_end/models/comment_manager/CommentManager.ts +3 -5
- package/front_end/models/comment_manager/CommentThread.ts +30 -13
- package/front_end/models/issues_manager/CookieDeprecationMetadataIssue.ts +6 -7
- package/front_end/models/issues_manager/DeprecationIssue.ts +1 -1
- package/front_end/models/issues_manager/MarkdownIssueDescription.ts +18 -52
- package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -4
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantRead.md +0 -1
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantReadOptOut.md +5 -0
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSet.md +0 -1
- package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSetOptOut.md +5 -0
- package/front_end/models/issues_manager/descriptions/deprecation.md +1 -1
- package/front_end/models/issues_manager/descriptions/sriValidationFailedIntegrityMismatch.md +2 -0
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +1 -1
- package/front_end/models/persistence/NetworkPersistenceManager.ts +14 -2
- package/front_end/panels/common/CommentThreadWidget.ts +29 -10
- package/front_end/panels/common/CommentsOverlayWidget.ts +50 -14
- package/front_end/panels/common/CommentsStatusBarPill.ts +40 -7
- package/front_end/panels/common/commentThreadWidget.css +11 -0
- package/front_end/panels/common/commentsStatusBarPill.css +13 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +10 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +101 -49
- package/front_end/panels/elements/components/CSSQuery.ts +1 -1
- package/front_end/panels/elements/components/cssQuery.css +4 -0
- package/front_end/panels/elements/elements.ts +0 -1
- package/front_end/panels/elements/stylesSidebarPane.css +6 -0
- package/front_end/panels/issues/IssueView.ts +5 -1
- package/front_end/panels/sources/ResourceOriginPlugin.ts +8 -3
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -4
- package/front_end/panels/sources/SourcesView.ts +127 -147
- package/front_end/panels/sources/TabbedEditorContainer.ts +518 -246
- package/front_end/panels/sources/UISourceCodeFrame.ts +9 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/chromium/client-variations/ClientVariations.js +25 -96
- package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/legacy.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
- package/front_end/third_party/codemirror.next/package.json +4 -1
- package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
- package/front_end/ui/comments/CommentOverlayManager.ts +11 -10
- package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +59 -0
- package/front_end/ui/components/markdown_view/markdown_view.ts +2 -0
- package/front_end/ui/legacy/TabbedPane.ts +51 -40
- package/front_end/ui/legacy/Treeoutline.ts +28 -19
- package/front_end/ui/legacy/UIUtils.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +424 -570
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -27
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +2 -1
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
+
import '../../ui/components/tooltips/tooltips.js';
|
|
6
|
+
import '../../ui/kit/kit.js';
|
|
7
|
+
|
|
5
8
|
import * as Common from '../../core/common/common.js';
|
|
6
9
|
import * as Host from '../../core/host/host.js';
|
|
7
10
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
@@ -10,12 +13,10 @@ import * as TextUtils from '../../core/text_utils/text_utils.js';
|
|
|
10
13
|
import * as Persistence from '../../models/persistence/persistence.js';
|
|
11
14
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
12
15
|
import type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
|
|
13
|
-
import * as Tooltips from '../../ui/components/tooltips/tooltips.js';
|
|
14
16
|
import * as uiI18n from '../../ui/i18n/i18n.js';
|
|
15
|
-
import {Icon, Link} from '../../ui/kit/kit.js';
|
|
16
17
|
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
|
17
18
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
18
|
-
import {html, render} from '../../ui/lit/lit.js';
|
|
19
|
+
import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
|
|
19
20
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
20
21
|
import * as PanelCommon from '../common/common.js';
|
|
21
22
|
import * as Snippets from '../snippets/snippets.js';
|
|
@@ -75,6 +76,8 @@ const UIStrings = {
|
|
|
75
76
|
} as const;
|
|
76
77
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/TabbedEditorContainer.ts', UIStrings);
|
|
77
78
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
79
|
+
const {repeat} = Directives;
|
|
80
|
+
const {widget} = UI.Widget;
|
|
78
81
|
|
|
79
82
|
const enum SourceViewType {
|
|
80
83
|
IMAGE_VIEW = 'ImageView',
|
|
@@ -84,6 +87,191 @@ const enum SourceViewType {
|
|
|
84
87
|
}
|
|
85
88
|
const HEADER_OVERRIDES_FILENAME = '.headers';
|
|
86
89
|
|
|
90
|
+
interface TabInfo {
|
|
91
|
+
tabId: string;
|
|
92
|
+
title: string;
|
|
93
|
+
tooltip: string;
|
|
94
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
|
95
|
+
isCloseable: boolean;
|
|
96
|
+
widget?: UI.Widget.Widget;
|
|
97
|
+
hasLoadError: boolean;
|
|
98
|
+
hasUnsavedCommittedChanges: boolean;
|
|
99
|
+
disconnectedAutomaticFileSystemRoot?: string;
|
|
100
|
+
icon?: LitTemplate;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface TabbedEditorViewInput {
|
|
104
|
+
openTabs: TabInfo[];
|
|
105
|
+
activeTabId?: string;
|
|
106
|
+
leftToolbarItems: Array<UI.Toolbar.ToolbarItem|LitTemplate>;
|
|
107
|
+
rightToolbarItems: Array<UI.Toolbar.ToolbarItem|LitTemplate>;
|
|
108
|
+
tabDelegate: UI.TabbedPane.TabbedPaneTabDelegate;
|
|
109
|
+
shortcuts: Array<{
|
|
110
|
+
description: Platform.UIString.LocalizedString,
|
|
111
|
+
onClick: () => void,
|
|
112
|
+
keys: string[],
|
|
113
|
+
}>;
|
|
114
|
+
onAddFileSystemClicked: () => void;
|
|
115
|
+
onConnectAutomaticFileSystem: (e: Event) => void;
|
|
116
|
+
onClose: (e: Event) => void;
|
|
117
|
+
onTabOrderChanged: (e: Event) => void;
|
|
118
|
+
onSelect: (e: Event) => void;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type View = (input: TabbedEditorViewInput, output: undefined, target: HTMLElement) => void;
|
|
122
|
+
|
|
123
|
+
const UI_SOURCE_CODE_WIDGET_MAP = new WeakMap<Workspace.UISourceCode.UISourceCode, UI.Widget.Widget>();
|
|
124
|
+
|
|
125
|
+
function getOrCreateSourceView(uiSourceCode: Workspace.UISourceCode.UISourceCode,
|
|
126
|
+
onCreate: (view: UI.Widget.Widget) => void): UI.Widget.Widget {
|
|
127
|
+
const existing = UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
128
|
+
if (existing) {
|
|
129
|
+
return existing;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let sourceView: UI.Widget.Widget;
|
|
133
|
+
const contentType = uiSourceCode.contentType();
|
|
134
|
+
if (contentType === Common.ResourceType.resourceTypes.Image || uiSourceCode.mimeType().startsWith('image/')) {
|
|
135
|
+
sourceView = new SourceFrame.ImageView.ImageView(uiSourceCode.mimeType(), uiSourceCode);
|
|
136
|
+
} else if (contentType === Common.ResourceType.resourceTypes.Font || uiSourceCode.mimeType().includes('font')) {
|
|
137
|
+
sourceView = new SourceFrame.FontView.FontView(uiSourceCode.mimeType(), uiSourceCode);
|
|
138
|
+
} else if (uiSourceCode.name() === Persistence.NetworkPersistenceManager.HEADERS_FILENAME) {
|
|
139
|
+
sourceView = new Components.HeadersView.HeadersView(uiSourceCode);
|
|
140
|
+
} else {
|
|
141
|
+
sourceView = new UISourceCodeFrame(uiSourceCode);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
UI_SOURCE_CODE_WIDGET_MAP.set(uiSourceCode, sourceView);
|
|
145
|
+
onCreate(sourceView);
|
|
146
|
+
return sourceView;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function recycleUISourceCodeFrame(sourceFrame: UISourceCodeFrame,
|
|
150
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
151
|
+
UI_SOURCE_CODE_WIDGET_MAP.delete(sourceFrame.uiSourceCode());
|
|
152
|
+
sourceFrame.setUISourceCode(uiSourceCode);
|
|
153
|
+
UI_SOURCE_CODE_WIDGET_MAP.set(uiSourceCode, sourceFrame);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getViewByUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget|undefined {
|
|
157
|
+
return UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function removeSourceViewCache(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget|undefined {
|
|
161
|
+
const view = UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
162
|
+
if (view) {
|
|
163
|
+
UI_SOURCE_CODE_WIDGET_MAP.delete(uiSourceCode);
|
|
164
|
+
}
|
|
165
|
+
return view;
|
|
166
|
+
}
|
|
167
|
+
function renderPlaceholder(input: TabbedEditorViewInput): LitTemplate {
|
|
168
|
+
// clang-format off
|
|
169
|
+
return html`
|
|
170
|
+
<div class="sources-placeholder">
|
|
171
|
+
<div class="tabbed-pane-placeholder-row workspace">
|
|
172
|
+
<span class="icon-container">
|
|
173
|
+
<devtools-icon name="sync" class="sync-icon"></devtools-icon>
|
|
174
|
+
</span>
|
|
175
|
+
<span>
|
|
176
|
+
${i18nString(UIStrings.workspaceDropInAFolderToSyncSources)}
|
|
177
|
+
<button @click=${input.onAddFileSystemClicked}>${i18nString(UIStrings.selectFolder)}</button>
|
|
178
|
+
</span>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="shortcuts-list tabbed-pane-placeholder-row" role="list"
|
|
181
|
+
aria-label=${i18nString(UIStrings.sourceViewActions)}>
|
|
182
|
+
${input.shortcuts.map(shortcut => !shortcut.keys.length
|
|
183
|
+
? html`<div class="shortcut-line" role="listitem"></div>`
|
|
184
|
+
: html`<div class="shortcut-line" role="listitem">
|
|
185
|
+
<button @click=${shortcut.onClick}>${shortcut.description}</button>
|
|
186
|
+
<span class="shortcuts">
|
|
187
|
+
${shortcut.keys.map(key => html`
|
|
188
|
+
<span class="keybinds-key"><span>${key}</span></span>
|
|
189
|
+
`)}
|
|
190
|
+
</span>
|
|
191
|
+
</div>`)}
|
|
192
|
+
</div>
|
|
193
|
+
</div>`;
|
|
194
|
+
// clang-format on
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function renderTabIcon(tab: TabInfo): LitTemplate {
|
|
198
|
+
if (tab.hasLoadError) {
|
|
199
|
+
// clang-format off
|
|
200
|
+
return html`
|
|
201
|
+
<span slot="icon">
|
|
202
|
+
<devtools-icon class="small" name="cross-circle-filled"
|
|
203
|
+
title=${i18nString(UIStrings.unableToLoadThisContent)}>
|
|
204
|
+
</devtools-icon>
|
|
205
|
+
</span>`;
|
|
206
|
+
// clang-format on
|
|
207
|
+
}
|
|
208
|
+
if (tab.icon) {
|
|
209
|
+
return html`<span slot="icon">${tab.icon}</span>`;
|
|
210
|
+
}
|
|
211
|
+
return nothing;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function renderTabSuffix(tab: TabInfo, input: TabbedEditorViewInput): LitTemplate {
|
|
215
|
+
if (!tab.hasUnsavedCommittedChanges) {
|
|
216
|
+
return nothing;
|
|
217
|
+
}
|
|
218
|
+
const tooltipId = `tab-tooltip-${tab.tabId}`;
|
|
219
|
+
// clang-format off
|
|
220
|
+
return html`
|
|
221
|
+
<span slot="suffix">
|
|
222
|
+
<div>
|
|
223
|
+
<devtools-icon name="warning-filled" class="small" aria-describedby=${tooltipId}></devtools-icon>
|
|
224
|
+
<devtools-tooltip id=${tooltipId} variant="rich">
|
|
225
|
+
${tab.disconnectedAutomaticFileSystemRoot !== undefined
|
|
226
|
+
? uiI18n.getFormatLocalizedStringTemplate(
|
|
227
|
+
str_, UIStrings.changesWereNotSavedToFileSystemToSaveAddFolderToWorkspace, {
|
|
228
|
+
PH1: html`<devtools-link class="devtools-link" @click=${input.onConnectAutomaticFileSystem}>${
|
|
229
|
+
tab.disconnectedAutomaticFileSystemRoot}</devtools-link>`,
|
|
230
|
+
})
|
|
231
|
+
: uiI18n.getFormatLocalizedStringTemplate(
|
|
232
|
+
str_, UIStrings.changesWereNotSavedToFileSystemToSaveSetUpYourWorkspace, {
|
|
233
|
+
PH1: html`<devtools-link href="https://developer.chrome.com/docs/devtools/workspaces/">Workspace</devtools-link>`,
|
|
234
|
+
})}
|
|
235
|
+
</devtools-tooltip>
|
|
236
|
+
</div>
|
|
237
|
+
</span>`;
|
|
238
|
+
// clang-format on
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
242
|
+
// clang-format off
|
|
243
|
+
render(html`
|
|
244
|
+
<devtools-tabbed-pane
|
|
245
|
+
class="flex-auto vbox"
|
|
246
|
+
.closeableTabs=${true}
|
|
247
|
+
.allowTabReorder=${true}
|
|
248
|
+
.automaticReorder=${true}
|
|
249
|
+
.tabDelegate=${input.tabDelegate}
|
|
250
|
+
.headerJslog=${`${VisualLogging.toolbar('top').track({keydown: 'ArrowUp|ArrowLeft|ArrowDown|ArrowRight|Enter|Space'})}`}
|
|
251
|
+
.placeholder=${renderPlaceholder(input)}
|
|
252
|
+
@close=${input.onClose}
|
|
253
|
+
@taborderchanged=${input.onTabOrderChanged}
|
|
254
|
+
@select=${input.onSelect}
|
|
255
|
+
>
|
|
256
|
+
<devtools-toolbar class="tabbed-pane-left-toolbar" slot="left">
|
|
257
|
+
${input.leftToolbarItems.map(item => item instanceof UI.Toolbar.ToolbarItem ? item.element : item)}
|
|
258
|
+
</devtools-toolbar>
|
|
259
|
+
<devtools-toolbar class="tabbed-pane-right-toolbar" slot="right">
|
|
260
|
+
${input.rightToolbarItems.map(item => item instanceof UI.Toolbar.ToolbarItem ? item.element : item)}
|
|
261
|
+
</devtools-toolbar>
|
|
262
|
+
${repeat(input.openTabs, tab => tab.tabId, tab => html`
|
|
263
|
+
<div id=${tab.tabId}
|
|
264
|
+
title=${tab.title}
|
|
265
|
+
?closeable=${tab.isCloseable}
|
|
266
|
+
?selected=${input.activeTabId === tab.tabId}
|
|
267
|
+
style="display: flex; flex: auto;">
|
|
268
|
+
${renderTabIcon(tab)}
|
|
269
|
+
${renderTabSuffix(tab, input)}
|
|
270
|
+
${tab.widget ? html`${widget(UI.Widget.WrapperWidget, {widget: tab.widget})}` : nothing}
|
|
271
|
+
</div>`)}
|
|
272
|
+
</devtools-tabbed-pane>`, target);
|
|
273
|
+
// clang-format on
|
|
274
|
+
};
|
|
87
275
|
let tabId = 0;
|
|
88
276
|
|
|
89
277
|
const TabbedEditorContainerBase: Common.ObjectWrapper.EventMixin<EventTypes, typeof UI.Widget.VBox> =
|
|
@@ -92,17 +280,174 @@ const TabbedEditorContainerBase: Common.ObjectWrapper.EventMixin<EventTypes, typ
|
|
|
92
280
|
);
|
|
93
281
|
|
|
94
282
|
export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
283
|
+
override focus(): void {
|
|
284
|
+
if (this.visibleView) {
|
|
285
|
+
this.visibleView.focus();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
#scheduleUpdate(): void {
|
|
290
|
+
this.performUpdate();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
override performUpdate(): void {
|
|
294
|
+
if (false) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const shortcuts = [
|
|
298
|
+
{actionId: 'quick-open.show', description: i18nString(UIStrings.openFile)},
|
|
299
|
+
{actionId: 'quick-open.show-command-menu', description: i18nString(UIStrings.runCommand)},
|
|
300
|
+
];
|
|
301
|
+
const separator = Host.Platform.isMac() ? '\u2004' : ' + ';
|
|
302
|
+
const shortcutElements = shortcuts.map(shortcut => {
|
|
303
|
+
const shortcutKeys = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(shortcut.actionId);
|
|
304
|
+
if (!shortcutKeys?.[0]) {
|
|
305
|
+
return {
|
|
306
|
+
description: shortcut.description,
|
|
307
|
+
onClick: () => {},
|
|
308
|
+
keys: [],
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const action = UI.ActionRegistry.ActionRegistry.instance().getAction(shortcut.actionId);
|
|
312
|
+
const keys = shortcutKeys[0].descriptors.flatMap(descriptor => descriptor.name.split(separator));
|
|
313
|
+
return {
|
|
314
|
+
description: shortcut.description,
|
|
315
|
+
onClick: () => {
|
|
316
|
+
void action.execute();
|
|
317
|
+
},
|
|
318
|
+
keys,
|
|
319
|
+
};
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const input: TabbedEditorViewInput = {
|
|
323
|
+
openTabs: [...this.files.entries()].map(([tabId, uiSourceCode]) => {
|
|
324
|
+
const hasLoadError = Boolean(uiSourceCode.loadError()) || this.#loadErrorFiles.has(uiSourceCode);
|
|
325
|
+
const hasUnsavedCommittedChanges = !hasLoadError &&
|
|
326
|
+
Persistence.Persistence.PersistenceImpl.instance().hasUnsavedCommittedChanges(uiSourceCode);
|
|
327
|
+
let disconnectedAutomaticFileSystemRoot: string|undefined;
|
|
328
|
+
if (hasUnsavedCommittedChanges) {
|
|
329
|
+
const {automaticFileSystem} = Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.instance();
|
|
330
|
+
if (automaticFileSystem?.state === 'disconnected') {
|
|
331
|
+
disconnectedAutomaticFileSystemRoot = Common.ParsedURL.ParsedURL.extractName(automaticFileSystem.root);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const icon = !hasLoadError ?
|
|
335
|
+
(PanelCommon.PersistenceUtils.PersistenceUtils.iconForUISourceCode(uiSourceCode) ?? undefined) :
|
|
336
|
+
undefined;
|
|
337
|
+
return {
|
|
338
|
+
tabId,
|
|
339
|
+
title: this.titleForFile(uiSourceCode),
|
|
340
|
+
tooltip: this.tooltipForFile(uiSourceCode),
|
|
341
|
+
uiSourceCode,
|
|
342
|
+
isCloseable: true,
|
|
343
|
+
hasLoadError,
|
|
344
|
+
hasUnsavedCommittedChanges,
|
|
345
|
+
disconnectedAutomaticFileSystemRoot,
|
|
346
|
+
icon,
|
|
347
|
+
widget: (this.#currentFile === uiSourceCode) ? this.getOrCreateSourceView(uiSourceCode) :
|
|
348
|
+
this.getCreatedSourceView(uiSourceCode),
|
|
349
|
+
};
|
|
350
|
+
}),
|
|
351
|
+
activeTabId: this.#currentFile ? this.tabIds.get(this.#currentFile) : undefined,
|
|
352
|
+
leftToolbarItems: this.#leftToolbarItems,
|
|
353
|
+
rightToolbarItems: this.#rightToolbarItems,
|
|
354
|
+
tabDelegate: this.#tabDelegate,
|
|
355
|
+
shortcuts: shortcutElements,
|
|
356
|
+
onAddFileSystemClicked: () => {
|
|
357
|
+
void this.#addFileSystemClicked();
|
|
358
|
+
},
|
|
359
|
+
onConnectAutomaticFileSystem: async (event: Event) => {
|
|
360
|
+
event.consume();
|
|
361
|
+
await UI.ViewManager.ViewManager.instance().showView('navigator-files');
|
|
362
|
+
await Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.instance().connectAutomaticFileSystem(
|
|
363
|
+
/* addIfMissing= */ true);
|
|
364
|
+
},
|
|
365
|
+
onClose: (e: Event) => {
|
|
366
|
+
this.tabClosed((e as CustomEvent<{tabId: string}>).detail.tabId,
|
|
367
|
+
(e as CustomEvent<{isUserGesture?: boolean}>).detail.isUserGesture);
|
|
368
|
+
this.#scheduleUpdate();
|
|
369
|
+
},
|
|
370
|
+
onTabOrderChanged: (e: Event) => {
|
|
371
|
+
const tabIds = (e as CustomEvent<{tabIds: string[]}>).detail.tabIds;
|
|
372
|
+
const newFiles = new Map<string, Workspace.UISourceCode.UISourceCode>();
|
|
373
|
+
for (const id of tabIds) {
|
|
374
|
+
if (this.files.has(id)) {
|
|
375
|
+
const file = this.files.get(id);
|
|
376
|
+
if (file) {
|
|
377
|
+
newFiles.set(id, file);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
this.files = newFiles;
|
|
382
|
+
this.#scheduleUpdate();
|
|
383
|
+
},
|
|
384
|
+
onSelect: (e: Event) => {
|
|
385
|
+
this.tabSelected((e as CustomEvent<{tabId: string}>).detail.tabId,
|
|
386
|
+
(e as CustomEvent<{isUserGesture?: boolean}>).detail.isUserGesture);
|
|
387
|
+
this.#scheduleUpdate();
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
this.#view(input, undefined, this.contentElement);
|
|
391
|
+
}
|
|
95
392
|
#historyManager!: EditingLocationHistoryManager;
|
|
96
393
|
set historyManager(historyManager: EditingLocationHistoryManager) {
|
|
97
394
|
this.#historyManager = historyManager;
|
|
98
395
|
}
|
|
99
|
-
|
|
100
|
-
|
|
396
|
+
|
|
397
|
+
#leftToolbarItems: Array<UI.Toolbar.ToolbarItem|LitTemplate> = [];
|
|
398
|
+
set leftToolbarItems(items: Array<UI.Toolbar.ToolbarItem|LitTemplate>) {
|
|
399
|
+
if (this.#leftToolbarItems === items) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
this.#leftToolbarItems = items;
|
|
403
|
+
this.#scheduleUpdate();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
#rightToolbarItems: Array<UI.Toolbar.ToolbarItem|LitTemplate> = [];
|
|
407
|
+
set rightToolbarItems(items: Array<UI.Toolbar.ToolbarItem|LitTemplate>) {
|
|
408
|
+
if (this.#rightToolbarItems === items) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
this.#rightToolbarItems = items;
|
|
412
|
+
this.#scheduleUpdate();
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
readonly #syncedUISourceCodes = new Set<Workspace.UISourceCode.UISourceCode>();
|
|
416
|
+
set uiSourceCodes(uiSourceCodes: ReadonlySet<Workspace.UISourceCode.UISourceCode>) {
|
|
417
|
+
const removed: Workspace.UISourceCode.UISourceCode[] = [];
|
|
418
|
+
for (const existing of this.#syncedUISourceCodes) {
|
|
419
|
+
if (!uiSourceCodes.has(existing)) {
|
|
420
|
+
removed.push(existing);
|
|
421
|
+
this.#syncedUISourceCodes.delete(existing);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (removed.length > 0) {
|
|
425
|
+
this.removeUISourceCodes(removed);
|
|
426
|
+
}
|
|
427
|
+
UI.UIUtils.startBatchUpdate();
|
|
428
|
+
for (const uiSourceCode of uiSourceCodes) {
|
|
429
|
+
if (!this.#syncedUISourceCodes.has(uiSourceCode)) {
|
|
430
|
+
this.#syncedUISourceCodes.add(uiSourceCode);
|
|
431
|
+
this.addUISourceCode(uiSourceCode);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
UI.UIUtils.endBatchUpdate();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
onEditorSelected?: (event: EditorSelectedEvent) => void;
|
|
438
|
+
onEditorClosed?: (uiSourceCode: Workspace.UISourceCode.UISourceCode) => void;
|
|
439
|
+
|
|
440
|
+
readonly #view: View;
|
|
441
|
+
readonly #tabDelegate: EditorContainerTabDelegate;
|
|
101
442
|
private tabIds: Map<Workspace.UISourceCode.UISourceCode, string>;
|
|
102
|
-
private
|
|
443
|
+
private files: Map<string, Workspace.UISourceCode.UISourceCode>;
|
|
444
|
+
readonly #loadErrorFiles = new Set<Workspace.UISourceCode.UISourceCode>();
|
|
103
445
|
#previouslyViewedFilesSetting!: Common.Settings.Setting<SerializedHistoryItem[]>;
|
|
104
446
|
history!: History;
|
|
105
447
|
set previouslyViewedFilesSetting(setting: Common.Settings.Setting<SerializedHistoryItem[]>) {
|
|
448
|
+
if (this.#previouslyViewedFilesSetting === setting) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
106
451
|
this.#previouslyViewedFilesSetting = setting;
|
|
107
452
|
this.history = History.fromObject(this.#previouslyViewedFilesSetting.get());
|
|
108
453
|
}
|
|
@@ -115,47 +460,42 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
115
460
|
private currentView!: UI.Widget.Widget|null;
|
|
116
461
|
private scrollTimer?: number;
|
|
117
462
|
private reentrantShow: boolean;
|
|
118
|
-
constructor(element?: HTMLElement) {
|
|
463
|
+
constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
|
|
119
464
|
super(element);
|
|
120
|
-
|
|
121
|
-
this
|
|
122
|
-
// eslint-disable-next-line @devtools/no-imperative-dom-api
|
|
123
|
-
this.tabbedPane.show(this.contentElement);
|
|
124
|
-
// eslint-disable-next-line @devtools/no-imperative-dom-api
|
|
125
|
-
const placeholderElement = document.createElement('div');
|
|
126
|
-
placeholderElement.classList.add('sources-placeholder');
|
|
127
|
-
this.tabbedPane.setPlaceholderElement(placeholderElement);
|
|
128
|
-
this.#renderPlaceholder(placeholderElement as HTMLElement);
|
|
129
|
-
this.tabbedPane.setTabDelegate(new EditorContainerTabDelegate(this));
|
|
130
|
-
|
|
131
|
-
this.tabbedPane.setCloseableTabs(true);
|
|
132
|
-
this.tabbedPane.setAllowTabReorder(true, true);
|
|
133
|
-
|
|
134
|
-
this.tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, this.tabClosed, this);
|
|
135
|
-
this.tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this.tabSelected, this);
|
|
136
|
-
|
|
137
|
-
this.tabbedPane.headerElement().setAttribute(
|
|
138
|
-
'jslog',
|
|
139
|
-
`${VisualLogging.toolbar('top').track({keydown: 'ArrowUp|ArrowLeft|ArrowDown|ArrowRight|Enter|Space'})}`);
|
|
140
|
-
|
|
141
|
-
Persistence.Persistence.PersistenceImpl.instance().addEventListener(
|
|
142
|
-
Persistence.Persistence.Events.BindingCreated, this.onBindingCreated, this);
|
|
143
|
-
Persistence.Persistence.PersistenceImpl.instance().addEventListener(
|
|
144
|
-
Persistence.Persistence.Events.BindingRemoved, this.onBindingRemoved, this);
|
|
145
|
-
Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().addEventListener(
|
|
146
|
-
Persistence.NetworkPersistenceManager.Events.REQUEST_FOR_HEADER_OVERRIDES_FILE_CHANGED,
|
|
147
|
-
this.#onRequestsForHeaderOverridesFileChanged, this);
|
|
465
|
+
this.#view = view;
|
|
466
|
+
this.#tabDelegate = new EditorContainerTabDelegate(this);
|
|
148
467
|
|
|
149
468
|
this.tabIds = new Map();
|
|
150
469
|
this.files = new Map();
|
|
151
|
-
|
|
152
470
|
this.uriToUISourceCode = new Map();
|
|
153
471
|
this.idToUISourceCode = new Map();
|
|
154
472
|
this.reentrantShow = false;
|
|
473
|
+
|
|
474
|
+
this.performUpdate();
|
|
475
|
+
|
|
476
|
+
Persistence.Persistence.PersistenceImpl.instance().addEventListener(Persistence.Persistence.Events.BindingCreated,
|
|
477
|
+
this.onBindingCreated, this);
|
|
478
|
+
Persistence.Persistence.PersistenceImpl.instance().addEventListener(Persistence.Persistence.Events.BindingRemoved,
|
|
479
|
+
this.onBindingRemoved, this);
|
|
480
|
+
Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().addEventListener(
|
|
481
|
+
Persistence.NetworkPersistenceManager.Events.REQUEST_FOR_HEADER_OVERRIDES_FILE_CHANGED,
|
|
482
|
+
this.#onRequestsForHeaderOverridesFileChanged, this);
|
|
483
|
+
}
|
|
484
|
+
#tabsHistory: string[] = [];
|
|
485
|
+
#appendHistory(tabId: string): void {
|
|
486
|
+
this.#tabsHistory.unshift(tabId);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
get #tabbedPane(): UI.TabbedPane.TabbedPaneElement|null {
|
|
490
|
+
return this.contentElement.querySelector('devtools-tabbed-pane');
|
|
155
491
|
}
|
|
156
492
|
|
|
157
|
-
get
|
|
158
|
-
return this.
|
|
493
|
+
get tabbedPane(): UI.TabbedPane.TabbedPaneElement {
|
|
494
|
+
return this.#tabbedPane as UI.TabbedPane.TabbedPaneElement;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
get tabbedPaneForTesting(): UI.TabbedPane.TabbedPaneElement {
|
|
498
|
+
return this.#tabbedPane as UI.TabbedPane.TabbedPaneElement;
|
|
159
499
|
}
|
|
160
500
|
|
|
161
501
|
private onBindingCreated(event: Common.EventTarget.EventTargetEvent<Persistence.Persistence.PersistenceBinding>):
|
|
@@ -177,21 +517,24 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
177
517
|
}
|
|
178
518
|
|
|
179
519
|
if (!fileSystemTabId) {
|
|
180
|
-
const networkView = this.
|
|
181
|
-
const tabIndex = this.
|
|
520
|
+
const networkView: UI.Widget.Widget|null = this.viewForFile(binding.network);
|
|
521
|
+
const tabIndex = Array.from(this.files.keys()).indexOf(networkTabId);
|
|
182
522
|
if (networkView instanceof UISourceCodeFrame) {
|
|
183
523
|
this.recycleUISourceCodeFrame(networkView, binding.fileSystem);
|
|
184
|
-
fileSystemTabId = this.appendFileTab(binding.fileSystem,
|
|
524
|
+
fileSystemTabId = this.appendFileTab(binding.fileSystem, tabIndex, true);
|
|
185
525
|
} else {
|
|
186
|
-
fileSystemTabId = this.appendFileTab(binding.fileSystem,
|
|
187
|
-
const fileSystemTabView =
|
|
188
|
-
|
|
526
|
+
fileSystemTabId = this.appendFileTab(binding.fileSystem, tabIndex);
|
|
527
|
+
const fileSystemTabView = this.viewForFile(binding.fileSystem);
|
|
528
|
+
if (fileSystemTabView) {
|
|
529
|
+
this.restoreEditorProperties(fileSystemTabView, currentSelectionRange, currentScrollLineNumber);
|
|
530
|
+
}
|
|
189
531
|
}
|
|
190
532
|
}
|
|
191
533
|
|
|
192
534
|
this.closeTabs([networkTabId], true);
|
|
193
535
|
if (wasSelectedInNetwork) {
|
|
194
|
-
this.
|
|
536
|
+
this.#currentFile = this.files.get(fileSystemTabId) || null;
|
|
537
|
+
this.#scheduleUpdate();
|
|
195
538
|
}
|
|
196
539
|
|
|
197
540
|
this.updateHistory();
|
|
@@ -209,19 +552,11 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
209
552
|
}
|
|
210
553
|
|
|
211
554
|
get visibleView(): UI.Widget.Widget|null {
|
|
212
|
-
return this
|
|
555
|
+
return this.#currentFile ? getViewByUISourceCode(this.#currentFile) || null : null;
|
|
213
556
|
}
|
|
214
557
|
|
|
215
558
|
fileViews(): UI.Widget.Widget[] {
|
|
216
|
-
return this.
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
leftToolbar(): UI.Toolbar.Toolbar {
|
|
220
|
-
return this.tabbedPane.leftToolbar();
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
rightToolbar(): UI.Toolbar.Toolbar {
|
|
224
|
-
return this.tabbedPane.rightToolbar();
|
|
559
|
+
return Array.from(this.files.values()).map(getViewByUISourceCode).filter(Boolean) as UI.Widget.Widget[];
|
|
225
560
|
}
|
|
226
561
|
|
|
227
562
|
showFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
@@ -250,11 +585,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
250
585
|
}
|
|
251
586
|
|
|
252
587
|
closeAllFiles(): void {
|
|
253
|
-
this.closeTabs(this.
|
|
588
|
+
this.closeTabs(Array.from(this.files.keys()));
|
|
254
589
|
}
|
|
255
590
|
|
|
256
591
|
detachEditors(): void {
|
|
257
|
-
this.
|
|
592
|
+
for (const view of this.fileViews()) {
|
|
593
|
+
view.detach();
|
|
594
|
+
}
|
|
258
595
|
}
|
|
259
596
|
|
|
260
597
|
historyUISourceCodes(): Workspace.UISourceCode.UISourceCode[] {
|
|
@@ -269,11 +606,37 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
269
606
|
}
|
|
270
607
|
|
|
271
608
|
selectNextTab(): void {
|
|
272
|
-
this.
|
|
609
|
+
const tabIds = Array.from(this.files.keys());
|
|
610
|
+
if (tabIds.length === 0 || !this.#currentFile) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const currentTabId = this.tabIds.get(this.#currentFile);
|
|
614
|
+
if (!currentTabId) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const index = tabIds.indexOf(currentTabId);
|
|
618
|
+
const nextIndex = (index + 1) % tabIds.length;
|
|
619
|
+
const nextFile = this.files.get(tabIds[nextIndex]);
|
|
620
|
+
if (nextFile) {
|
|
621
|
+
this.#showFile(nextFile, false);
|
|
622
|
+
}
|
|
273
623
|
}
|
|
274
624
|
|
|
275
625
|
selectPrevTab(): void {
|
|
276
|
-
this.
|
|
626
|
+
const tabIds = Array.from(this.files.keys());
|
|
627
|
+
if (tabIds.length === 0 || !this.#currentFile) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const currentTabId = this.tabIds.get(this.#currentFile);
|
|
631
|
+
if (!currentTabId) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const index = tabIds.indexOf(currentTabId);
|
|
635
|
+
const prevIndex = (index - 1 + tabIds.length) % tabIds.length;
|
|
636
|
+
const prevFile = this.files.get(tabIds[prevIndex]);
|
|
637
|
+
if (prevFile) {
|
|
638
|
+
this.#showFile(prevFile, false);
|
|
639
|
+
}
|
|
277
640
|
}
|
|
278
641
|
|
|
279
642
|
private addViewListeners(): void {
|
|
@@ -311,8 +674,8 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
311
674
|
if (update.docChanged || update.selectionSet) {
|
|
312
675
|
const {main} = update.state.selection;
|
|
313
676
|
const lineFrom = update.state.doc.lineAt(main.from), lineTo = update.state.doc.lineAt(main.to);
|
|
314
|
-
const range = new TextUtils.TextRange.TextRange(
|
|
315
|
-
|
|
677
|
+
const range = new TextUtils.TextRange.TextRange(lineFrom.number - 1, main.from - lineFrom.from, lineTo.number - 1,
|
|
678
|
+
main.to - lineTo.from);
|
|
316
679
|
if (this.#currentFile) {
|
|
317
680
|
this.history.updateSelectionRange(historyItemKey(this.#currentFile), range);
|
|
318
681
|
}
|
|
@@ -342,9 +705,12 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
342
705
|
// Selecting the tab may cause showFile to be called again, but with the canonical source code,
|
|
343
706
|
// which is not what we want, so we prevent reentrant calls.
|
|
344
707
|
this.reentrantShow = true;
|
|
345
|
-
const tabId = this.tabIds.get(canonicalSourceCode) || this.appendFileTab(canonicalSourceCode
|
|
708
|
+
const tabId = this.tabIds.get(canonicalSourceCode) || this.appendFileTab(canonicalSourceCode);
|
|
709
|
+
this.#appendHistory(tabId);
|
|
346
710
|
|
|
347
|
-
this
|
|
711
|
+
this.#scheduleUpdate();
|
|
712
|
+
// Force TabbedPaneElement to sync its tabs synchronously to avoid layout races in E2E tests.
|
|
713
|
+
this.#tabbedPane?.tabs;
|
|
348
714
|
} finally {
|
|
349
715
|
this.reentrantShow = false;
|
|
350
716
|
}
|
|
@@ -354,6 +720,9 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
354
720
|
}
|
|
355
721
|
|
|
356
722
|
const previousView = this.currentView;
|
|
723
|
+
if (uiSourceCode) {
|
|
724
|
+
this.getOrCreateSourceView(uiSourceCode);
|
|
725
|
+
}
|
|
357
726
|
this.currentView = this.visibleView;
|
|
358
727
|
this.addViewListeners();
|
|
359
728
|
|
|
@@ -375,6 +744,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
375
744
|
userGesture,
|
|
376
745
|
};
|
|
377
746
|
this.dispatchEventToListeners(Events.EDITOR_SELECTED, eventData);
|
|
747
|
+
this.onEditorSelected?.(eventData);
|
|
378
748
|
}
|
|
379
749
|
|
|
380
750
|
private titleForFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): string {
|
|
@@ -396,9 +766,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
396
766
|
if (!shouldPrompt || confirm(i18nString(UIStrings.areYouSureYouWantToCloseUnsaved, {PH1: uiSourceCode.name()}))) {
|
|
397
767
|
uiSourceCode.resetWorkingCopy();
|
|
398
768
|
if (nextTabId) {
|
|
399
|
-
this.
|
|
769
|
+
const nextFile = this.files.get(nextTabId);
|
|
770
|
+
if (nextFile) {
|
|
771
|
+
this.#showFile(nextFile, false);
|
|
772
|
+
}
|
|
400
773
|
}
|
|
401
|
-
this.
|
|
774
|
+
this.tabClosed(id, true);
|
|
775
|
+
this.#scheduleUpdate();
|
|
402
776
|
return true;
|
|
403
777
|
}
|
|
404
778
|
return false;
|
|
@@ -419,9 +793,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
419
793
|
}
|
|
420
794
|
}
|
|
421
795
|
if (dirtyTabs.length) {
|
|
422
|
-
this.
|
|
796
|
+
const dirtyFile = this.files.get(dirtyTabs[0]);
|
|
797
|
+
if (dirtyFile) {
|
|
798
|
+
this.#showFile(dirtyFile, false);
|
|
799
|
+
}
|
|
423
800
|
}
|
|
424
|
-
this.
|
|
801
|
+
cleanTabs.forEach(id => this.tabClosed(id, true));
|
|
802
|
+
this.#scheduleUpdate();
|
|
425
803
|
for (let i = 0; i < dirtyTabs.length; ++i) {
|
|
426
804
|
const nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
|
|
427
805
|
if (!this.maybeCloseTab(dirtyTabs[i], nextTabId)) {
|
|
@@ -470,7 +848,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
470
848
|
}
|
|
471
849
|
|
|
472
850
|
if (!this.tabIds.has(uiSourceCode)) {
|
|
473
|
-
this.appendFileTab(uiSourceCode
|
|
851
|
+
this.appendFileTab(uiSourceCode);
|
|
474
852
|
}
|
|
475
853
|
|
|
476
854
|
// Select tab if this file was the last to be shown.
|
|
@@ -500,16 +878,22 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
500
878
|
const tabId = this.tabIds.get(uiSourceCode);
|
|
501
879
|
if (tabId) {
|
|
502
880
|
tabIds.push(tabId);
|
|
881
|
+
} else {
|
|
882
|
+
this.removeSourceFrame(uiSourceCode);
|
|
503
883
|
}
|
|
504
|
-
|
|
505
|
-
|
|
884
|
+
for (const [k, v] of this.uriToUISourceCode) {
|
|
885
|
+
if (v === uiSourceCode) {
|
|
886
|
+
this.uriToUISourceCode.delete(k);
|
|
887
|
+
}
|
|
506
888
|
}
|
|
507
|
-
|
|
508
|
-
|
|
889
|
+
for (const [k, v] of this.idToUISourceCode) {
|
|
890
|
+
if (v === uiSourceCode) {
|
|
891
|
+
this.idToUISourceCode.delete(k);
|
|
892
|
+
}
|
|
509
893
|
}
|
|
510
|
-
this.removeSourceFrame(uiSourceCode);
|
|
511
894
|
}
|
|
512
|
-
this.
|
|
895
|
+
tabIds.forEach(id => this.tabClosed(id, false));
|
|
896
|
+
this.#scheduleUpdate();
|
|
513
897
|
}
|
|
514
898
|
|
|
515
899
|
private editorClosedByUserAction(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
@@ -523,7 +907,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
523
907
|
|
|
524
908
|
private updateHistory(): void {
|
|
525
909
|
const historyItemKeys = [];
|
|
526
|
-
for (const tabId of this.
|
|
910
|
+
for (const tabId of this.#tabsHistory.slice(0, MAX_PREVIOUSLY_VIEWED_FILES_COUNT)) {
|
|
527
911
|
const uiSourceCode = this.files.get(tabId);
|
|
528
912
|
if (uiSourceCode !== undefined) {
|
|
529
913
|
historyItemKeys.push(historyItemKey(uiSourceCode));
|
|
@@ -538,24 +922,27 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
538
922
|
return uiSourceCode.url();
|
|
539
923
|
}
|
|
540
924
|
|
|
541
|
-
private appendFileTab(
|
|
542
|
-
|
|
543
|
-
replaceView?: UI.Widget.Widget): string {
|
|
544
|
-
const view = replaceView || this.viewForFile(uiSourceCode);
|
|
545
|
-
const title = this.titleForFile(uiSourceCode);
|
|
546
|
-
const tooltip = this.tooltipForFile(uiSourceCode);
|
|
547
|
-
|
|
925
|
+
private appendFileTab(uiSourceCode: Workspace.UISourceCode.UISourceCode, index?: number,
|
|
926
|
+
ignoreHistory?: boolean): string {
|
|
548
927
|
const tabId = this.generateTabId();
|
|
549
928
|
this.tabIds.set(uiSourceCode, tabId);
|
|
550
|
-
this.files.set(tabId, uiSourceCode);
|
|
551
929
|
|
|
552
|
-
if (
|
|
553
|
-
const
|
|
554
|
-
|
|
930
|
+
if (index !== undefined) {
|
|
931
|
+
const entries = Array.from(this.files.entries());
|
|
932
|
+
entries.splice(index, 0, [tabId, uiSourceCode]);
|
|
933
|
+
this.files = new Map(entries);
|
|
934
|
+
} else {
|
|
935
|
+
this.files.set(tabId, uiSourceCode);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
const savedSelectionRange = this.history.selectionRange(historyItemKey(uiSourceCode));
|
|
939
|
+
const savedScrollLineNumber = this.history.scrollLineNumber(historyItemKey(uiSourceCode));
|
|
940
|
+
const view = this.viewForFile(uiSourceCode);
|
|
941
|
+
if (view && !ignoreHistory) {
|
|
555
942
|
this.restoreEditorProperties(view, savedSelectionRange, savedScrollLineNumber);
|
|
556
943
|
}
|
|
557
944
|
|
|
558
|
-
this
|
|
945
|
+
this.#scheduleUpdate();
|
|
559
946
|
|
|
560
947
|
this.updateFileTitle(uiSourceCode);
|
|
561
948
|
this.addUISourceCodeListeners(uiSourceCode);
|
|
@@ -568,22 +955,23 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
568
955
|
}
|
|
569
956
|
});
|
|
570
957
|
}
|
|
958
|
+
|
|
959
|
+
if (!this.#currentFile) {
|
|
960
|
+
this.#showFile(uiSourceCode, false);
|
|
961
|
+
}
|
|
571
962
|
return tabId;
|
|
572
963
|
}
|
|
573
964
|
|
|
574
965
|
private addLoadErrorIcon(tabId: string): void {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
// clang-format on
|
|
580
|
-
if (this.tabbedPane.tabView(tabId)) {
|
|
581
|
-
this.tabbedPane.setTrailingTabIcon(tabId, icon);
|
|
966
|
+
const uiSourceCode = this.files.get(tabId);
|
|
967
|
+
if (uiSourceCode) {
|
|
968
|
+
this.#loadErrorFiles.add(uiSourceCode);
|
|
969
|
+
this.#scheduleUpdate();
|
|
582
970
|
}
|
|
583
971
|
}
|
|
584
972
|
|
|
585
|
-
private restoreEditorProperties(
|
|
586
|
-
|
|
973
|
+
private restoreEditorProperties(editorView: UI.Widget.Widget, selection?: TextUtils.TextRange.TextRange,
|
|
974
|
+
firstLineNumber?: number): void {
|
|
587
975
|
const sourceFrame = editorView instanceof SourceFrame.SourceFrame.SourceFrameImpl ? editorView : null;
|
|
588
976
|
if (!sourceFrame) {
|
|
589
977
|
return;
|
|
@@ -596,8 +984,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
596
984
|
}
|
|
597
985
|
}
|
|
598
986
|
|
|
599
|
-
private tabClosed(
|
|
600
|
-
const {tabId, isUserGesture} = event.data;
|
|
987
|
+
private tabClosed(tabId: string, isUserGesture?: boolean): void {
|
|
601
988
|
const uiSourceCode = this.files.get(tabId);
|
|
602
989
|
if (this.#currentFile && this.#currentFile.canonicalScriptId() === uiSourceCode?.canonicalScriptId()) {
|
|
603
990
|
this.removeViewListeners();
|
|
@@ -606,6 +993,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
606
993
|
}
|
|
607
994
|
if (uiSourceCode) {
|
|
608
995
|
this.tabIds.delete(uiSourceCode);
|
|
996
|
+
this.#loadErrorFiles.delete(uiSourceCode);
|
|
609
997
|
}
|
|
610
998
|
this.files.delete(tabId);
|
|
611
999
|
|
|
@@ -614,6 +1002,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
614
1002
|
this.removeSourceFrame(uiSourceCode);
|
|
615
1003
|
|
|
616
1004
|
this.dispatchEventToListeners(Events.EDITOR_CLOSED, uiSourceCode);
|
|
1005
|
+
this.onEditorClosed?.(uiSourceCode);
|
|
617
1006
|
|
|
618
1007
|
if (isUserGesture) {
|
|
619
1008
|
this.editorClosedByUserAction(uiSourceCode);
|
|
@@ -621,9 +1010,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
621
1010
|
}
|
|
622
1011
|
}
|
|
623
1012
|
|
|
624
|
-
private tabSelected(
|
|
625
|
-
const {tabId, isUserGesture} = event.data;
|
|
626
|
-
|
|
1013
|
+
private tabSelected(tabId: string, isUserGesture?: boolean): void {
|
|
627
1014
|
const uiSourceCode = this.files.get(tabId);
|
|
628
1015
|
if (uiSourceCode) {
|
|
629
1016
|
this.#showFile(uiSourceCode, isUserGesture);
|
|
@@ -632,70 +1019,26 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
632
1019
|
|
|
633
1020
|
private addUISourceCodeListeners(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
634
1021
|
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
635
|
-
uiSourceCode.addEventListener(
|
|
636
|
-
|
|
637
|
-
uiSourceCode.addEventListener(
|
|
638
|
-
|
|
1022
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged, this.uiSourceCodeWorkingCopyChanged,
|
|
1023
|
+
this);
|
|
1024
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
|
|
1025
|
+
this.uiSourceCodeWorkingCopyCommitted, this);
|
|
639
1026
|
}
|
|
640
1027
|
|
|
641
1028
|
private removeUISourceCodeListeners(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
642
1029
|
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
643
|
-
uiSourceCode.removeEventListener(
|
|
644
|
-
|
|
645
|
-
uiSourceCode.removeEventListener(
|
|
646
|
-
|
|
1030
|
+
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged,
|
|
1031
|
+
this.uiSourceCodeWorkingCopyChanged, this);
|
|
1032
|
+
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
|
|
1033
|
+
this.uiSourceCodeWorkingCopyCommitted, this);
|
|
647
1034
|
}
|
|
648
1035
|
|
|
649
1036
|
private updateFileTitle(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const tooltip = this.tooltipForFile(uiSourceCode);
|
|
654
|
-
this.tabbedPane.changeTabTitle(tabId, title, tooltip);
|
|
655
|
-
if (uiSourceCode.loadError()) {
|
|
656
|
-
// clang-format off
|
|
657
|
-
const icon = html`<devtools-icon class="small" name="cross-circle-filled"
|
|
658
|
-
title=${i18nString(UIStrings.unableToLoadThisContent)}>
|
|
659
|
-
</devtools-icon>`;
|
|
660
|
-
// clang-format on
|
|
661
|
-
this.tabbedPane.setTrailingTabIcon(tabId, icon);
|
|
662
|
-
} else if (Persistence.Persistence.PersistenceImpl.instance().hasUnsavedCommittedChanges(uiSourceCode)) {
|
|
663
|
-
/* eslint-disable @devtools/no-imperative-dom-api --
|
|
664
|
-
* This is a temporary solution using the <devtools-tooltip>
|
|
665
|
-
* and we will use a toast instead once available.
|
|
666
|
-
**/
|
|
667
|
-
const suffixElement = document.createElement('div');
|
|
668
|
-
const icon = new Icon();
|
|
669
|
-
icon.name = 'warning-filled';
|
|
670
|
-
icon.classList.add('small');
|
|
671
|
-
const id = `tab-tooltip-${nextTooltipId++}`;
|
|
672
|
-
icon.setAttribute('aria-describedby', id);
|
|
673
|
-
const tooltip = new Tooltips.Tooltip.Tooltip({id, anchor: icon, variant: 'rich'});
|
|
674
|
-
const automaticFileSystemManager = Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.instance();
|
|
675
|
-
const {automaticFileSystem} = automaticFileSystemManager;
|
|
676
|
-
if (automaticFileSystem?.state === 'disconnected') {
|
|
677
|
-
const link = document.createElement('a');
|
|
678
|
-
link.className = 'devtools-link';
|
|
679
|
-
link.textContent = Common.ParsedURL.ParsedURL.extractName(automaticFileSystem.root);
|
|
680
|
-
link.addEventListener('click', async event => {
|
|
681
|
-
event.consume();
|
|
682
|
-
await UI.ViewManager.ViewManager.instance().showView('navigator-files');
|
|
683
|
-
await automaticFileSystemManager.connectAutomaticFileSystem(/* addIfMissing= */ true);
|
|
684
|
-
});
|
|
685
|
-
tooltip.append(uiI18n.getFormatLocalizedString(
|
|
686
|
-
str_, UIStrings.changesWereNotSavedToFileSystemToSaveAddFolderToWorkspace, {PH1: link}));
|
|
687
|
-
} else {
|
|
688
|
-
const link = Link.create('https://developer.chrome.com/docs/devtools/workspaces/', 'Workspace');
|
|
689
|
-
tooltip.append(uiI18n.getFormatLocalizedString(
|
|
690
|
-
str_, UIStrings.changesWereNotSavedToFileSystemToSaveSetUpYourWorkspace, {PH1: link}));
|
|
691
|
-
}
|
|
692
|
-
suffixElement.append(icon, tooltip);
|
|
693
|
-
/* eslint-enable @devtools/no-imperative-dom-api */
|
|
694
|
-
this.tabbedPane.setSuffixElement(tabId, suffixElement);
|
|
695
|
-
} else {
|
|
696
|
-
const icon = PanelCommon.PersistenceUtils.PersistenceUtils.iconForUISourceCode(uiSourceCode);
|
|
697
|
-
this.tabbedPane.setTrailingTabIcon(tabId, icon);
|
|
1037
|
+
if (this.tabIds.has(uiSourceCode)) {
|
|
1038
|
+
if (!uiSourceCode.loadError()) {
|
|
1039
|
+
this.#loadErrorFiles.delete(uiSourceCode);
|
|
698
1040
|
}
|
|
1041
|
+
this.#scheduleUpdate();
|
|
699
1042
|
}
|
|
700
1043
|
}
|
|
701
1044
|
|
|
@@ -703,7 +1046,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
703
1046
|
void {
|
|
704
1047
|
const uiSourceCode = event.data;
|
|
705
1048
|
|
|
706
|
-
const widget =
|
|
1049
|
+
const widget = getViewByUISourceCode(uiSourceCode);
|
|
707
1050
|
if (widget) {
|
|
708
1051
|
if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForUISourceCode(uiSourceCode)) {
|
|
709
1052
|
// Remove the existing editor tab and create a new one of the correct type.
|
|
@@ -749,60 +1092,6 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
749
1092
|
return 'tab-' + (tabId++) as Lowercase<string>;
|
|
750
1093
|
}
|
|
751
1094
|
|
|
752
|
-
#renderPlaceholder(placeholderElement: HTMLElement): void {
|
|
753
|
-
const shortcuts = [
|
|
754
|
-
{actionId: 'quick-open.show', description: i18nString(UIStrings.openFile)},
|
|
755
|
-
{actionId: 'quick-open.show-command-menu', description: i18nString(UIStrings.runCommand)},
|
|
756
|
-
];
|
|
757
|
-
const separator = Host.Platform.isMac() ? '\u2004' : ' + ';
|
|
758
|
-
const shortcutElements = shortcuts.map(shortcut => {
|
|
759
|
-
const shortcutKeys = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(shortcut.actionId);
|
|
760
|
-
if (!shortcutKeys?.[0]) {
|
|
761
|
-
return {
|
|
762
|
-
description: shortcut.description,
|
|
763
|
-
onClick: () => {},
|
|
764
|
-
keys: [],
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
const action = UI.ActionRegistry.ActionRegistry.instance().getAction(shortcut.actionId);
|
|
768
|
-
const keys = shortcutKeys[0].descriptors.flatMap(descriptor => descriptor.name.split(separator));
|
|
769
|
-
return {
|
|
770
|
-
description: shortcut.description,
|
|
771
|
-
onClick: () => {
|
|
772
|
-
void action.execute();
|
|
773
|
-
},
|
|
774
|
-
keys,
|
|
775
|
-
};
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
// clang-format off
|
|
779
|
-
// eslint-disable-next-line @devtools/no-lit-render-outside-of-view
|
|
780
|
-
render(html`
|
|
781
|
-
<div class="tabbed-pane-placeholder-row workspace">
|
|
782
|
-
<span class="icon-container">
|
|
783
|
-
<devtools-icon name="sync" class="sync-icon"></devtools-icon>
|
|
784
|
-
</span>
|
|
785
|
-
<span>
|
|
786
|
-
${i18nString(UIStrings.workspaceDropInAFolderToSyncSources)}
|
|
787
|
-
<button @click=${this.#addFileSystemClicked.bind(this)}>${i18nString(UIStrings.selectFolder)}</button>
|
|
788
|
-
</span>
|
|
789
|
-
</div>
|
|
790
|
-
<div class="shortcuts-list tabbed-pane-placeholder-row" role="list"
|
|
791
|
-
aria-label=${i18nString(UIStrings.sourceViewActions)}>
|
|
792
|
-
${shortcutElements.map(shortcut => !shortcut.keys.length
|
|
793
|
-
? html`<div class="shortcut-line" role="listitem"></div>`
|
|
794
|
-
: html`<div class="shortcut-line" role="listitem">
|
|
795
|
-
<button @click=${shortcut.onClick}>${shortcut.description}</button>
|
|
796
|
-
<span class="shortcuts">
|
|
797
|
-
${shortcut.keys.map(key => html`
|
|
798
|
-
<span class="keybinds-key"><span>${key}</span></span>
|
|
799
|
-
`)}
|
|
800
|
-
</span>
|
|
801
|
-
</div>`)}
|
|
802
|
-
</div>`, placeholderElement);
|
|
803
|
-
// clang-format on
|
|
804
|
-
}
|
|
805
|
-
|
|
806
1095
|
async #addFileSystemClicked(): Promise<void> {
|
|
807
1096
|
const result = await Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.instance().addFileSystem();
|
|
808
1097
|
if (!result) {
|
|
@@ -813,49 +1102,35 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
813
1102
|
}
|
|
814
1103
|
|
|
815
1104
|
getCreatedSourceView(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget|undefined {
|
|
816
|
-
return
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
viewForFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget {
|
|
820
|
-
return this.getOrCreateSourceView(uiSourceCode);
|
|
1105
|
+
return getViewByUISourceCode(uiSourceCode);
|
|
821
1106
|
}
|
|
822
1107
|
|
|
823
1108
|
private getOrCreateSourceView(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
private createSourceView(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget {
|
|
828
|
-
let sourceView;
|
|
829
|
-
const contentType = uiSourceCode.contentType();
|
|
830
|
-
|
|
831
|
-
if (contentType === Common.ResourceType.resourceTypes.Image || uiSourceCode.mimeType().startsWith('image/')) {
|
|
832
|
-
sourceView = new SourceFrame.ImageView.ImageView(uiSourceCode.mimeType(), uiSourceCode);
|
|
833
|
-
} else if (contentType === Common.ResourceType.resourceTypes.Font || uiSourceCode.mimeType().includes('font')) {
|
|
834
|
-
sourceView = new SourceFrame.FontView.FontView(uiSourceCode.mimeType(), uiSourceCode);
|
|
835
|
-
} else if (uiSourceCode.name() === HEADER_OVERRIDES_FILENAME) {
|
|
836
|
-
sourceView = new Components.HeadersView.HeadersView(uiSourceCode);
|
|
837
|
-
} else {
|
|
838
|
-
sourceView = new UISourceCodeFrame(uiSourceCode);
|
|
839
|
-
this.#historyManager.trackSourceFrameCursorJumps(sourceView);
|
|
1109
|
+
const view = getViewByUISourceCode(uiSourceCode);
|
|
1110
|
+
if (view) {
|
|
1111
|
+
return view;
|
|
840
1112
|
}
|
|
1113
|
+
return getOrCreateSourceView(uiSourceCode, sourceView => {
|
|
1114
|
+
if (sourceView instanceof UISourceCodeFrame) {
|
|
1115
|
+
this.#historyManager.trackSourceFrameCursorJumps(sourceView);
|
|
1116
|
+
}
|
|
1117
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
841
1120
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
return sourceView;
|
|
1121
|
+
viewForFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget {
|
|
1122
|
+
return this.getOrCreateSourceView(uiSourceCode);
|
|
845
1123
|
}
|
|
846
1124
|
|
|
847
1125
|
recycleUISourceCodeFrame(sourceFrame: UISourceCodeFrame, uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
848
1126
|
sourceFrame.uiSourceCode().removeEventListener(Workspace.UISourceCode.Events.TitleChanged,
|
|
849
1127
|
this.uiSourceCodeTitleChanged, this);
|
|
850
|
-
|
|
851
|
-
sourceFrame.setUISourceCode(uiSourceCode);
|
|
852
|
-
this.sourceViewByUISourceCode.set(uiSourceCode, sourceFrame);
|
|
1128
|
+
recycleUISourceCodeFrame(sourceFrame, uiSourceCode);
|
|
853
1129
|
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
854
1130
|
}
|
|
855
1131
|
|
|
856
1132
|
private removeSourceFrame(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
857
|
-
const sourceView =
|
|
858
|
-
this.sourceViewByUISourceCode.delete(uiSourceCode);
|
|
1133
|
+
const sourceView = removeSourceViewCache(uiSourceCode);
|
|
859
1134
|
if (sourceView) {
|
|
860
1135
|
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
861
1136
|
}
|
|
@@ -897,8 +1172,6 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
897
1172
|
}
|
|
898
1173
|
}
|
|
899
1174
|
|
|
900
|
-
let nextTooltipId = 1;
|
|
901
|
-
|
|
902
1175
|
export const enum Events {
|
|
903
1176
|
EDITOR_SELECTED = 'EditorSelected',
|
|
904
1177
|
EDITOR_CLOSED = 'EditorClosed',
|
|
@@ -941,9 +1214,8 @@ export class HistoryItem implements HistoryItemKey {
|
|
|
941
1214
|
selectionRange: TextUtils.TextRange.TextRange|undefined;
|
|
942
1215
|
scrollLineNumber: number|undefined;
|
|
943
1216
|
|
|
944
|
-
constructor(
|
|
945
|
-
|
|
946
|
-
selectionRange?: TextUtils.TextRange.TextRange, scrollLineNumber?: number) {
|
|
1217
|
+
constructor(url: Platform.DevToolsPath.UrlString, resourceType: Common.ResourceType.ResourceType,
|
|
1218
|
+
selectionRange?: TextUtils.TextRange.TextRange, scrollLineNumber?: number) {
|
|
947
1219
|
this.url = url;
|
|
948
1220
|
this.resourceType = resourceType;
|
|
949
1221
|
this.selectionRange = selectionRange;
|