chrome-devtools-frontend 1.0.1701636 → 1.0.1702515
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/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/devtools_compatibility.js +2 -1
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -3
- package/front_end/generated/protocol.ts +0 -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/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 +14 -5
- 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/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/commentThreadWidget.css +11 -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/sources/ResourceOriginPlugin.ts +8 -3
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -4
- package/front_end/panels/sources/TabbedEditorContainer.ts +339 -126
- 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 +117 -0
- package/front_end/ui/components/markdown_view/markdown_view.ts +2 -0
- 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 +228 -343
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -27
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ import * as uiI18n from '../../ui/i18n/i18n.js';
|
|
|
15
15
|
import {Icon, Link} from '../../ui/kit/kit.js';
|
|
16
16
|
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
|
17
17
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
18
|
-
import {html, render} from '../../ui/lit/lit.js';
|
|
18
|
+
import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
19
19
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
20
20
|
import * as PanelCommon from '../common/common.js';
|
|
21
21
|
import * as Snippets from '../snippets/snippets.js';
|
|
@@ -75,6 +75,8 @@ const UIStrings = {
|
|
|
75
75
|
} as const;
|
|
76
76
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/TabbedEditorContainer.ts', UIStrings);
|
|
77
77
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
78
|
+
const {repeat} = Directives;
|
|
79
|
+
const {widget} = UI.Widget;
|
|
78
80
|
|
|
79
81
|
const enum SourceViewType {
|
|
80
82
|
IMAGE_VIEW = 'ImageView',
|
|
@@ -84,6 +86,95 @@ const enum SourceViewType {
|
|
|
84
86
|
}
|
|
85
87
|
const HEADER_OVERRIDES_FILENAME = '.headers';
|
|
86
88
|
|
|
89
|
+
export interface TabbedEditorViewInput {
|
|
90
|
+
openTabs: Array<{
|
|
91
|
+
tabId: string,
|
|
92
|
+
title: string,
|
|
93
|
+
tooltip: string,
|
|
94
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode,
|
|
95
|
+
isCloseable: boolean,
|
|
96
|
+
widget?: UI.Widget.Widget,
|
|
97
|
+
icon?: TemplateResult|HTMLElement,
|
|
98
|
+
suffix?: HTMLElement,
|
|
99
|
+
}>;
|
|
100
|
+
activeTabId?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface TabbedEditorViewOutput {
|
|
104
|
+
onClose(e: Event): void;
|
|
105
|
+
onTabOrderChanged(e: Event): void;
|
|
106
|
+
onSelect(e: Event): void;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type View = (input: TabbedEditorViewInput, output: TabbedEditorViewOutput, target: HTMLElement) => void;
|
|
110
|
+
|
|
111
|
+
const UI_SOURCE_CODE_WIDGET_MAP = new WeakMap<Workspace.UISourceCode.UISourceCode, UI.Widget.Widget>();
|
|
112
|
+
|
|
113
|
+
function getOrCreateSourceView(uiSourceCode: Workspace.UISourceCode.UISourceCode,
|
|
114
|
+
onCreate: (view: UI.Widget.Widget) => void): UI.Widget.Widget {
|
|
115
|
+
const existing = UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
116
|
+
if (existing) {
|
|
117
|
+
return existing;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let sourceView: UI.Widget.Widget;
|
|
121
|
+
const contentType = uiSourceCode.contentType();
|
|
122
|
+
if (contentType === Common.ResourceType.resourceTypes.Image || uiSourceCode.mimeType().startsWith('image/')) {
|
|
123
|
+
sourceView = new SourceFrame.ImageView.ImageView(uiSourceCode.mimeType(), uiSourceCode);
|
|
124
|
+
} else if (contentType === Common.ResourceType.resourceTypes.Font || uiSourceCode.mimeType().includes('font')) {
|
|
125
|
+
sourceView = new SourceFrame.FontView.FontView(uiSourceCode.mimeType(), uiSourceCode);
|
|
126
|
+
} else if (uiSourceCode.name() === Persistence.NetworkPersistenceManager.HEADERS_FILENAME) {
|
|
127
|
+
sourceView = new Components.HeadersView.HeadersView(uiSourceCode);
|
|
128
|
+
} else {
|
|
129
|
+
sourceView = new UISourceCodeFrame(uiSourceCode);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
UI_SOURCE_CODE_WIDGET_MAP.set(uiSourceCode, sourceView);
|
|
133
|
+
onCreate(sourceView);
|
|
134
|
+
return sourceView;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function recycleUISourceCodeFrame(sourceFrame: UISourceCodeFrame,
|
|
138
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
139
|
+
UI_SOURCE_CODE_WIDGET_MAP.delete(sourceFrame.uiSourceCode());
|
|
140
|
+
sourceFrame.setUISourceCode(uiSourceCode);
|
|
141
|
+
UI_SOURCE_CODE_WIDGET_MAP.set(uiSourceCode, sourceFrame);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getViewByUISourceCode(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget|undefined {
|
|
145
|
+
return UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function removeSourceViewCache(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget|undefined {
|
|
149
|
+
const view = UI_SOURCE_CODE_WIDGET_MAP.get(uiSourceCode);
|
|
150
|
+
if (view) {
|
|
151
|
+
UI_SOURCE_CODE_WIDGET_MAP.delete(uiSourceCode);
|
|
152
|
+
}
|
|
153
|
+
return view;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
157
|
+
// clang-format off
|
|
158
|
+
render(html`
|
|
159
|
+
<devtools-tabbed-pane
|
|
160
|
+
class="flex-auto vbox"
|
|
161
|
+
@close=${output.onClose}
|
|
162
|
+
@taborderchanged=${output.onTabOrderChanged}
|
|
163
|
+
@select=${output.onSelect}
|
|
164
|
+
>
|
|
165
|
+
${repeat(input.openTabs, tab => tab.tabId, tab => html`
|
|
166
|
+
<div id=${tab.tabId}
|
|
167
|
+
title=${tab.title}
|
|
168
|
+
?closeable=${tab.isCloseable}
|
|
169
|
+
?selected=${input.activeTabId === tab.tabId}
|
|
170
|
+
style="display: flex; flex: auto;">
|
|
171
|
+
${tab.icon ? html`<span slot="icon">${tab.icon}</span>` : nothing}
|
|
172
|
+
${tab.suffix ? html`<span slot="suffix">${tab.suffix}</span>` : nothing}
|
|
173
|
+
${tab.widget ? html`${widget(UI.Widget.WrapperWidget, {widget: tab.widget})}` : nothing}
|
|
174
|
+
</div>`)}
|
|
175
|
+
</devtools-tabbed-pane>`, target);
|
|
176
|
+
// clang-format on
|
|
177
|
+
};
|
|
87
178
|
let tabId = 0;
|
|
88
179
|
|
|
89
180
|
const TabbedEditorContainerBase: Common.ObjectWrapper.EventMixin<EventTypes, typeof UI.Widget.VBox> =
|
|
@@ -92,14 +183,70 @@ const TabbedEditorContainerBase: Common.ObjectWrapper.EventMixin<EventTypes, typ
|
|
|
92
183
|
);
|
|
93
184
|
|
|
94
185
|
export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
186
|
+
override focus(): void {
|
|
187
|
+
if (this.visibleView) {
|
|
188
|
+
this.visibleView.focus();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
#scheduleUpdate(): void {
|
|
193
|
+
this.#renderView();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#renderView(): void {
|
|
197
|
+
const input: TabbedEditorViewInput = {
|
|
198
|
+
openTabs: [...this.files.entries()].map(
|
|
199
|
+
([tabId, uiSourceCode]) => ({
|
|
200
|
+
tabId,
|
|
201
|
+
title: this.titleForFile(uiSourceCode),
|
|
202
|
+
tooltip: this.tooltipForFile(uiSourceCode),
|
|
203
|
+
uiSourceCode,
|
|
204
|
+
isCloseable: true,
|
|
205
|
+
icon: this.#tabIcons.get(uiSourceCode),
|
|
206
|
+
suffix: this.#tabSuffixes.get(uiSourceCode),
|
|
207
|
+
widget: (this.#currentFile === uiSourceCode) ? this.getOrCreateSourceView(uiSourceCode) :
|
|
208
|
+
this.getCreatedSourceView(uiSourceCode),
|
|
209
|
+
})),
|
|
210
|
+
activeTabId: this.#currentFile ? this.tabIds.get(this.#currentFile) : undefined,
|
|
211
|
+
};
|
|
212
|
+
const output: TabbedEditorViewOutput = {
|
|
213
|
+
onClose: (e: Event) => {
|
|
214
|
+
this.tabClosed((e as CustomEvent<{tabId: string}>).detail.tabId,
|
|
215
|
+
(e as CustomEvent<{isUserGesture?: boolean}>).detail.isUserGesture);
|
|
216
|
+
this.#scheduleUpdate();
|
|
217
|
+
},
|
|
218
|
+
onTabOrderChanged: (e: Event) => {
|
|
219
|
+
const tabIds = (e as CustomEvent<{tabIds: string[]}>).detail.tabIds;
|
|
220
|
+
const newFiles = new Map<string, Workspace.UISourceCode.UISourceCode>();
|
|
221
|
+
for (const id of tabIds) {
|
|
222
|
+
if (this.files.has(id)) {
|
|
223
|
+
const file = this.files.get(id);
|
|
224
|
+
if (file) {
|
|
225
|
+
newFiles.set(id, file);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
this.files = newFiles;
|
|
230
|
+
this.#scheduleUpdate();
|
|
231
|
+
},
|
|
232
|
+
onSelect: (e: Event) => {
|
|
233
|
+
this.tabSelected((e as CustomEvent<{tabId: string}>).detail.tabId,
|
|
234
|
+
(e as CustomEvent<{isUserGesture?: boolean}>).detail.isUserGesture);
|
|
235
|
+
this.#scheduleUpdate();
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
DEFAULT_VIEW(input, output, this.contentElement);
|
|
239
|
+
}
|
|
95
240
|
#historyManager!: EditingLocationHistoryManager;
|
|
96
241
|
set historyManager(historyManager: EditingLocationHistoryManager) {
|
|
97
242
|
this.#historyManager = historyManager;
|
|
98
243
|
}
|
|
99
|
-
|
|
100
|
-
private readonly tabbedPane: UI.TabbedPane.
|
|
244
|
+
|
|
245
|
+
private readonly tabbedPane: UI.TabbedPane.TabbedPaneElement;
|
|
101
246
|
private tabIds: Map<Workspace.UISourceCode.UISourceCode, string>;
|
|
102
|
-
private
|
|
247
|
+
private files: Map<string, Workspace.UISourceCode.UISourceCode>;
|
|
248
|
+
readonly #tabIcons = new Map<Workspace.UISourceCode.UISourceCode, TemplateResult|HTMLElement>();
|
|
249
|
+
readonly #tabSuffixes = new Map<Workspace.UISourceCode.UISourceCode, HTMLElement>();
|
|
103
250
|
#previouslyViewedFilesSetting!: Common.Settings.Setting<SerializedHistoryItem[]>;
|
|
104
251
|
history!: History;
|
|
105
252
|
set previouslyViewedFilesSetting(setting: Common.Settings.Setting<SerializedHistoryItem[]>) {
|
|
@@ -118,43 +265,46 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
118
265
|
constructor(element?: HTMLElement) {
|
|
119
266
|
super(element);
|
|
120
267
|
|
|
121
|
-
this.
|
|
122
|
-
|
|
123
|
-
this.
|
|
268
|
+
this.tabIds = new Map();
|
|
269
|
+
this.files = new Map();
|
|
270
|
+
this.uriToUISourceCode = new Map();
|
|
271
|
+
this.idToUISourceCode = new Map();
|
|
272
|
+
this.reentrantShow = false;
|
|
273
|
+
|
|
274
|
+
this.#renderView();
|
|
275
|
+
|
|
276
|
+
this.tabbedPane = this.contentElement.querySelector('devtools-tabbed-pane') as UI.TabbedPane.TabbedPaneElement;
|
|
277
|
+
|
|
124
278
|
// eslint-disable-next-line @devtools/no-imperative-dom-api
|
|
125
279
|
const placeholderElement = document.createElement('div');
|
|
126
280
|
placeholderElement.classList.add('sources-placeholder');
|
|
127
|
-
this.tabbedPane.
|
|
281
|
+
this.tabbedPane.placeholder = placeholderElement;
|
|
128
282
|
this.#renderPlaceholder(placeholderElement as HTMLElement);
|
|
129
|
-
this.tabbedPane.
|
|
130
|
-
|
|
131
|
-
this.tabbedPane.setCloseableTabs(true);
|
|
132
|
-
this.tabbedPane.setAllowTabReorder(true, true);
|
|
283
|
+
this.tabbedPane.tabDelegate = new EditorContainerTabDelegate(this);
|
|
133
284
|
|
|
134
|
-
this.tabbedPane.
|
|
135
|
-
this.tabbedPane.
|
|
285
|
+
this.tabbedPane.closeableTabs = true;
|
|
286
|
+
this.tabbedPane.allowTabReorder = true;
|
|
287
|
+
this.tabbedPane.automaticReorder = true;
|
|
136
288
|
|
|
137
|
-
this.tabbedPane
|
|
289
|
+
const widget = UI.Widget.Widget.getOrCreateWidget(this.tabbedPane) as UI.TabbedPane.TabbedPane;
|
|
290
|
+
widget.headerElement().setAttribute(
|
|
138
291
|
'jslog',
|
|
139
292
|
`${VisualLogging.toolbar('top').track({keydown: 'ArrowUp|ArrowLeft|ArrowDown|ArrowRight|Enter|Space'})}`);
|
|
140
293
|
|
|
141
|
-
Persistence.Persistence.PersistenceImpl.instance().addEventListener(
|
|
142
|
-
|
|
143
|
-
Persistence.Persistence.PersistenceImpl.instance().addEventListener(
|
|
144
|
-
|
|
294
|
+
Persistence.Persistence.PersistenceImpl.instance().addEventListener(Persistence.Persistence.Events.BindingCreated,
|
|
295
|
+
this.onBindingCreated, this);
|
|
296
|
+
Persistence.Persistence.PersistenceImpl.instance().addEventListener(Persistence.Persistence.Events.BindingRemoved,
|
|
297
|
+
this.onBindingRemoved, this);
|
|
145
298
|
Persistence.NetworkPersistenceManager.NetworkPersistenceManager.instance().addEventListener(
|
|
146
299
|
Persistence.NetworkPersistenceManager.Events.REQUEST_FOR_HEADER_OVERRIDES_FILE_CHANGED,
|
|
147
300
|
this.#onRequestsForHeaderOverridesFileChanged, this);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
this.uriToUISourceCode = new Map();
|
|
153
|
-
this.idToUISourceCode = new Map();
|
|
154
|
-
this.reentrantShow = false;
|
|
301
|
+
}
|
|
302
|
+
#tabsHistory: string[] = [];
|
|
303
|
+
#appendHistory(tabId: string): void {
|
|
304
|
+
this.#tabsHistory.unshift(tabId);
|
|
155
305
|
}
|
|
156
306
|
|
|
157
|
-
get tabbedPaneForTesting(): UI.TabbedPane.
|
|
307
|
+
get tabbedPaneForTesting(): UI.TabbedPane.TabbedPaneElement {
|
|
158
308
|
return this.tabbedPane;
|
|
159
309
|
}
|
|
160
310
|
|
|
@@ -177,21 +327,24 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
177
327
|
}
|
|
178
328
|
|
|
179
329
|
if (!fileSystemTabId) {
|
|
180
|
-
const networkView = this.
|
|
181
|
-
const tabIndex = this.
|
|
330
|
+
const networkView: UI.Widget.Widget|null = this.viewForFile(binding.network);
|
|
331
|
+
const tabIndex = Array.from(this.files.keys()).indexOf(networkTabId);
|
|
182
332
|
if (networkView instanceof UISourceCodeFrame) {
|
|
183
333
|
this.recycleUISourceCodeFrame(networkView, binding.fileSystem);
|
|
184
|
-
fileSystemTabId = this.appendFileTab(binding.fileSystem,
|
|
334
|
+
fileSystemTabId = this.appendFileTab(binding.fileSystem, tabIndex, true);
|
|
185
335
|
} else {
|
|
186
|
-
fileSystemTabId = this.appendFileTab(binding.fileSystem,
|
|
187
|
-
const fileSystemTabView =
|
|
188
|
-
|
|
336
|
+
fileSystemTabId = this.appendFileTab(binding.fileSystem, tabIndex);
|
|
337
|
+
const fileSystemTabView = this.viewForFile(binding.fileSystem);
|
|
338
|
+
if (fileSystemTabView) {
|
|
339
|
+
this.restoreEditorProperties(fileSystemTabView, currentSelectionRange, currentScrollLineNumber);
|
|
340
|
+
}
|
|
189
341
|
}
|
|
190
342
|
}
|
|
191
343
|
|
|
192
344
|
this.closeTabs([networkTabId], true);
|
|
193
345
|
if (wasSelectedInNetwork) {
|
|
194
|
-
this.
|
|
346
|
+
this.#currentFile = this.files.get(fileSystemTabId) || null;
|
|
347
|
+
this.#scheduleUpdate();
|
|
195
348
|
}
|
|
196
349
|
|
|
197
350
|
this.updateHistory();
|
|
@@ -209,19 +362,35 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
209
362
|
}
|
|
210
363
|
|
|
211
364
|
get visibleView(): UI.Widget.Widget|null {
|
|
212
|
-
return this
|
|
365
|
+
return this.#currentFile ? getViewByUISourceCode(this.#currentFile) || null : null;
|
|
213
366
|
}
|
|
214
367
|
|
|
215
368
|
fileViews(): UI.Widget.Widget[] {
|
|
216
|
-
return this.
|
|
369
|
+
return Array.from(this.files.values()).map(getViewByUISourceCode).filter(Boolean) as UI.Widget.Widget[];
|
|
217
370
|
}
|
|
218
371
|
|
|
372
|
+
#leftToolbar?: UI.Toolbar.Toolbar;
|
|
219
373
|
leftToolbar(): UI.Toolbar.Toolbar {
|
|
220
|
-
|
|
374
|
+
if (!this.#leftToolbar) {
|
|
375
|
+
this.#leftToolbar =
|
|
376
|
+
document.createElement('devtools-toolbar') /* eslint-disable-line @devtools/no-imperative-dom-api */;
|
|
377
|
+
this.#leftToolbar.classList.add('tabbed-pane-left-toolbar');
|
|
378
|
+
this.#leftToolbar.slot = 'left';
|
|
379
|
+
this.tabbedPane.appendChild(this.#leftToolbar);
|
|
380
|
+
}
|
|
381
|
+
return this.#leftToolbar;
|
|
221
382
|
}
|
|
222
383
|
|
|
384
|
+
#rightToolbar?: UI.Toolbar.Toolbar;
|
|
223
385
|
rightToolbar(): UI.Toolbar.Toolbar {
|
|
224
|
-
|
|
386
|
+
if (!this.#rightToolbar) {
|
|
387
|
+
this.#rightToolbar =
|
|
388
|
+
document.createElement('devtools-toolbar') /* eslint-disable-line @devtools/no-imperative-dom-api */;
|
|
389
|
+
this.#rightToolbar.classList.add('tabbed-pane-right-toolbar');
|
|
390
|
+
this.#rightToolbar.slot = 'right';
|
|
391
|
+
this.tabbedPane.appendChild(this.#rightToolbar);
|
|
392
|
+
}
|
|
393
|
+
return this.#rightToolbar;
|
|
225
394
|
}
|
|
226
395
|
|
|
227
396
|
showFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
@@ -250,11 +419,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
250
419
|
}
|
|
251
420
|
|
|
252
421
|
closeAllFiles(): void {
|
|
253
|
-
this.closeTabs(this.
|
|
422
|
+
this.closeTabs(Array.from(this.files.keys()));
|
|
254
423
|
}
|
|
255
424
|
|
|
256
425
|
detachEditors(): void {
|
|
257
|
-
this.
|
|
426
|
+
for (const view of this.fileViews()) {
|
|
427
|
+
view.detach();
|
|
428
|
+
}
|
|
258
429
|
}
|
|
259
430
|
|
|
260
431
|
historyUISourceCodes(): Workspace.UISourceCode.UISourceCode[] {
|
|
@@ -269,11 +440,37 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
269
440
|
}
|
|
270
441
|
|
|
271
442
|
selectNextTab(): void {
|
|
272
|
-
this.
|
|
443
|
+
const tabIds = Array.from(this.files.keys());
|
|
444
|
+
if (tabIds.length === 0 || !this.#currentFile) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const currentTabId = this.tabIds.get(this.#currentFile);
|
|
448
|
+
if (!currentTabId) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
const index = tabIds.indexOf(currentTabId);
|
|
452
|
+
const nextIndex = (index + 1) % tabIds.length;
|
|
453
|
+
const nextFile = this.files.get(tabIds[nextIndex]);
|
|
454
|
+
if (nextFile) {
|
|
455
|
+
this.#showFile(nextFile, false);
|
|
456
|
+
}
|
|
273
457
|
}
|
|
274
458
|
|
|
275
459
|
selectPrevTab(): void {
|
|
276
|
-
this.
|
|
460
|
+
const tabIds = Array.from(this.files.keys());
|
|
461
|
+
if (tabIds.length === 0 || !this.#currentFile) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const currentTabId = this.tabIds.get(this.#currentFile);
|
|
465
|
+
if (!currentTabId) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const index = tabIds.indexOf(currentTabId);
|
|
469
|
+
const prevIndex = (index - 1 + tabIds.length) % tabIds.length;
|
|
470
|
+
const prevFile = this.files.get(tabIds[prevIndex]);
|
|
471
|
+
if (prevFile) {
|
|
472
|
+
this.#showFile(prevFile, false);
|
|
473
|
+
}
|
|
277
474
|
}
|
|
278
475
|
|
|
279
476
|
private addViewListeners(): void {
|
|
@@ -311,8 +508,8 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
311
508
|
if (update.docChanged || update.selectionSet) {
|
|
312
509
|
const {main} = update.state.selection;
|
|
313
510
|
const lineFrom = update.state.doc.lineAt(main.from), lineTo = update.state.doc.lineAt(main.to);
|
|
314
|
-
const range = new TextUtils.TextRange.TextRange(
|
|
315
|
-
|
|
511
|
+
const range = new TextUtils.TextRange.TextRange(lineFrom.number - 1, main.from - lineFrom.from, lineTo.number - 1,
|
|
512
|
+
main.to - lineTo.from);
|
|
316
513
|
if (this.#currentFile) {
|
|
317
514
|
this.history.updateSelectionRange(historyItemKey(this.#currentFile), range);
|
|
318
515
|
}
|
|
@@ -342,9 +539,12 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
342
539
|
// Selecting the tab may cause showFile to be called again, but with the canonical source code,
|
|
343
540
|
// which is not what we want, so we prevent reentrant calls.
|
|
344
541
|
this.reentrantShow = true;
|
|
345
|
-
const tabId = this.tabIds.get(canonicalSourceCode) || this.appendFileTab(canonicalSourceCode
|
|
542
|
+
const tabId = this.tabIds.get(canonicalSourceCode) || this.appendFileTab(canonicalSourceCode);
|
|
543
|
+
this.#appendHistory(tabId);
|
|
346
544
|
|
|
347
|
-
this
|
|
545
|
+
this.#scheduleUpdate();
|
|
546
|
+
// Force TabbedPaneElement to sync its tabs synchronously to avoid layout races in E2E tests.
|
|
547
|
+
this.tabbedPane.tabs;
|
|
348
548
|
} finally {
|
|
349
549
|
this.reentrantShow = false;
|
|
350
550
|
}
|
|
@@ -354,6 +554,9 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
354
554
|
}
|
|
355
555
|
|
|
356
556
|
const previousView = this.currentView;
|
|
557
|
+
if (uiSourceCode) {
|
|
558
|
+
this.getOrCreateSourceView(uiSourceCode);
|
|
559
|
+
}
|
|
357
560
|
this.currentView = this.visibleView;
|
|
358
561
|
this.addViewListeners();
|
|
359
562
|
|
|
@@ -396,9 +599,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
396
599
|
if (!shouldPrompt || confirm(i18nString(UIStrings.areYouSureYouWantToCloseUnsaved, {PH1: uiSourceCode.name()}))) {
|
|
397
600
|
uiSourceCode.resetWorkingCopy();
|
|
398
601
|
if (nextTabId) {
|
|
399
|
-
this.
|
|
602
|
+
const nextFile = this.files.get(nextTabId);
|
|
603
|
+
if (nextFile) {
|
|
604
|
+
this.#showFile(nextFile, false);
|
|
605
|
+
}
|
|
400
606
|
}
|
|
401
|
-
this.
|
|
607
|
+
this.tabClosed(id, true);
|
|
608
|
+
this.#scheduleUpdate();
|
|
402
609
|
return true;
|
|
403
610
|
}
|
|
404
611
|
return false;
|
|
@@ -419,9 +626,13 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
419
626
|
}
|
|
420
627
|
}
|
|
421
628
|
if (dirtyTabs.length) {
|
|
422
|
-
this.
|
|
629
|
+
const dirtyFile = this.files.get(dirtyTabs[0]);
|
|
630
|
+
if (dirtyFile) {
|
|
631
|
+
this.#showFile(dirtyFile, false);
|
|
632
|
+
}
|
|
423
633
|
}
|
|
424
|
-
this.
|
|
634
|
+
cleanTabs.forEach(id => this.tabClosed(id, true));
|
|
635
|
+
this.#scheduleUpdate();
|
|
425
636
|
for (let i = 0; i < dirtyTabs.length; ++i) {
|
|
426
637
|
const nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
|
|
427
638
|
if (!this.maybeCloseTab(dirtyTabs[i], nextTabId)) {
|
|
@@ -470,7 +681,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
470
681
|
}
|
|
471
682
|
|
|
472
683
|
if (!this.tabIds.has(uiSourceCode)) {
|
|
473
|
-
this.appendFileTab(uiSourceCode
|
|
684
|
+
this.appendFileTab(uiSourceCode);
|
|
474
685
|
}
|
|
475
686
|
|
|
476
687
|
// Select tab if this file was the last to be shown.
|
|
@@ -500,16 +711,22 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
500
711
|
const tabId = this.tabIds.get(uiSourceCode);
|
|
501
712
|
if (tabId) {
|
|
502
713
|
tabIds.push(tabId);
|
|
714
|
+
} else {
|
|
715
|
+
this.removeSourceFrame(uiSourceCode);
|
|
503
716
|
}
|
|
504
|
-
|
|
505
|
-
|
|
717
|
+
for (const [k, v] of this.uriToUISourceCode) {
|
|
718
|
+
if (v === uiSourceCode) {
|
|
719
|
+
this.uriToUISourceCode.delete(k);
|
|
720
|
+
}
|
|
506
721
|
}
|
|
507
|
-
|
|
508
|
-
|
|
722
|
+
for (const [k, v] of this.idToUISourceCode) {
|
|
723
|
+
if (v === uiSourceCode) {
|
|
724
|
+
this.idToUISourceCode.delete(k);
|
|
725
|
+
}
|
|
509
726
|
}
|
|
510
|
-
this.removeSourceFrame(uiSourceCode);
|
|
511
727
|
}
|
|
512
|
-
this.
|
|
728
|
+
tabIds.forEach(id => this.tabClosed(id, false));
|
|
729
|
+
this.#scheduleUpdate();
|
|
513
730
|
}
|
|
514
731
|
|
|
515
732
|
private editorClosedByUserAction(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
@@ -523,7 +740,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
523
740
|
|
|
524
741
|
private updateHistory(): void {
|
|
525
742
|
const historyItemKeys = [];
|
|
526
|
-
for (const tabId of this.
|
|
743
|
+
for (const tabId of this.#tabsHistory.slice(0, MAX_PREVIOUSLY_VIEWED_FILES_COUNT)) {
|
|
527
744
|
const uiSourceCode = this.files.get(tabId);
|
|
528
745
|
if (uiSourceCode !== undefined) {
|
|
529
746
|
historyItemKeys.push(historyItemKey(uiSourceCode));
|
|
@@ -538,24 +755,27 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
538
755
|
return uiSourceCode.url();
|
|
539
756
|
}
|
|
540
757
|
|
|
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
|
-
|
|
758
|
+
private appendFileTab(uiSourceCode: Workspace.UISourceCode.UISourceCode, index?: number,
|
|
759
|
+
ignoreHistory?: boolean): string {
|
|
548
760
|
const tabId = this.generateTabId();
|
|
549
761
|
this.tabIds.set(uiSourceCode, tabId);
|
|
550
|
-
this.files.set(tabId, uiSourceCode);
|
|
551
762
|
|
|
552
|
-
if (
|
|
553
|
-
const
|
|
554
|
-
|
|
763
|
+
if (index !== undefined) {
|
|
764
|
+
const entries = Array.from(this.files.entries());
|
|
765
|
+
entries.splice(index, 0, [tabId, uiSourceCode]);
|
|
766
|
+
this.files = new Map(entries);
|
|
767
|
+
} else {
|
|
768
|
+
this.files.set(tabId, uiSourceCode);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const savedSelectionRange = this.history.selectionRange(historyItemKey(uiSourceCode));
|
|
772
|
+
const savedScrollLineNumber = this.history.scrollLineNumber(historyItemKey(uiSourceCode));
|
|
773
|
+
const view = this.viewForFile(uiSourceCode);
|
|
774
|
+
if (view && !ignoreHistory) {
|
|
555
775
|
this.restoreEditorProperties(view, savedSelectionRange, savedScrollLineNumber);
|
|
556
776
|
}
|
|
557
777
|
|
|
558
|
-
this
|
|
778
|
+
this.#scheduleUpdate();
|
|
559
779
|
|
|
560
780
|
this.updateFileTitle(uiSourceCode);
|
|
561
781
|
this.addUISourceCodeListeners(uiSourceCode);
|
|
@@ -568,6 +788,10 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
568
788
|
}
|
|
569
789
|
});
|
|
570
790
|
}
|
|
791
|
+
|
|
792
|
+
if (!this.#currentFile) {
|
|
793
|
+
this.#showFile(uiSourceCode, false);
|
|
794
|
+
}
|
|
571
795
|
return tabId;
|
|
572
796
|
}
|
|
573
797
|
|
|
@@ -577,13 +801,15 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
577
801
|
title=${i18nString(UIStrings.unableToLoadThisContent)}>
|
|
578
802
|
</devtools-icon>`;
|
|
579
803
|
// clang-format on
|
|
580
|
-
|
|
581
|
-
|
|
804
|
+
const uiSourceCode = this.files.get(tabId);
|
|
805
|
+
if (uiSourceCode) {
|
|
806
|
+
this.#tabIcons.set(uiSourceCode, icon);
|
|
807
|
+
this.#scheduleUpdate();
|
|
582
808
|
}
|
|
583
809
|
}
|
|
584
810
|
|
|
585
|
-
private restoreEditorProperties(
|
|
586
|
-
|
|
811
|
+
private restoreEditorProperties(editorView: UI.Widget.Widget, selection?: TextUtils.TextRange.TextRange,
|
|
812
|
+
firstLineNumber?: number): void {
|
|
587
813
|
const sourceFrame = editorView instanceof SourceFrame.SourceFrame.SourceFrameImpl ? editorView : null;
|
|
588
814
|
if (!sourceFrame) {
|
|
589
815
|
return;
|
|
@@ -596,8 +822,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
596
822
|
}
|
|
597
823
|
}
|
|
598
824
|
|
|
599
|
-
private tabClosed(
|
|
600
|
-
const {tabId, isUserGesture} = event.data;
|
|
825
|
+
private tabClosed(tabId: string, isUserGesture?: boolean): void {
|
|
601
826
|
const uiSourceCode = this.files.get(tabId);
|
|
602
827
|
if (this.#currentFile && this.#currentFile.canonicalScriptId() === uiSourceCode?.canonicalScriptId()) {
|
|
603
828
|
this.removeViewListeners();
|
|
@@ -621,9 +846,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
621
846
|
}
|
|
622
847
|
}
|
|
623
848
|
|
|
624
|
-
private tabSelected(
|
|
625
|
-
const {tabId, isUserGesture} = event.data;
|
|
626
|
-
|
|
849
|
+
private tabSelected(tabId: string, isUserGesture?: boolean): void {
|
|
627
850
|
const uiSourceCode = this.files.get(tabId);
|
|
628
851
|
if (uiSourceCode) {
|
|
629
852
|
this.#showFile(uiSourceCode, isUserGesture);
|
|
@@ -632,33 +855,32 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
632
855
|
|
|
633
856
|
private addUISourceCodeListeners(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
634
857
|
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
635
|
-
uiSourceCode.addEventListener(
|
|
636
|
-
|
|
637
|
-
uiSourceCode.addEventListener(
|
|
638
|
-
|
|
858
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged, this.uiSourceCodeWorkingCopyChanged,
|
|
859
|
+
this);
|
|
860
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
|
|
861
|
+
this.uiSourceCodeWorkingCopyCommitted, this);
|
|
639
862
|
}
|
|
640
863
|
|
|
641
864
|
private removeUISourceCodeListeners(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
642
865
|
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
643
|
-
uiSourceCode.removeEventListener(
|
|
644
|
-
|
|
645
|
-
uiSourceCode.removeEventListener(
|
|
646
|
-
|
|
866
|
+
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged,
|
|
867
|
+
this.uiSourceCodeWorkingCopyChanged, this);
|
|
868
|
+
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.WorkingCopyCommitted,
|
|
869
|
+
this.uiSourceCodeWorkingCopyCommitted, this);
|
|
647
870
|
}
|
|
648
871
|
|
|
649
872
|
private updateFileTitle(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
650
873
|
const tabId = this.tabIds.get(uiSourceCode);
|
|
651
874
|
if (tabId) {
|
|
652
|
-
|
|
653
|
-
const tooltip = this.tooltipForFile(uiSourceCode);
|
|
654
|
-
this.tabbedPane.changeTabTitle(tabId, title, tooltip);
|
|
875
|
+
this.#scheduleUpdate();
|
|
655
876
|
if (uiSourceCode.loadError()) {
|
|
656
877
|
// clang-format off
|
|
657
878
|
const icon = html`<devtools-icon class="small" name="cross-circle-filled"
|
|
658
879
|
title=${i18nString(UIStrings.unableToLoadThisContent)}>
|
|
659
880
|
</devtools-icon>`;
|
|
660
881
|
// clang-format on
|
|
661
|
-
this.
|
|
882
|
+
this.#tabIcons.set(uiSourceCode, icon);
|
|
883
|
+
this.#scheduleUpdate();
|
|
662
884
|
} else if (Persistence.Persistence.PersistenceImpl.instance().hasUnsavedCommittedChanges(uiSourceCode)) {
|
|
663
885
|
/* eslint-disable @devtools/no-imperative-dom-api --
|
|
664
886
|
* This is a temporary solution using the <devtools-tooltip>
|
|
@@ -691,10 +913,16 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
691
913
|
}
|
|
692
914
|
suffixElement.append(icon, tooltip);
|
|
693
915
|
/* eslint-enable @devtools/no-imperative-dom-api */
|
|
694
|
-
this.
|
|
916
|
+
this.#tabSuffixes.set(uiSourceCode, suffixElement);
|
|
917
|
+
this.#scheduleUpdate();
|
|
695
918
|
} else {
|
|
696
919
|
const icon = PanelCommon.PersistenceUtils.PersistenceUtils.iconForUISourceCode(uiSourceCode);
|
|
697
|
-
|
|
920
|
+
if (icon) {
|
|
921
|
+
this.#tabIcons.set(uiSourceCode, icon as TemplateResult);
|
|
922
|
+
} else {
|
|
923
|
+
this.#tabIcons.delete(uiSourceCode);
|
|
924
|
+
}
|
|
925
|
+
this.#scheduleUpdate();
|
|
698
926
|
}
|
|
699
927
|
}
|
|
700
928
|
}
|
|
@@ -703,7 +931,7 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
703
931
|
void {
|
|
704
932
|
const uiSourceCode = event.data;
|
|
705
933
|
|
|
706
|
-
const widget =
|
|
934
|
+
const widget = getViewByUISourceCode(uiSourceCode);
|
|
707
935
|
if (widget) {
|
|
708
936
|
if (this.#sourceViewTypeForWidget(widget) !== this.#sourceViewTypeForUISourceCode(uiSourceCode)) {
|
|
709
937
|
// Remove the existing editor tab and create a new one of the correct type.
|
|
@@ -813,49 +1041,35 @@ export class TabbedEditorContainer extends TabbedEditorContainerBase {
|
|
|
813
1041
|
}
|
|
814
1042
|
|
|
815
1043
|
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);
|
|
1044
|
+
return getViewByUISourceCode(uiSourceCode);
|
|
821
1045
|
}
|
|
822
1046
|
|
|
823
1047
|
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);
|
|
1048
|
+
const view = getViewByUISourceCode(uiSourceCode);
|
|
1049
|
+
if (view) {
|
|
1050
|
+
return view;
|
|
840
1051
|
}
|
|
1052
|
+
return getOrCreateSourceView(uiSourceCode, sourceView => {
|
|
1053
|
+
if (sourceView instanceof UISourceCodeFrame) {
|
|
1054
|
+
this.#historyManager.trackSourceFrameCursorJumps(sourceView);
|
|
1055
|
+
}
|
|
1056
|
+
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
841
1059
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
return sourceView;
|
|
1060
|
+
viewForFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): UI.Widget.Widget {
|
|
1061
|
+
return this.getOrCreateSourceView(uiSourceCode);
|
|
845
1062
|
}
|
|
846
1063
|
|
|
847
1064
|
recycleUISourceCodeFrame(sourceFrame: UISourceCodeFrame, uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
848
1065
|
sourceFrame.uiSourceCode().removeEventListener(Workspace.UISourceCode.Events.TitleChanged,
|
|
849
1066
|
this.uiSourceCodeTitleChanged, this);
|
|
850
|
-
|
|
851
|
-
sourceFrame.setUISourceCode(uiSourceCode);
|
|
852
|
-
this.sourceViewByUISourceCode.set(uiSourceCode, sourceFrame);
|
|
1067
|
+
recycleUISourceCodeFrame(sourceFrame, uiSourceCode);
|
|
853
1068
|
uiSourceCode.addEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
854
1069
|
}
|
|
855
1070
|
|
|
856
1071
|
private removeSourceFrame(uiSourceCode: Workspace.UISourceCode.UISourceCode): void {
|
|
857
|
-
const sourceView =
|
|
858
|
-
this.sourceViewByUISourceCode.delete(uiSourceCode);
|
|
1072
|
+
const sourceView = removeSourceViewCache(uiSourceCode);
|
|
859
1073
|
if (sourceView) {
|
|
860
1074
|
uiSourceCode.removeEventListener(Workspace.UISourceCode.Events.TitleChanged, this.uiSourceCodeTitleChanged, this);
|
|
861
1075
|
}
|
|
@@ -941,9 +1155,8 @@ export class HistoryItem implements HistoryItemKey {
|
|
|
941
1155
|
selectionRange: TextUtils.TextRange.TextRange|undefined;
|
|
942
1156
|
scrollLineNumber: number|undefined;
|
|
943
1157
|
|
|
944
|
-
constructor(
|
|
945
|
-
|
|
946
|
-
selectionRange?: TextUtils.TextRange.TextRange, scrollLineNumber?: number) {
|
|
1158
|
+
constructor(url: Platform.DevToolsPath.UrlString, resourceType: Common.ResourceType.ResourceType,
|
|
1159
|
+
selectionRange?: TextUtils.TextRange.TextRange, scrollLineNumber?: number) {
|
|
947
1160
|
this.url = url;
|
|
948
1161
|
this.resourceType = resourceType;
|
|
949
1162
|
this.selectionRange = selectionRange;
|