diff --git a/package-lock.json b/package-lock.json index 9d3afc8..0e21abf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,11 @@ "dependencies": { "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^3.0.0", + "electron-prompt": "^1.7.0", "electron-updater": "^6.3.4", "is-json": "^2.0.1", "js-yaml": "^4.1.0", + "phin": "^3.7.1", "swagger-editor-dist": "^4.13.1" }, "bin": { @@ -24,6 +26,7 @@ "@electron-toolkit/eslint-config-prettier": "^2.0.0", "@electron-toolkit/eslint-config-ts": "^2.0.0", "@electron-toolkit/tsconfig": "^1.0.1", + "@types/electron-prompt": "^1.6.5", "@types/js-yaml": "^4.0.9", "@types/node": "^22.5.4", "@types/react": "^18.3.5", @@ -2222,6 +2225,16 @@ "@types/ms": "*" } }, + "node_modules/@types/electron-prompt": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@types/electron-prompt/-/electron-prompt-1.6.5.tgz", + "integrity": "sha512-CuhgXY5xQZ2lzoXdofCHrLEHoQdf6DIZelmRlDf+uvWhF7z00vIOjXxlXcp3rUAJ28qkM8MDdSFh9NyU8vKi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "electron": "latest" + } + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -3494,6 +3507,15 @@ ], "license": "CC-BY-4.0" }, + "node_modules/centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4435,6 +4457,12 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-prompt": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/electron-prompt/-/electron-prompt-1.7.0.tgz", + "integrity": "sha512-IfqJYEgcRO6NuyPROo8AtdkAiZ6N9I1lQEf4dJAkPuhV5YgOHdmLqZJf6OXumZJfzrjpzCM5jHeYOrhGdgbnEA==", + "license": "MIT" + }, "node_modules/electron-publish": { "version": "25.0.3", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.0.3.tgz", @@ -5555,6 +5583,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -8215,6 +8263,18 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "license": "MIT" }, + "node_modules/phin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", + "license": "MIT", + "dependencies": { + "centra": "^2.7.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", diff --git a/package.json b/package.json index e55baf4..9308408 100644 --- a/package.json +++ b/package.json @@ -38,15 +38,18 @@ "dependencies": { "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^3.0.0", + "electron-prompt": "^1.7.0", "electron-updater": "^6.3.4", "is-json": "^2.0.1", "js-yaml": "^4.1.0", + "phin": "^3.7.1", "swagger-editor-dist": "^4.13.1" }, "devDependencies": { "@electron-toolkit/eslint-config-prettier": "^2.0.0", "@electron-toolkit/eslint-config-ts": "^2.0.0", "@electron-toolkit/tsconfig": "^1.0.1", + "@types/electron-prompt": "^1.6.5", "@types/js-yaml": "^4.0.9", "@types/node": "^22.5.4", "@types/react": "^18.3.5", diff --git a/src/main/commands.ts b/src/main/commands.ts index e441d28..6af16ee 100644 --- a/src/main/commands.ts +++ b/src/main/commands.ts @@ -1,8 +1,9 @@ import {BrowserWindow, dialog} from 'electron' +import prompt from "electron-prompt"; import { promises as fs } from 'fs' - -import { dump, load } from "js-yaml" import isJsonObject from "is-json" +import { dump, load } from "js-yaml" +import request from 'phin' function updateSpec(window: BrowserWindow, content: string) { const preparedContent = isJsonObject(content) ? dump(load(content)) : content @@ -10,6 +11,26 @@ function updateSpec(window: BrowserWindow, content: string) { window.webContents.send('update-spec', preparedContent); } +export async function importURL() { + const window = BrowserWindow.getFocusedWindow()! + const url = await prompt({ + title: 'Import URL', + label: 'Enter the URL to import from', + inputAttrs: { + type: 'url' + }, + type: 'input' + }, window) + if (url) { + try { + const res = await request({method: "GET", url}); + updateSpec(window, res.body.toString()); + } catch(e: any) { + dialog.showErrorBox('Error loading URL', `Oof! There was an error loading your document:\n\n${e.message || e}`) + } + } +} + export async function importFile() { const window = BrowserWindow.getFocusedWindow()! const selected = await dialog.showOpenDialog({ diff --git a/src/main/index.ts b/src/main/index.ts index 9b7c649..182645d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,6 +3,7 @@ import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/icon.png?asset' +import { importURL } from './commands' import './menus' function createWindow(): void { @@ -53,8 +54,7 @@ app.whenReady().then(() => { optimizer.watchWindowShortcuts(window) }) - // IPC test - ipcMain.on('ping', () => console.log('pong')) + ipcMain.handle('import-url', importURL) createWindow() diff --git a/src/main/menus.ts b/src/main/menus.ts index 492f524..ae01f7a 100644 --- a/src/main/menus.ts +++ b/src/main/menus.ts @@ -1,6 +1,6 @@ import { Menu, MenuItemConstructorOptions, shell } from 'electron' -import { clearEditor, importFile } from "./commands"; +import { clearEditor, importFile, importURL } from "./commands"; const isMac = process.platform === 'darwin' @@ -13,6 +13,11 @@ const template = [ label: 'Import file', click: importFile }, + { + label: 'Import URL', + click: importURL + }, + { type: 'separator' }, { label: 'Clear editor', click: clearEditor diff --git a/src/renderer/src/plugins/electron-menus.ts b/src/renderer/src/plugins/electron-menus.ts index 1f05a9f..67a6d35 100644 --- a/src/renderer/src/plugins/electron-menus.ts +++ b/src/renderer/src/plugins/electron-menus.ts @@ -9,8 +9,22 @@ class ElectronMenus { constructor() { window.electron.ipcRenderer.on("update-spec", this.updateSpec); + this.overridePrompt() } + overridePrompt() { + const originalPrompt = window.prompt; + window.prompt = message => { + if (message === "Enter the URL to import from:") { + window.electron.ipcRenderer.invoke('import-url'); + return ""; + } else { + return originalPrompt(message); + } + } + } + + updateSpec = (_event, spec) => { this.system.specActions.updateSpec(spec); }