From 822c311a0ae7ef65fe8b5e0dce40b919a42b8769 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Thu, 26 Nov 2020 09:55:42 +0100
Subject: [PATCH] [dome] trigger search field on Edit > Find (Cmd+F)

---
 ivette/src/dome/src/main/menubar.ts             | 10 ++++++++++
 ivette/src/dome/src/renderer/dome.tsx           | 17 +++++++++++++----
 ivette/src/dome/src/renderer/frame/toolbars.tsx | 12 +++++++++---
 3 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/ivette/src/dome/src/main/menubar.ts b/ivette/src/dome/src/main/menubar.ts
index 292cfffe70f..b8db69299ff 100644
--- a/ivette/src/dome/src/main/menubar.ts
+++ b/ivette/src/dome/src/main/menubar.ts
@@ -162,6 +162,16 @@ const editMenuItems: MenuSpec = [
     accelerator: 'CmdOrCtrl+A',
     role: 'selectAll',
   },
+  Separator,
+  {
+    label: 'Find',
+    accelerator: 'CmdOrCtrl+F',
+    click: (
+      _item: Electron.MenuItem,
+      window: Electron.BrowserWindow,
+      _evt: Electron.KeyboardEvent,
+    ) => window.webContents.send('dome.ipc.find'),
+  },
 ];
 
 // --------------------------------------------------------------------------
diff --git a/ivette/src/dome/src/renderer/dome.tsx b/ivette/src/dome/src/renderer/dome.tsx
index dda75f74670..b1e1d879afc 100644
--- a/ivette/src/dome/src/renderer/dome.tsx
+++ b/ivette/src/dome/src/renderer/dome.tsx
@@ -98,13 +98,17 @@ export class Event<A = void> {
 
 }
 
+/** Custom React Hook on event. */
 export function useEvent<A>(
-  evt: Event<A>,
+  evt: undefined | null | Event<A>,
   callback: (arg: A) => void,
 ) {
   return React.useEffect(() => {
-    evt.on(callback);
-    return () => evt.off(callback);
+    if (evt) {
+      evt.on(callback);
+      return () => evt.off(callback);
+    }
+    return undefined;
   });
 }
 
@@ -126,9 +130,14 @@ export const update = new Event('dome.update');
    It is emitted when the entire window is reloaded.
 */
 export const reload = new Event('dome.reload');
-
 ipcRenderer.on('dome.ipc.reload', () => reload.emit());
 
+/**
+   Dome « Find » event. Trigered by [Cmd+F] and [Edit > Find] menu.
+ */
+export const find = new Event('dome.find');
+ipcRenderer.on('dome.ipc.find', () => find.emit());
+
 /** Command-line arguments event handler. */
 export function onCommand(
   job: (argv: string[], workingDir: string) => void,
diff --git a/ivette/src/dome/src/renderer/frame/toolbars.tsx b/ivette/src/dome/src/renderer/frame/toolbars.tsx
index bb923b4baf2..e61e95841ea 100644
--- a/ivette/src/dome/src/renderer/frame/toolbars.tsx
+++ b/ivette/src/dome/src/renderer/frame/toolbars.tsx
@@ -8,6 +8,7 @@
  */
 
 import React from 'react';
+import { Event, useEvent, find } from 'dome';
 import { debounce } from 'lodash';
 import { SVG } from 'dome/controls/icons';
 import { Label } from 'dome/controls/labels';
@@ -221,17 +222,24 @@ export interface SearchFieldProps<A> {
   onSearch?: (pattern: string, suggestions: A[]) => void;
   /** Suggestions Callback. */
   onLookup?: (pattern: string) => Promise<Suggestion<A>[]>;
+  /** Triggering Event (defaults to [[Dome.find]]). */
+  event?: null | Event<void>;
 }
 
 /**
    Search Bar.
  */
 export function SearchField<A>(props: SearchFieldProps<A>) {
-  const { onLookup } = props;
+  const { onLookup, event = find } = props;
   const inputRef = React.useRef<HTMLInputElement | null>(null);
+  const blur = () => inputRef.current?.blur();
+  const focus = () => inputRef.current?.focus();
   const [value, setValue] = React.useState('');
   const [items, setItems] = React.useState<Suggestion<A>[]>([]);
 
+  // Find event trigger
+  useEvent(event, focus);
+
   // Lookup trigger
   const triggerLookup = React.useCallback(debounce((pattern: string) => {
     if (onLookup) onLookup(pattern).then(setItems).catch();
@@ -243,8 +251,6 @@ export function SearchField<A>(props: SearchFieldProps<A>) {
     setItems([]);
   };
 
-  const blur = () => inputRef.current?.blur();
-
   // Key Events
   const onKeyUp = (evt: React.KeyboardEvent) => {
     if (evt.key === 'Escape') blur();
-- 
GitLab