diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index d5487d3..8ef5520 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -298,6 +298,10 @@
"AliasTypeIndicator": {
"random": "This is a randomly generated alias",
"custom": "This is a custom-made alias"
+ },
+ "NoSearchResults": {
+ "title": "Nothing found",
+ "description": "We couldn't find anything for your search query. Try again with a different query."
}
},
diff --git a/src/components/NoSearchResults.tsx b/src/components/NoSearchResults.tsx
new file mode 100644
index 0000000..12a0ca9
--- /dev/null
+++ b/src/components/NoSearchResults.tsx
@@ -0,0 +1,25 @@
+import {ReactElement} from "react"
+import {useTranslation} from "react-i18next"
+import {FaQuestion} from "react-icons/fa"
+
+import {Grid, Typography} from "@mui/material"
+
+export default function NoSearchResults(): ReactElement {
+ const {t} = useTranslation()
+
+ return (
+
+
+ {t("components.NoSearchResults.title")}
+
+
+
+
+
+
+ {t("components.NoSearchResults.description")}
+
+
+
+ )
+}
diff --git a/src/components/index.ts b/src/components/index.ts
index 2eb9270..0de4954 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -34,5 +34,7 @@ export * from "./SimpleOverlayInformation"
export {default as SimpleOverlayInformation} from "./SimpleOverlayInformation"
export * from "./SimpleInformationContainer"
export {default as SimpleInformationContainer} from "./SimpleInformationContainer"
+export * from "./NoSearchResults"
+export {default as NoSearchResults} from "./NoSearchResults"
export * as SimplePageBuilder from "./simple-page-builder"
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 02edbd6..b5d3ebc 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -12,3 +12,5 @@ export * from "./use-navigate-to-next"
export {default as useNavigateToNext} from "./use-navigate-to-next"
export * from "./use-error-success-snacks"
export {default as useErrorSuccessSnacks} from "./use-error-success-snacks"
+export * from "./use-is-any-input-focused"
+export {default as useIsAnyInputFocused} from "./use-is-any-input-focused"
diff --git a/src/hooks/use-is-any-input-focused.ts b/src/hooks/use-is-any-input-focused.ts
new file mode 100644
index 0000000..8dbb469
--- /dev/null
+++ b/src/hooks/use-is-any-input-focused.ts
@@ -0,0 +1,21 @@
+import {useCallback, useState} from "react"
+import {useEvent} from "react-use"
+
+export default function useIsAnyInputFocused(): boolean {
+ const [isFocused, setIsFocused] = useState(false)
+
+ const focusHandler = useCallback(event => {
+ const target = event.target as HTMLElement
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA") {
+ setIsFocused(true)
+ }
+ }, [])
+ const blurHandler = useCallback(() => {
+ setIsFocused(false)
+ }, [])
+
+ useEvent("focus", focusHandler, window, {capture: true})
+ useEvent("blur", blurHandler, window, {capture: true})
+
+ return isFocused
+}
diff --git a/src/route-widgets/AliasesRoute/AliasesDetails.tsx b/src/route-widgets/AliasesRoute/AliasesDetails.tsx
index d7cd522..869ae04 100644
--- a/src/route-widgets/AliasesRoute/AliasesDetails.tsx
+++ b/src/route-widgets/AliasesRoute/AliasesDetails.tsx
@@ -17,10 +17,9 @@ import {
import {AliasTypeIndicator} from "~/components"
import {AliasList} from "~/server-types"
-import {useUIState} from "~/hooks"
+import {useIsAnyInputFocused, useUIState} from "~/hooks"
import {SUCCESS_SNACKBAR_SHOW_DURATION} from "~/constants/values"
import CreateAliasButton from "~/route-widgets/AliasesRoute/CreateAliasButton"
-import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen"
export interface AliasesDetailsProps {
aliases: AliasList[]
@@ -31,54 +30,53 @@ const getAddress = (alias: AliasList): string => `${alias.local}@${alias.domain}
export default function AliasesDetails({aliases}: AliasesDetailsProps): ReactElement {
const {t} = useTranslation()
const {enqueueSnackbar} = useSnackbar()
- const [isInCopyAddressMode] = useKeyPress("Control")
+ const [isPressingControl] = useKeyPress("Control")
+ const isAnyInputFocused = useIsAnyInputFocused()
const [aliasesUIState, setAliasesUIState] = useUIState(aliases)
+ const isInCopyAddressMode = !isAnyInputFocused && isPressingControl
+
return (
- {aliasesUIState.length > 0 ? (
-
- {aliasesUIState.map(alias => (
- {
- if (isInCopyAddressMode) {
- event.preventDefault()
- event.stopPropagation()
+
+ {aliasesUIState.map(alias => (
+ {
+ if (isInCopyAddressMode) {
+ event.preventDefault()
+ event.stopPropagation()
- copy(getAddress(alias))
+ copy(getAddress(alias))
- enqueueSnackbar(
- t(
- "relations.alias.mutations.success.addressCopiedToClipboard",
- ),
- {
- variant: "success",
- autoHideDuration: SUCCESS_SNACKBAR_SHOW_DURATION,
- },
- )
- }
- }}
- to={`/aliases/${btoa(getAddress(alias))}`}
- >
-
-
-
-
- {isInCopyAddressMode && (
-
-
-
- )}
-
- ))}
-
- ) : (
-
- )}
+ enqueueSnackbar(
+ t(
+ "relations.alias.mutations.success.addressCopiedToClipboard",
+ ),
+ {
+ variant: "success",
+ autoHideDuration: SUCCESS_SNACKBAR_SHOW_DURATION,
+ },
+ )
+ }
+ }}
+ to={`/aliases/${btoa(getAddress(alias))}`}
+ >
+
+
+
+
+ {isInCopyAddressMode && (
+
+
+
+ )}
+
+ ))}
+
("")
const [queryValue, setQueryValue] = useState("")
const [, startTransition] = useTransition()
+ const [showSearch, setShowSearch] = useState(false)
const query = useQuery, AxiosError>(
["get_aliases", queryValue],
@@ -25,14 +26,22 @@ export default function AliasesRoute(): ReactElement {
getAliases({
query: queryValue,
}),
+ {
+ onSuccess: ({items}) => {
+ if (items.length) {
+ setShowSearch(true)
+ }
+ },
+ },
)
return (
0 && (
+ showSearch && (
{
setSearchValue(event.target.value)
@@ -55,7 +64,19 @@ export default function AliasesRoute(): ReactElement {
}
>
, AxiosError> query={query}>
- {result => }
+ {result =>
+ (() => {
+ if (result.items.length === 0) {
+ if (searchValue === "") {
+ return
+ } else {
+ return
+ }
+ }
+
+ return
+ })()
+ }
)