fixed latest alias passing between extension and instance

This commit is contained in:
Myzel394 2022-12-18 16:06:36 +01:00
parent c71c36fcc5
commit 46f9b4b526
4 changed files with 88 additions and 28 deletions

View File

@ -1,29 +1,37 @@
interface ExtensionKleckMessagePasswordStatus { export interface ExtensionKleckMessagePasswordStatus {
type: "password-status" type: "password-status"
} }
interface ExtensionKleckMessageAskForPassword { export interface ExtensionKleckMessageAskForPassword {
type: "ask-for-password" type: "ask-for-password"
} }
interface ExtensionKleckMessageUser { export interface ExtensionKleckMessageUser {
type: "get-user" type: "get-user"
} }
interface ExtensionKleckMessageEnterPassword { export interface ExtensionKleckMessageEnterPassword {
type: "enter-password" type: "enter-password"
} }
interface ExtensionKleckMessageRefetchAliases { export interface ExtensionKleckMessageRefetchAliases {
type: "refetch-aliases" type: "refetch-aliases"
} }
export interface ExtensionKleckMessageLatestAlias {
type: "latest-alias"
data: {
latestAliasId: string
}
}
export type ExtensionKleckMessage = export type ExtensionKleckMessage =
| ExtensionKleckMessagePasswordStatus | ExtensionKleckMessagePasswordStatus
| ExtensionKleckMessageAskForPassword | ExtensionKleckMessageAskForPassword
| ExtensionKleckMessageUser | ExtensionKleckMessageUser
| ExtensionKleckMessageEnterPassword | ExtensionKleckMessageEnterPassword
| ExtensionKleckMessageRefetchAliases | ExtensionKleckMessageRefetchAliases
| ExtensionKleckMessageLatestAlias
export type ExtensionKleckEvent = MessageEvent & { export type ExtensionKleckEvent = MessageEvent & {
detail: ExtensionKleckMessage detail: ExtensionKleckMessage

View File

@ -1,22 +1,33 @@
import {useCallback} from "react" import {useCallback} from "react"
import {useEvent} from "react-use" import {useEvent} from "react-use"
import {ExtensionKleckEvent} from "~/extension-types" import {ExtensionKleckEvent, ExtensionKleckMessageLatestAlias} from "~/extension-types"
export interface UseExtensionHandlerData { export interface UseExtensionHandlerData {
onEnterPassword?: () => void onEnterPassword?: () => void
onRefetchAliases?: () => void
onLatestAliasChange?: ({latestAliasId}: ExtensionKleckMessageLatestAlias["data"]) => void
} }
export default function useExtensionHandler({onEnterPassword}: UseExtensionHandlerData): void { export default function useExtensionHandler({
onEnterPassword,
onRefetchAliases,
onLatestAliasChange,
}: UseExtensionHandlerData): void {
const handleExtensionEvent = useCallback( const handleExtensionEvent = useCallback(
(event: ExtensionKleckEvent) => { (event: ExtensionKleckEvent) => {
switch (event.detail.type) { switch (event.detail.type) {
case "enter-password": case "enter-password":
onEnterPassword?.() onEnterPassword?.()
break break
case "refetch-aliases":
onRefetchAliases?.()
break
case "latest-alias":
onLatestAliasChange?.(event.detail.data)
} }
}, },
[onEnterPassword], [onEnterPassword, onRefetchAliases, onLatestAliasChange],
) )
useEvent("kleckrelay-kleck", handleExtensionEvent) useEvent("kleckrelay-kleck", handleExtensionEvent)

View File

@ -1,5 +1,5 @@
import {ReactElement} from "react" import {ReactElement} from "react"
import {MdContentCopy} from "react-icons/md" import {MdContentCopy, MdExtension} from "react-icons/md"
import {Link as RouterLink} from "react-router-dom" import {Link as RouterLink} from "react-router-dom"
import {ListItemButton, ListItemIcon, ListItemSecondaryAction, ListItemText} from "@mui/material" import {ListItemButton, ListItemIcon, ListItemSecondaryAction, ListItemText} from "@mui/material"
@ -9,12 +9,18 @@ import {AliasList} from "~/server-types"
export interface AliasesListItemProps { export interface AliasesListItemProps {
alias: AliasList alias: AliasList
showExtensionIcon?: boolean
onCopy?: (address: string) => void onCopy?: (address: string) => void
} }
const getAddress = (alias: AliasList): string => `${alias.local}@${alias.domain}` const getAddress = (alias: AliasList): string => `${alias.local}@${alias.domain}`
export default function AliasesListItem({alias, onCopy}: AliasesListItemProps): ReactElement { export default function AliasesListItem({
alias,
showExtensionIcon,
onCopy,
}: AliasesListItemProps): ReactElement {
const isInCopyAddressMode = onCopy !== undefined const isInCopyAddressMode = onCopy !== undefined
const address = getAddress(alias) const address = getAddress(alias)
@ -44,11 +50,19 @@ export default function AliasesListItem({alias, onCopy}: AliasesListItemProps):
</> </>
} }
/> />
{isInCopyAddressMode && ( {(() => {
<ListItemSecondaryAction> if (isInCopyAddressMode) {
<MdContentCopy /> return (
</ListItemSecondaryAction> <ListItemSecondaryAction>
)} <MdContentCopy />
</ListItemSecondaryAction>
)
}
if (showExtensionIcon) {
return <MdExtension />
}
})()}
</ListItemButton> </ListItemButton>
) )
} }

View File

@ -1,21 +1,11 @@
import {ReactElement, useState, useTransition} from "react" import {ReactElement, useCallback, useEffect, useState, useTransition} from "react"
import {AxiosError} from "axios" import {AxiosError} from "axios"
import {MdSearch} from "react-icons/md" import {MdSearch} from "react-icons/md"
import {useTranslation} from "react-i18next" import {useTranslation} from "react-i18next"
import {useCopyToClipboard, useKeyPress, useUpdateEffect} from "react-use" import {useCopyToClipboard, useKeyPress, useUpdateEffect} from "react-use"
import {useQuery} from "@tanstack/react-query" import {useQuery} from "@tanstack/react-query"
import { import {Alert, Chip, Grid, InputAdornment, List, Snackbar, TextField} from "@mui/material"
Alert,
Chip,
Divider,
Grid,
InputAdornment,
List,
Snackbar,
TextField,
ToggleButton,
} from "@mui/material"
import {AliasList, AliasType, PaginationResult} from "~/server-types" import {AliasList, AliasType, PaginationResult} from "~/server-types"
import { import {
@ -26,8 +16,9 @@ import {
SimplePage, SimplePage,
SuccessSnack, SuccessSnack,
} from "~/components" } from "~/components"
import {useIsAnyInputFocused} from "~/hooks" import {useExtensionHandler, useIsAnyInputFocused, useWindowVisible} from "~/hooks"
import {CreateAliasButton} from "~/route-widgets/AliasesRoute/CreateAliasButton" import {CreateAliasButton} from "~/route-widgets/AliasesRoute/CreateAliasButton"
import {ExtensionKleckMessageLatestAlias} from "~/extension-types"
import AliasesListItem from "~/route-widgets/AliasesRoute/AliasesListItem" import AliasesListItem from "~/route-widgets/AliasesRoute/AliasesListItem"
import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen" import EmptyStateScreen from "~/route-widgets/AliasesRoute/EmptyStateScreen"
import getAliases from "~/apis/get-aliases" import getAliases from "~/apis/get-aliases"
@ -59,6 +50,8 @@ export default function AliasesRoute(): ReactElement {
const isAnyInputFocused = useIsAnyInputFocused() const isAnyInputFocused = useIsAnyInputFocused()
const [lockDisabledCopyMode, setLockDisabledCopyMode] = useState<boolean>(false) const [lockDisabledCopyMode, setLockDisabledCopyMode] = useState<boolean>(false)
const isInCopyAddressMode = !isAnyInputFocused && !lockDisabledCopyMode && isPressingControl const isInCopyAddressMode = !isAnyInputFocused && !lockDisabledCopyMode && isPressingControl
const [latestAliasId, setLatestAliasId] = useState<string | null>(null)
const isVisible = useWindowVisible()
const query = useQuery<PaginationResult<AliasList>, AxiosError>( const query = useQuery<PaginationResult<AliasList>, AxiosError>(
["get_aliases", {queryValue, searchFilter, typeFilter}], ["get_aliases", {queryValue, searchFilter, typeFilter}],
@ -97,12 +90,45 @@ export default function AliasesRoute(): ReactElement {
}, },
) )
const updateLatestAliasId = useCallback(
({latestAliasId}: ExtensionKleckMessageLatestAlias["data"]) => {
setLatestAliasId(latestAliasId)
},
[],
)
useExtensionHandler({
onLatestAliasChange: updateLatestAliasId,
onRefetchAliases: query.refetch,
})
useUpdateEffect(() => { useUpdateEffect(() => {
if (!isPressingControl) { if (!isPressingControl) {
setLockDisabledCopyMode(false) setLockDisabledCopyMode(false)
} }
}, [isPressingControl]) }, [isPressingControl])
useUpdateEffect(() => {
if (!query.data) {
return
}
// If `latestAliasId` is not present in the current query result, then
// we need to refetch the query to get the latest alias.
if (!query.data.items.some(({id}) => id === latestAliasId)) {
query.refetch()
}
}, [latestAliasId])
useEffect(() => {
window.dispatchEvent(
new CustomEvent("kleckrelay-blob", {
detail: {
type: "get-latest-alias",
},
}),
)
}, [isVisible])
return ( return (
<SimplePage <SimplePage
title={t("routes.AliasesRoute.title")} title={t("routes.AliasesRoute.title")}
@ -260,6 +286,7 @@ export default function AliasesRoute(): ReactElement {
<AliasesListItem <AliasesListItem
alias={alias} alias={alias}
key={alias.id} key={alias.id}
showExtensionIcon={alias.id === latestAliasId}
onCopy={ onCopy={
isInCopyAddressMode isInCopyAddressMode
? alias => { ? alias => {