diff --git a/src/app/components/join-address-prompt/JoinAddressPrompt.tsx b/src/app/components/join-address-prompt/JoinAddressPrompt.tsx new file mode 100644 index 00000000..50a89418 --- /dev/null +++ b/src/app/components/join-address-prompt/JoinAddressPrompt.tsx @@ -0,0 +1,131 @@ +import React, { FormEventHandler, useState } from 'react'; +import FocusTrap from 'focus-trap-react'; +import { + Dialog, + Overlay, + OverlayCenter, + OverlayBackdrop, + Header, + config, + Box, + Text, + IconButton, + Icon, + Icons, + Button, + Input, + color, +} from 'folds'; +import { stopPropagation } from '../../utils/keyboard'; +import { isRoomAlias, isRoomId } from '../../utils/matrix'; +import { parseMatrixToRoom, parseMatrixToRoomEvent, testMatrixTo } from '../../plugins/matrix-to'; +import { tryDecodeURIComponent } from '../../utils/dom'; + +type JoinAddressProps = { + onOpen: (roomIdOrAlias: string, via?: string[], eventId?: string) => void; + onCancel: () => void; +}; +export function JoinAddressPrompt({ onOpen, onCancel }: JoinAddressProps) { + const [invalid, setInvalid] = useState(false); + + const handleSubmit: FormEventHandler = (evt) => { + evt.preventDefault(); + setInvalid(false); + + const target = evt.target as HTMLFormElement | undefined; + const addressInput = target?.addressInput as HTMLInputElement | undefined; + const address = addressInput?.value.trim(); + if (!address) return; + + if (isRoomId(address) || isRoomAlias(address)) { + onOpen(address); + return; + } + + if (testMatrixTo(address)) { + const decodedAddress = tryDecodeURIComponent(address); + const toRoom = parseMatrixToRoom(decodedAddress); + if (toRoom) { + onOpen(toRoom.roomIdOrAlias, toRoom.viaServers); + return; + } + + const toEvent = parseMatrixToRoomEvent(decodedAddress); + if (toEvent) { + onOpen(toEvent.roomIdOrAlias, toEvent.viaServers, toEvent.eventId); + return; + } + } + + setInvalid(true); + }; + + return ( + }> + + + +
+ + Join with Address + + + + +
+ + + + Enter public address to join the community. Addresses looks like: + + +
  • #community:server
  • +
  • https://matrix.to/#/#community:server
  • +
  • https://matrix.to/#/!xYzAj?via=server
  • +
    +
    + + Address + + {invalid && ( + + Invalid Address + + )} + + +
    +
    +
    +
    +
    + ); +} diff --git a/src/app/components/join-address-prompt/index.ts b/src/app/components/join-address-prompt/index.ts new file mode 100644 index 00000000..b14b8a61 --- /dev/null +++ b/src/app/components/join-address-prompt/index.ts @@ -0,0 +1 @@ +export * from './JoinAddressPrompt'; diff --git a/src/app/pages/client/home/Home.tsx b/src/app/pages/client/home/Home.tsx index d2333919..2597bb73 100644 --- a/src/app/pages/client/home/Home.tsx +++ b/src/app/pages/client/home/Home.tsx @@ -30,10 +30,12 @@ import { NavLink, } from '../../../components/nav'; import { + encodeSearchParamValueArray, getExplorePath, getHomeCreatePath, getHomeRoomPath, getHomeSearchPath, + withSearchParam, } from '../../pathUtils'; import { getCanonicalAliasOrRoomId } from '../../../utils/matrix'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; @@ -49,7 +51,6 @@ import { makeNavCategoryId } from '../../../state/closedNavCategories'; import { roomToUnreadAtom } from '../../../state/room/roomToUnread'; import { useCategoryHandler } from '../../../hooks/useCategoryHandler'; import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper'; -import { openJoinAlias } from '../../../../client/action/navigation'; import { PageNav, PageNavHeader, PageNavContent } from '../../../components/page'; import { useRoomsUnread } from '../../../state/hooks/unread'; import { markAsRead } from '../../../../client/action/notifications'; @@ -61,6 +62,9 @@ import { getRoomNotificationMode, useRoomsNotificationPreferencesContext, } from '../../../hooks/useRoomsNotificationPreferences'; +import { UseStateProvider } from '../../../components/UseStateProvider'; +import { JoinAddressPrompt } from '../../../components/join-address-prompt'; +import { _RoomSearchParams } from '../../paths'; type HomeMenuProps = { requestClose: () => void; @@ -77,11 +81,6 @@ const HomeMenu = forwardRef(({ requestClose }, re requestClose(); }; - const handleJoinAddress = () => { - openJoinAlias(); - requestClose(); - }; - return ( @@ -96,16 +95,6 @@ const HomeMenu = forwardRef(({ requestClose }, re Mark as Read - } - > - - Join with Address - - ); @@ -268,22 +257,44 @@ export function Home() { - - openJoinAlias()}> - - - - - - - - Join with Address - - - - - - + + {(open, setOpen) => ( + <> + + setOpen(true)}> + + + + + + + + Join with Address + + + + + + + {open && ( + setOpen(false)} + onOpen={(roomIdOrAlias, viaServers, eventId) => { + setOpen(false); + const path = getHomeRoomPath(roomIdOrAlias, eventId); + navigate( + viaServers + ? withSearchParam<_RoomSearchParams>(path, { + viaServers: encodeSearchParamValueArray(viaServers), + }) + : path + ); + }} + /> + )} + + )} + diff --git a/src/app/pages/client/sidebar/CreateTab.tsx b/src/app/pages/client/sidebar/CreateTab.tsx index a7f9350c..e6575cb4 100644 --- a/src/app/pages/client/sidebar/CreateTab.tsx +++ b/src/app/pages/client/sidebar/CreateTab.tsx @@ -7,15 +7,22 @@ import { stopPropagation } from '../../../utils/keyboard'; import { SequenceCard } from '../../../components/sequence-card'; import { SettingTile } from '../../../components/setting-tile'; import { ContainerColor } from '../../../styles/ContainerColor.css'; -import { openJoinAlias } from '../../../../client/action/navigation'; -import { getCreatePath } from '../../pathUtils'; +import { + encodeSearchParamValueArray, + getCreatePath, + getSpacePath, + withSearchParam, +} from '../../pathUtils'; import { useCreateSelected } from '../../../hooks/router/useCreateSelected'; +import { JoinAddressPrompt } from '../../../components/join-address-prompt'; +import { _RoomSearchParams } from '../../paths'; export function CreateTab() { const createSelected = useCreateSelected(); const navigate = useNavigate(); const [menuCords, setMenuCords] = useState(); + const [joinAddress, setJoinAddress] = useState(false); const handleMenu: MouseEventHandler = (evt) => { setMenuCords(menuCords ? undefined : evt.currentTarget.getBoundingClientRect()); @@ -27,7 +34,7 @@ export function CreateTab() { }; const handleJoinWithAddress = () => { - openJoinAlias(); + setJoinAddress(true); setMenuCords(undefined); }; @@ -103,6 +110,22 @@ export function CreateTab() { > + {joinAddress && ( + setJoinAddress(false)} + onOpen={(roomIdOrAlias, viaServers) => { + setJoinAddress(false); + const path = getSpacePath(roomIdOrAlias); + navigate( + viaServers + ? withSearchParam<_RoomSearchParams>(path, { + viaServers: encodeSearchParamValueArray(viaServers), + }) + : path + ); + }} + /> + )} )}