Add join with address option (#420, #447)

This commit is contained in:
Ajay Bura 2022-05-03 16:01:50 +05:30
parent 3afc068a02
commit e51fc5a585
8 changed files with 202 additions and 2 deletions

View file

@ -125,7 +125,7 @@ function EmojiVerificationContent({ data, requestClose }) {
return ( return (
<div className="emoji-verification__content"> <div className="emoji-verification__content">
<Text>Click accept to start the verification process</Text> <Text>Click accept to start the verification process.</Text>
<div className="emoji-verification__buttons"> <div className="emoji-verification__buttons">
{ {
process process

View file

@ -0,0 +1,155 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './JoinAlias.scss';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
import { join } from '../../../client/action/room';
import { selectRoom, selectSpace } from '../../../client/action/navigation';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
import Button from '../../atoms/button/Button';
import Input from '../../atoms/input/Input';
import Spinner from '../../atoms/spinner/Spinner';
import Dialog from '../../molecules/dialog/Dialog';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useStore } from '../../hooks/useStore';
const ALIAS_OR_ID_REG = /^[#|!].+:.+\..+$/;
function JoinAliasContent({ term, requestClose }) {
const [process, setProcess] = useState(false);
const [error, setError] = useState(undefined);
const [lastJoinId, setLastJoinId] = useState(undefined);
const mx = initMatrix.matrixClient;
const mountStore = useStore();
const openRoom = (roomId) => {
const room = mx.getRoom(roomId);
if (!room) return;
if (room.isSpaceRoom()) selectSpace(roomId);
else selectRoom(roomId);
requestClose();
};
useEffect(() => {
const handleJoin = (roomId) => {
if (lastJoinId !== roomId) return;
openRoom(roomId);
};
initMatrix.roomList.on(cons.events.roomList.ROOM_JOINED, handleJoin);
return () => {
initMatrix.roomList.removeListener(cons.events.roomList.ROOM_JOINED, handleJoin);
};
}, [lastJoinId]);
const handleSubmit = async (e) => {
e.preventDefault();
mountStore.setItem(true);
const alias = e.target.alias.value;
if (alias?.trim() === '') return;
if (alias.match(ALIAS_OR_ID_REG) === null) {
setError('Invalid address.');
return;
}
setProcess('Looking for address...');
setError(undefined);
let via;
if (alias.startsWith('#')) {
try {
const aliasData = await mx.resolveRoomAlias(alias);
via = aliasData?.servers || [];
if (mountStore.getItem()) {
setProcess(`Joining ${alias}...`);
}
} catch (err) {
if (!mountStore.getItem()) return;
setProcess(false);
setError(`Unable to find room/space with ${alias}. Either room/space is private or doesn't exist.`);
}
}
try {
const roomId = await join(alias, false, via);
if (!mountStore.getItem()) return;
setLastJoinId(roomId);
openRoom(roomId);
} catch {
if (!mountStore.getItem()) return;
setProcess(false);
setError(`Unable to join ${alias}. Either room/space is private or doesn't exist.`);
}
};
return (
<form className="join-alias" onSubmit={handleSubmit}>
<Input
label="Address"
value={term}
name="alias"
required
/>
{error && <Text className="join-alias__error" variant="b3">{error}</Text>}
<div className="join-alias__btn">
{
process
? (
<>
<Spinner size="small" />
<Text>{process}</Text>
</>
)
: <Button variant="primary" type="submit">Join</Button>
}
</div>
</form>
);
}
JoinAliasContent.defaultProps = {
term: undefined,
};
JoinAliasContent.propTypes = {
term: PropTypes.string,
requestClose: PropTypes.func.isRequired,
};
function useWindowToggle() {
const [data, setData] = useState(null);
useEffect(() => {
const handleOpen = (term) => {
setData({ term });
};
navigation.on(cons.events.navigation.JOIN_ALIAS_OPENED, handleOpen);
return () => {
navigation.removeListener(cons.events.navigation.JOIN_ALIAS_OPENED, handleOpen);
};
}, []);
const onRequestClose = () => setData(null);
return [data, onRequestClose];
}
function JoinAlias() {
const [data, requestClose] = useWindowToggle();
return (
<Dialog
isOpen={data !== null}
title={(
<Text variant="s1" weight="medium" primary>Join with address</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip="Close" />}
onRequestClose={requestClose}
>
{ data ? <JoinAliasContent term={data.term} requestClose={requestClose} /> : <div /> }
</Dialog>
);
}
export default JoinAlias;

View file

@ -0,0 +1,20 @@
@use '../../partials/dir';
.join-alias {
padding: var(--sp-normal);
@include dir.side(padding, var(--sp-normal), var(--sp-extra-tight));
& > *:not(:first-child) {
margin-top: var(--sp-normal);
}
&__error {
color: var(--tc-danger-high);
margin-top: var(--sp-extra-tight) !important;
}
&__btn {
display: flex;
gap: var(--sp-normal);
}
}

View file

@ -7,7 +7,7 @@ import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix'; import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons'; import cons from '../../../client/state/cons';
import { import {
openPublicRooms, openCreateRoom, openSpaceManage, openPublicRooms, openCreateRoom, openSpaceManage, openJoinAlias,
openSpaceAddExisting, openInviteUser, openReusableContextMenu, openSpaceAddExisting, openInviteUser, openReusableContextMenu,
} from '../../../client/action/navigation'; } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common'; import { getEventCords } from '../../../util/common';
@ -60,6 +60,14 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
Join public room Join public room
</MenuItem> </MenuItem>
)} )}
{ !spaceId && (
<MenuItem
iconSrc={PlusIC}
onClick={() => { afterOptionSelect(); openJoinAlias(); }}
>
Join with address
</MenuItem>
)}
{ spaceId && ( { spaceId && (
<MenuItem <MenuItem
iconSrc={PlusIC} iconSrc={PlusIC}

View file

@ -7,6 +7,7 @@ import SpaceAddExisting from '../../molecules/space-add-existing/SpaceAddExistin
import Search from '../search/Search'; import Search from '../search/Search';
import ViewSource from '../view-source/ViewSource'; import ViewSource from '../view-source/ViewSource';
import CreateRoom from '../create-room/CreateRoom'; import CreateRoom from '../create-room/CreateRoom';
import JoinAlias from '../join-alias/JoinAlias';
import EmojiVerification from '../emoji-verification/EmojiVerification'; import EmojiVerification from '../emoji-verification/EmojiVerification';
import ReusableDialog from '../../molecules/dialog/ReusableDialog'; import ReusableDialog from '../../molecules/dialog/ReusableDialog';
@ -19,6 +20,7 @@ function Dialogs() {
<ProfileViewer /> <ProfileViewer />
<ShortcutSpaces /> <ShortcutSpaces />
<CreateRoom /> <CreateRoom />
<JoinAlias />
<SpaceAddExisting /> <SpaceAddExisting />
<Search /> <Search />
<EmojiVerification /> <EmojiVerification />

View file

@ -86,6 +86,13 @@ export function openCreateRoom(isSpace = false, parentId = null) {
}); });
} }
export function openJoinAlias(term) {
appDispatcher.dispatch({
type: cons.actions.navigation.OPEN_JOIN_ALIAS,
term,
});
}
export function openInviteUser(roomId, searchTerm) { export function openInviteUser(roomId, searchTerm) {
appDispatcher.dispatch({ appDispatcher.dispatch({
type: cons.actions.navigation.OPEN_INVITE_USER, type: cons.actions.navigation.OPEN_INVITE_USER,

View file

@ -38,6 +38,7 @@ const cons = {
OPEN_INVITE_LIST: 'OPEN_INVITE_LIST', OPEN_INVITE_LIST: 'OPEN_INVITE_LIST',
OPEN_PUBLIC_ROOMS: 'OPEN_PUBLIC_ROOMS', OPEN_PUBLIC_ROOMS: 'OPEN_PUBLIC_ROOMS',
OPEN_CREATE_ROOM: 'OPEN_CREATE_ROOM', OPEN_CREATE_ROOM: 'OPEN_CREATE_ROOM',
OPEN_JOIN_ALIAS: 'OPEN_JOIN_ALIAS',
OPEN_INVITE_USER: 'OPEN_INVITE_USER', OPEN_INVITE_USER: 'OPEN_INVITE_USER',
OPEN_PROFILE_VIEWER: 'OPEN_PROFILE_VIEWER', OPEN_PROFILE_VIEWER: 'OPEN_PROFILE_VIEWER',
OPEN_SETTINGS: 'OPEN_SETTINGS', OPEN_SETTINGS: 'OPEN_SETTINGS',
@ -86,6 +87,7 @@ const cons = {
INVITE_LIST_OPENED: 'INVITE_LIST_OPENED', INVITE_LIST_OPENED: 'INVITE_LIST_OPENED',
PUBLIC_ROOMS_OPENED: 'PUBLIC_ROOMS_OPENED', PUBLIC_ROOMS_OPENED: 'PUBLIC_ROOMS_OPENED',
CREATE_ROOM_OPENED: 'CREATE_ROOM_OPENED', CREATE_ROOM_OPENED: 'CREATE_ROOM_OPENED',
JOIN_ALIAS_OPENED: 'JOIN_ALIAS_OPENED',
INVITE_USER_OPENED: 'INVITE_USER_OPENED', INVITE_USER_OPENED: 'INVITE_USER_OPENED',
SETTINGS_OPENED: 'SETTINGS_OPENED', SETTINGS_OPENED: 'SETTINGS_OPENED',
PROFILE_VIEWER_OPENED: 'PROFILE_VIEWER_OPENED', PROFILE_VIEWER_OPENED: 'PROFILE_VIEWER_OPENED',

View file

@ -122,6 +122,12 @@ class Navigation extends EventEmitter {
action.parentId, action.parentId,
); );
}, },
[cons.actions.navigation.OPEN_JOIN_ALIAS]: () => {
this.emit(
cons.events.navigation.JOIN_ALIAS_OPENED,
action.term,
);
},
[cons.actions.navigation.OPEN_INVITE_USER]: () => { [cons.actions.navigation.OPEN_INVITE_USER]: () => {
this.emit(cons.events.navigation.INVITE_USER_OPENED, action.roomId, action.searchTerm); this.emit(cons.events.navigation.INVITE_USER_OPENED, action.roomId, action.searchTerm);
}, },