From 2aa98c82da2a516f715d1a466c65e0dbb752fd01 Mon Sep 17 00:00:00 2001 From: kaorun343 <5625395+kaorun343@users.noreply.github.com> Date: Fri, 3 Nov 2023 03:12:51 +0900 Subject: [PATCH 1/4] Introduce react-contexify --- package.json | 1 + yarn.lock | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/package.json b/package.json index a3800a58..85b32786 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "pg": "8.7.1", "plotly.js-basic-dist-min": "1.57.1", "react": "16.8.6", + "react-contexify": "^6.0.0", "react-dom": "16.8.6", "react-linkify": "^1.0.0-alpha", "react-micro-flyout": "1.0.1", diff --git a/yarn.lock b/yarn.lock index e79660be..b119c60d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2488,6 +2488,11 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -6131,6 +6136,13 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-contexify@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/react-contexify/-/react-contexify-6.0.0.tgz#52959bb507d6a31224fe870ae147e211e359abe1" + integrity sha512-jMhz6yZI81Jv3UDj7TXqCkhdkCFEEmvwGCPXsQuA2ZUC8EbCuVQ6Cy8FzKMXa0y454XTDClBN2YFvvmoFlrFkg== + dependencies: + clsx "^1.2.1" + react-dom@16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f" From 742a8995c9ecc6a597a4a3e0decda3195c409980 Mon Sep 17 00:00:00 2001 From: kaorun343 <5625395+kaorun343@users.noreply.github.com> Date: Fri, 3 Nov 2023 03:12:57 +0900 Subject: [PATCH 2/4] Use react-contexify --- .../DataSourceList/DataSourceList.tsx | 106 ++++++++++-------- .../components/QueryList/QueryList.tsx | 61 ++++++---- 2 files changed, 99 insertions(+), 68 deletions(-) diff --git a/src/renderer/components/DataSourceList/DataSourceList.tsx b/src/renderer/components/DataSourceList/DataSourceList.tsx index 5cee8f14..d9fd7f44 100644 --- a/src/renderer/components/DataSourceList/DataSourceList.tsx +++ b/src/renderer/components/DataSourceList/DataSourceList.tsx @@ -1,7 +1,10 @@ -import React from "react"; +import React, { MouseEvent } from "react"; import classNames from "classnames"; -import { remote } from "electron"; import { DataSourceType } from "../../pages/DataSource/DataSourceStore"; +import { Menu, Item, useContextMenu } from "react-contexify"; +import "react-contexify/ReactContexify.css"; + +const MENU_ID = "DATA_SOURCE_LIST_MENU"; type Props = { readonly dataSources: DataSourceType[]; @@ -26,53 +29,60 @@ const DataSourceList: React.FC = ({ onDelete, changeDefaultDataSourceId, }) => { - const handleContextMenu = (id: number): void => { + const handleEdit = () => { + if (selectedDataSourceId === null) { + return; + } + const dataSource = find(selectedDataSourceId); + if (dataSource) { + onEdit(dataSource); + } + }; + + const handleReload = () => { + if (selectedDataSourceId === null) { + return; + } + const dataSource = find(selectedDataSourceId); + if (dataSource) { + onReload(dataSource); + } + }; + + const handleSetAsDefault = () => { + if (selectedDataSourceId === null) { + return; + } + changeDefaultDataSourceId(selectedDataSourceId); + }; + + const handleDelete = () => { + if (selectedDataSourceId === null) { + return; + } + if (window.confirm("Are you sure?")) { + onDelete(selectedDataSourceId); + } + }; + + const { show } = useContextMenu({ + id: MENU_ID, + }); + + const handleContextMenu = (event: MouseEvent, id: number): void => { + show({ + event, + props: { + key: "value", + }, + }); + if (id !== selectedDataSourceId) { const dataSource = find(id); if (dataSource) { - onSelect(dataSources[id]); + onSelect(dataSource); } } - - setImmediate(() => { - const menu = remote.Menu.buildFromTemplate([ - { - label: "Edit", - click: (): void => { - const dataSource = find(id); - if (dataSource) { - onEdit(dataSource); - } - }, - }, - { - label: "Reload", - click: (): void => { - const dataSource = find(id); - if (dataSource) { - onReload(dataSource); - } - }, - }, - { - label: "Set as default", - type: "checkbox", - checked: id === defaultDataSourceId, - click: (): void => { - changeDefaultDataSourceId(id); - }, - }, - { - label: "Delete", - click: (): void => { - if (window.confirm("Are you sure?")) { - onDelete(id); - } - }, - }, - ]); - menu.popup({ window: remote.getCurrentWindow() }); - }); }; const find = (id: number): DataSourceType | undefined => { @@ -88,7 +98,7 @@ const DataSourceList: React.FC = ({
  • handleContextMenu(dataSource.id)} + onContextMenu={(event): void => handleContextMenu(event, dataSource.id)} onClick={(): void => onSelect(dataSource)} > {label} @@ -101,6 +111,12 @@ const DataSourceList: React.FC = ({
    + + Edit + Reload + Set as default + Delete +
      {items}
    ); diff --git a/src/renderer/components/QueryList/QueryList.tsx b/src/renderer/components/QueryList/QueryList.tsx index 962bc94e..d36601f6 100644 --- a/src/renderer/components/QueryList/QueryList.tsx +++ b/src/renderer/components/QueryList/QueryList.tsx @@ -1,7 +1,10 @@ -import React, { useState } from "react"; +import React, { useState, MouseEvent } from "react"; import classNames from "classnames"; -import { remote } from "electron"; import { QueryType } from "../../../lib/Database/Query"; +import { Menu, Item, useContextMenu } from "react-contexify"; +import "react-contexify/ReactContexify.css"; + +const MENU_ID = "QUERY_LIST_MENU"; type Props = { readonly queries: QueryType[]; @@ -24,27 +27,35 @@ const QueryList: React.FC = ({ const handleClickItem = onSelectQuery; - const handleContextMenu = (queryId: number): void => { - onSelectQuery(queryId); - setImmediate(() => { - const menu = remote.Menu.buildFromTemplate([ - { - label: "Duplicate", - click: (): void => { - onDuplicateQuery(queryId); - }, - }, - { - label: "Delete", - click: (): void => { - if (window.confirm("Are you sure?")) { - onDeleteQuery(queryId); - } - }, - }, - ]); - menu.popup({ window: remote.getCurrentWindow() }); + const handleDuplicate = () => { + if (selectedQueryId === null) { + return; + } + onDuplicateQuery(selectedQueryId); + }; + + const handleDelete = () => { + if (selectedQueryId === null) { + return; + } + if (window.confirm("Are you sure?")) { + onDeleteQuery(selectedQueryId); + } + }; + + const { show } = useContextMenu({ + id: MENU_ID, + }); + + const handleContextMenu = (event: MouseEvent, queryId: number): void => { + show({ + event, + props: { + key: "value", + }, }); + + onSelectQuery(queryId); }; const [filterText, setFilterText] = useState(""); @@ -63,13 +74,17 @@ const QueryList: React.FC = ({ + + Duplicate + Delete +
      {filteredQueries.map((query) => (
    • handleClickItem(query.id)} - onContextMenu={(): void => handleContextMenu(query.id)} + onContextMenu={(event): void => handleContextMenu(event, query.id)} >
      {query.title}
      From 481dc17ac352e1ef62b404012f2841e5124327fc Mon Sep 17 00:00:00 2001 From: kaorun343 <5625395+kaorun343@users.noreply.github.com> Date: Fri, 3 Nov 2023 21:41:04 +0900 Subject: [PATCH 3/4] Add getConfig channel --- src/lib/Bdash.ts | 5 ++++- src/{lib => main}/Config.ts | 2 +- src/main/window.ts | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) rename src/{lib => main}/Config.ts (84%) diff --git a/src/lib/Bdash.ts b/src/lib/Bdash.ts index 0c63a962..6acf4401 100644 --- a/src/lib/Bdash.ts +++ b/src/lib/Bdash.ts @@ -1,13 +1,16 @@ import fs from "fs"; -import Config from "./Config"; import { ensureDirSync } from "fs-extra"; import { setting } from "./Setting"; import Database from "./Database"; +import { ipcRenderer } from "electron"; const Bdash = { async initialize(): Promise { // @see https://github.com/bdash-app/bdash/pull/99#issuecomment-590011101 window.process["browser"] = true; + + const Config = await ipcRenderer.invoke("getConfig"); + if (!fs.existsSync(Config.bdashRoot)) { ensureDirSync(Config.bdashRoot); } diff --git a/src/lib/Config.ts b/src/main/Config.ts similarity index 84% rename from src/lib/Config.ts rename to src/main/Config.ts index 3056cc43..ccf2bcad 100644 --- a/src/lib/Config.ts +++ b/src/main/Config.ts @@ -5,7 +5,7 @@ import os from "os"; const bdashRoot = process.env.NODE_ENV === "test" ? path.join(os.tmpdir(), ".bdash") - : path.resolve(electron.remote.app.getPath("home"), ".bdash"); + : path.resolve(electron.app.getPath("home"), ".bdash"); const databasePath = path.join(bdashRoot, "bdash.sqlite3"); const settingPath = path.join(bdashRoot, "setting.yml"); diff --git a/src/main/window.ts b/src/main/window.ts index cc2e28c1..c87e3b67 100644 --- a/src/main/window.ts +++ b/src/main/window.ts @@ -1,6 +1,7 @@ import electron, { BrowserWindow, dialog, ipcMain, shell } from "electron"; import path from "path"; import logger from "./logger"; +import Config from "./Config"; const windows: BrowserWindow[] = []; @@ -18,6 +19,8 @@ export async function createWindow(): Promise { }, }); + ipcMain.handle("getConfig", async () => Config); + ipcMain.on("showUpdateQueryDialog", async (event) => { const { response } = await dialog.showMessageBox(win, { message: "This query has been already shared.", From e0e88883f8e78813e63f58b06f267835bbe547c3 Mon Sep 17 00:00:00 2001 From: kaorun343 <5625395+kaorun343@users.noreply.github.com> Date: Fri, 3 Nov 2023 21:41:27 +0900 Subject: [PATCH 4/4] Set enableRemoteModule to false --- src/main/window.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/window.ts b/src/main/window.ts index c87e3b67..4731d042 100644 --- a/src/main/window.ts +++ b/src/main/window.ts @@ -14,7 +14,6 @@ export async function createWindow(): Promise { icon: path.join(__dirname, "..", "icon.png"), webPreferences: { nodeIntegration: true, - enableRemoteModule: true, contextIsolation: false, }, });