Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions front_end/global_typings/react_native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ declare global {
namespace globalThis {
var enableReactNativePerfMetrics: boolean|undefined;
var enableReactNativePerfMetricsGlobalPostMessage: boolean|undefined;
var enableReactNativeOpenInExternalEditor: boolean|undefined;
var reactNativeOpenInEditorButtonImage: string|undefined;
var FB_ONLY__reactNativeFeedbackLink: string|undefined;
}
}
45 changes: 45 additions & 0 deletions front_end/panels/sources/UISourceCodeFrame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import * as Persistence from '../../models/persistence/persistence.js';
import * as TextUtils from '../../models/text_utils/text_utils.js';
import * as Workspace from '../../models/workspace/workspace.js';
import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
import * as Adorners from '../../ui/components/adorners/adorners.js';
import * as IconButton from '../../ui/components/icon_button/icon_button.js';
import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
Expand Down Expand Up @@ -78,6 +79,7 @@ export class UISourceCodeFrame extends
// recreated when the binding changes
private plugins: Plugin[] = [];
private readonly errorPopoverHelper: UI.PopoverHelper.PopoverHelper;
private openInExternalEditorToolbarButton?: UI.Toolbar.ToolbarButton;
#sourcesPanelOpenedMetricsRecorded = false;

constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
Expand All @@ -93,6 +95,37 @@ export class UISourceCodeFrame extends
this.uiSourceCodeEventListeners = [];
this.messageAndDecorationListeners = [];

if (this.canOpenInExternalEditor()) {
this.openInExternalEditorToolbarButton =
new UI.Toolbar.ToolbarButton('Open in editor', undefined, 'Open in editor');
const maybeBackgroundImage = globalThis.reactNativeOpenInEditorButtonImage;
if (typeof maybeBackgroundImage === 'string' && maybeBackgroundImage !== '') {
const adorner = new Adorners.Adorner.Adorner();
adorner.classList.add('open-in-external-editor-adorner');
adorner.style.setProperty('background-image', maybeBackgroundImage);
this.openInExternalEditorToolbarButton.element.classList.add(
'toolbar-has-glyph', 'open-in-external-editor-button');
this.openInExternalEditorToolbarButton.setGlyphOrAdorner(adorner);
} else {
this.openInExternalEditorToolbarButton.setGlyph('open-externally');
}
this.openInExternalEditorToolbarButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, () => {
const body: {url: string, lineNumber?: number} = {
url: this.uiSourceCode().url(),
};

const state = this.textEditor.state;
const line = state.doc.lineAt(state.selection.main.head);
const {lineNumber} = this.editorLocationToUILocation(line.number);
body.lineNumber = lineNumber;

fetch('/open-stack-frame', {
method: 'POST',
body: JSON.stringify(body),
}).catch(e => console.error(e));
});
}

this.boundOnBindingChanged = this.onBindingChanged.bind(this);

Common.Settings.Settings.instance()
Expand All @@ -108,6 +141,14 @@ export class UISourceCodeFrame extends
this.initializeUISourceCode();
}

private canOpenInExternalEditor(): boolean {
if (!globalThis.enableReactNativeOpenInExternalEditor) {
return false;
}

return this.uiSourceCode().url().startsWith('http') ?? false;
}

private async workingCopy(): Promise<TextUtils.ContentProvider.DeferredContent> {
if (this.uiSourceCodeInternal.isDirty()) {
return {content: this.uiSourceCodeInternal.workingCopy(), isEncoded: false};
Expand Down Expand Up @@ -456,6 +497,10 @@ export class UISourceCodeFrame extends
return leftToolbarItems;
}

if (this.openInExternalEditorToolbarButton) {
leftToolbarItems.push(this.openInExternalEditorToolbarButton);
}

return [...leftToolbarItems, new UI.Toolbar.ToolbarSeparator(true), ...rightToolbarItems];
}

Expand Down
19 changes: 19 additions & 0 deletions front_end/ui/legacy/toolbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,22 @@ devtools-icon.leading-issue-icon {
.fusebox-connection-status .toolbar-glyph {
color: white !important;
}

.toolbar-item.open-in-external-editor-button {
background-color: transparent;
border: none;
}

.toolbar-item.open-in-external-editor-button:hover {
background-color: var(--sys-color-state-hover-on-subtle);
}

.open-in-external-editor-adorner {
background-repeat: no-repeat;
background-origin: content-box;
background-size: contain;
padding: 4px;
width: 28px;
height: 28px;
margin-right: -4px;
}
Loading