redux-devtools/packages/redux-devtools-inspector-monitor-trace-tab/src/openFile.ts

142 lines
4.6 KiB
TypeScript

import StackFrame from './react-error-overlay/utils/stack-frame';
const isFF = navigator.userAgent.indexOf('Firefox') !== -1;
function openResource(
fileName: string,
lineNumber: number,
stackFrame: StackFrame
) {
const adjustedLineNumber = Math.max(lineNumber - 1, 0);
chrome.devtools.panels.openResource(fileName, adjustedLineNumber, ((result: {
isError?: boolean;
}) => {
//console.log("openResource callback args: ", callbackArgs);
if (result.isError) {
const { fileName: finalFileName, lineNumber: finalLineNumber } =
stackFrame;
const adjustedLineNumber = Math.max(finalLineNumber! - 1, 0);
chrome.devtools.panels.openResource(
finalFileName!,
adjustedLineNumber,
(/* result */) => {
// console.log("openResource result: ", result);
}
);
}
}) as () => void);
}
function openAndCloseTab(url: string) {
chrome.tabs.create({ url }, (tab) => {
const removeTab = () => {
chrome.windows.onFocusChanged.removeListener(removeTab);
if (tab && tab.id) {
chrome.tabs.remove(tab.id, async () => {
// eslint-disable-next-line no-console
if (chrome.runtime.lastError) console.log(chrome.runtime.lastError);
else if (chrome.devtools && chrome.devtools.inspectedWindow) {
await chrome.tabs.update(chrome.devtools.inspectedWindow.tabId, {
active: true,
});
}
});
}
};
if (chrome.windows) chrome.windows.onFocusChanged.addListener(removeTab);
});
}
function openInIframe(url: string) {
const iframe = document.createElement('iframe');
iframe.src = url;
iframe.style.display = 'none';
document.body.appendChild(iframe);
setTimeout(() => iframe.parentNode!.removeChild(iframe), 3000);
}
function openInEditor(editor: string, path: string, stackFrame: StackFrame) {
const projectPath = path.replace(/\/$/, '');
const file =
stackFrame._originalFileName ||
(stackFrame as unknown as { finalFileName: string }).finalFileName ||
stackFrame.fileName ||
'';
let filePath = /^https?:\/\//.test(file)
? file.replace(/^https?:\/\/[^/]*/, '')
: file.replace(/^\w+:\/\//, '');
filePath = filePath.replace(/^\/~\//, '/node_modules/');
const line = stackFrame._originalLineNumber || stackFrame.lineNumber || '0';
const column =
stackFrame._originalColumnNumber || stackFrame.columnNumber || '0';
let url;
switch (editor) {
case 'vscode':
case 'code':
url = `vscode://file/${projectPath}${filePath}:${line}:${column}`;
break;
case 'atom':
url = `atom://core/open/file?filename=${projectPath}${filePath}&line=${line}&column=${column}`;
break;
case 'webstorm':
case 'phpstorm':
case 'idea':
url = `${editor}://open?file=${projectPath}${filePath}&line=${line}&column=${column}`;
break;
default:
// sublime, emacs, macvim, textmate + custom like https://github.com/eclemens/atom-url-handler
url = `${editor}://open/?url=file://${projectPath}${filePath}&line=${line}&column=${column}`;
}
if (chrome.devtools && !isFF) {
if (chrome.tabs) openAndCloseTab(url);
else window.open(url);
} else {
openInIframe(url);
}
}
export default function openFile(
fileName: string,
lineNumber: number,
stackFrame: StackFrame
) {
if (!chrome || !chrome.storage) return; // TODO: Pass editor settings for using outside of browser extension
const storage = isFF
? chrome.storage.local
: chrome.storage.sync || chrome.storage.local;
storage.get(
['useEditor', 'editor', 'projectPath'],
function ({ useEditor, editor, projectPath }) {
if (
useEditor &&
projectPath &&
typeof editor === 'string' &&
/^\w{1,30}$/.test(editor)
) {
openInEditor(editor.toLowerCase(), projectPath as string, stackFrame);
} else {
if (
chrome.devtools &&
chrome.devtools.panels &&
!!chrome.devtools.panels.openResource
) {
openResource(fileName, lineNumber, stackFrame);
} else if (chrome.runtime && (chrome.runtime.openOptionsPage || isFF)) {
if (chrome.devtools && isFF) {
chrome.devtools.inspectedWindow.eval(
'confirm("Set the editor to open the file in?")',
(result) => {
if (!result) return;
chrome.runtime.sendMessage({ type: 'OPEN_OPTIONS' });
}
);
} else if (confirm('Set the editor to open the file in?')) {
chrome.runtime.openOptionsPage();
}
}
}
}
);
}