Extract common search logic

This commit is contained in:
Willian Mitsuda 2021-11-25 06:44:25 -03:00
parent 33939054f2
commit 0b43df6b75
4 changed files with 57 additions and 57 deletions

View File

@ -1,45 +1,18 @@
import React, { useState, useRef, useContext } from "react"; import React, { useState, useContext } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode";
import useKeyboardShortcut from "use-keyboard-shortcut";
import PriceBox from "./PriceBox"; import PriceBox from "./PriceBox";
import SourcifyMenu from "./SourcifyMenu"; import SourcifyMenu from "./SourcifyMenu";
import { RuntimeContext } from "./useRuntime"; import { RuntimeContext } from "./useRuntime";
import { search } from "./search/search"; import { useGenericSearch } from "./search/search";
import Otter from "./otter.jpg"; import Otter from "./otter.jpg";
const CameraScanner = React.lazy(() => import("./search/CameraScanner")); const CameraScanner = React.lazy(() => import("./search/CameraScanner"));
const Title: React.FC = () => { const Header: React.FC = () => {
const { provider } = useContext(RuntimeContext); const { provider } = useContext(RuntimeContext);
const [searchString, setSearchString] = useState<string>(""); const [searchRef, handleChange, handleSubmit] = useGenericSearch();
const [canSubmit, setCanSubmit] = useState<boolean>(false);
const navigate = useNavigate();
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
const searchTerm = e.target.value.trim();
setCanSubmit(searchTerm.length > 0);
setSearchString(searchTerm);
};
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
if (!canSubmit) {
return;
}
if (searchRef.current) {
searchRef.current.value = "";
}
search(searchString, navigate);
};
const searchRef = useRef<HTMLInputElement>(null);
useKeyboardShortcut(["/"], () => {
searchRef.current?.focus();
});
const [isScanning, setScanning] = useState<boolean>(false); const [isScanning, setScanning] = useState<boolean>(false);
return ( return (
@ -97,4 +70,4 @@ const Title: React.FC = () => {
); );
}; };
export default Title; export default Header;

View File

@ -1,5 +1,5 @@
import React, { useState, useContext } from "react"; import React, { useState, useContext } from "react";
import { NavLink, useNavigate } from "react-router-dom"; import { NavLink } from "react-router-dom";
import { commify } from "@ethersproject/units"; import { commify } from "@ethersproject/units";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn"; import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn";
@ -9,30 +9,13 @@ import Timestamp from "./components/Timestamp";
import { RuntimeContext } from "./useRuntime"; import { RuntimeContext } from "./useRuntime";
import { useLatestBlock } from "./useLatestBlock"; import { useLatestBlock } from "./useLatestBlock";
import { blockURL } from "./url"; import { blockURL } from "./url";
import { search } from "./search/search"; import { useGenericSearch } from "./search/search";
const CameraScanner = React.lazy(() => import("./search/CameraScanner")); const CameraScanner = React.lazy(() => import("./search/CameraScanner"));
const Home: React.FC = () => { const Home: React.FC = () => {
const { provider } = useContext(RuntimeContext); const { provider } = useContext(RuntimeContext);
const [searchString, setSearchString] = useState<string>(""); const [searchRef, handleChange, handleSubmit] = useGenericSearch();
const [canSubmit, setCanSubmit] = useState<boolean>(false);
const navigate = useNavigate();
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
const searchTerm = e.target.value.trim();
setCanSubmit(searchTerm.length > 0);
setSearchString(searchTerm);
};
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
if (!canSubmit) {
return;
}
search(searchString, navigate);
};
const latestBlock = useLatestBlock(provider); const latestBlock = useLatestBlock(provider);
const [isScanning, setScanning] = useState<boolean>(false); const [isScanning, setScanning] = useState<boolean>(false);
@ -58,6 +41,7 @@ const Home: React.FC = () => {
size={50} size={50}
placeholder="Search by address / txn hash / block number / ENS name" placeholder="Search by address / txn hash / block number / ENS name"
onChange={handleChange} onChange={handleChange}
ref={searchRef}
autoFocus autoFocus
/> />
<button <button

View File

@ -1,6 +1,6 @@
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import Title from "./Title"; import Header from "./Header";
import { AppConfig, AppConfigContext } from "./useAppConfig"; import { AppConfig, AppConfigContext } from "./useAppConfig";
import { SourcifySource } from "./url"; import { SourcifySource } from "./url";
@ -17,7 +17,7 @@ const Main: React.FC = () => {
return ( return (
<AppConfigContext.Provider value={appConfig}> <AppConfigContext.Provider value={appConfig}>
<Title /> <Header />
<Outlet /> <Outlet />
</AppConfigContext.Provider> </AppConfigContext.Provider>
); );

View File

@ -1,7 +1,15 @@
import {
ChangeEventHandler,
FormEventHandler,
RefObject,
useRef,
useState,
} from "react";
import { NavigateFunction, useNavigate } from "react-router";
import { JsonRpcProvider, TransactionResponse } from "@ethersproject/providers"; import { JsonRpcProvider, TransactionResponse } from "@ethersproject/providers";
import { isAddress } from "@ethersproject/address"; import { isAddress } from "@ethersproject/address";
import { isHexString } from "@ethersproject/bytes"; import { isHexString } from "@ethersproject/bytes";
import { NavigateFunction } from "react-router"; import useKeyboardShortcut from "use-keyboard-shortcut";
import { PAGE_SIZE } from "../params"; import { PAGE_SIZE } from "../params";
import { ProcessedTransaction, TransactionChunk } from "../types"; import { ProcessedTransaction, TransactionChunk } from "../types";
@ -198,7 +206,7 @@ export class SearchController {
} }
} }
export const search = (q: string, navigate: NavigateFunction) => { const doSearch = (q: string, navigate: NavigateFunction) => {
if (isAddress(q)) { if (isAddress(q)) {
navigate(`/address/${q}`, { replace: true }); navigate(`/address/${q}`, { replace: true });
return; return;
@ -218,3 +226,38 @@ export const search = (q: string, navigate: NavigateFunction) => {
// Assume it is an ENS name // Assume it is an ENS name
navigate(`/address/${q}`); navigate(`/address/${q}`);
}; };
export const useGenericSearch = (): [
RefObject<HTMLInputElement>,
ChangeEventHandler<HTMLInputElement>,
FormEventHandler<HTMLFormElement>
] => {
const [searchString, setSearchString] = useState<string>("");
const [canSubmit, setCanSubmit] = useState<boolean>(false);
const navigate = useNavigate();
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
const searchTerm = e.target.value.trim();
setCanSubmit(searchTerm.length > 0);
setSearchString(searchTerm);
};
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
if (!canSubmit) {
return;
}
if (searchRef.current) {
searchRef.current.value = "";
}
doSearch(searchString, navigate);
};
const searchRef = useRef<HTMLInputElement>(null);
useKeyboardShortcut(["/"], () => {
searchRef.current?.focus();
});
return [searchRef, handleChange, handleSubmit];
};