diff --git a/src/app/organisms/public-channels/PublicChannels.jsx b/src/app/organisms/public-channels/PublicChannels.jsx index 6527798..2f02ba0 100644 --- a/src/app/organisms/public-channels/PublicChannels.jsx +++ b/src/app/organisms/public-channels/PublicChannels.jsx @@ -20,6 +20,70 @@ import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg'; const SEARCH_LIMIT = 20; +function TryJoinWithAlias({ alias, onRequestClose }) { + const [status, setStatus] = useState({ + isJoining: false, + error: null, + roomId: null, + tempRoomId: null, + }); + function handleOnRoomAdded(roomId) { + if (status.tempRoomId !== null && status.tempRoomId !== roomId) return; + setStatus({ + isJoining: false, error: null, roomId, tempRoomId: null, + }); + } + + useEffect(() => { + initMatrix.roomList.on(cons.events.roomList.ROOM_JOINED, handleOnRoomAdded); + return () => { + initMatrix.roomList.removeListener(cons.events.roomList.ROOM_JOINED, handleOnRoomAdded); + }; + }, [status]); + + async function joinWithAlias() { + setStatus({ + isJoining: true, error: null, roomId: null, tempRoomId: null, + }); + try { + const roomId = await roomActions.join(alias, false); + setStatus({ + isJoining: true, error: null, roomId: null, tempRoomId: roomId, + }); + } catch (e) { + setStatus({ + isJoining: false, + error: `Unable to join ${alias}. Either room is private or doesn't exist.`, + roomId: null, + tempRoomId: null, + }); + } + } + + return ( +
+ {status.roomId === null && !status.isJoining && status.error === null && ( + + )} + {status.isJoining && ( + <> + + {`Joining ${alias}...`} + + )} + {status.roomId !== null && ( + + )} + {status.error !== null && {status.error}} +
+ ); +} + +TryJoinWithAlias.propTypes = { + alias: PropTypes.string.isRequired, + onRequestClose: PropTypes.func.isRequired, +}; + function PublicChannels({ isOpen, onRequestClose }) { const [isSearching, updateIsSearching] = useState(false); const [isViewMore, updateIsViewMore] = useState(false); @@ -33,8 +97,13 @@ function PublicChannels({ isOpen, onRequestClose }) { const userId = initMatrix.matrixClient.getUserId(); async function searchChannels(viewMore) { - let inputHs = hsRef?.current?.value; let inputChannelName = channelNameRef?.current?.value; + let isInputAlias = false; + if (typeof inputChannelName === 'string') { + isInputAlias = inputChannelName[0] === '#' && inputChannelName.indexOf(':') > 1; + } + const hsFromAlias = (isInputAlias) ? inputChannelName.slice(inputChannelName.indexOf(':') + 1) : null; + let inputHs = hsFromAlias || hsRef?.current?.value; if (typeof inputHs !== 'string') inputHs = userId.slice(userId.indexOf(':') + 1); if (typeof inputChannelName !== 'string') inputChannelName = ''; @@ -68,6 +137,12 @@ function PublicChannels({ isOpen, onRequestClose }) { updateNextBatch(result.next_batch); updateIsSearching(false); updateIsViewMore(false); + if (totalChannels.length === 0) { + updateSearchQuery({ + error: `No result found for "${inputChannelName}" on ${inputHs}`, + alias: isInputAlias ? inputChannelName : null, + }); + } } catch (e) { updatePublicChannels([]); updateSearchQuery({ error: 'Something went wrong!' }); @@ -139,7 +214,7 @@ function PublicChannels({ isOpen, onRequestClose }) {
{ e.preventDefault(); searchChannels(); }}>
- +
@@ -169,9 +244,14 @@ function PublicChannels({ isOpen, onRequestClose }) { : {`Search result for "${searchQuery.name}" on ${searchQuery.homeserver}.`} ) } - { - searchQuery.error && {searchQuery.error} - } + { searchQuery.error && ( + <> + {searchQuery.error} + {searchQuery.alias !== null && ( + + )} + + )}
{ publicChannels.length !== 0 && (
diff --git a/src/app/organisms/public-channels/PublicChannels.scss b/src/app/organisms/public-channels/PublicChannels.scss index 21309ab..3eef310 100644 --- a/src/app/organisms/public-channels/PublicChannels.scss +++ b/src/app/organisms/public-channels/PublicChannels.scss @@ -55,6 +55,10 @@ & .donut-spinner { margin: 0 var(--sp-tight); } + + .try-join-with-alias { + margin-top: var(--sp-normal); + } } &__search-error { color: var(--bg-danger); @@ -84,4 +88,13 @@ right: var(--sp-normal); } } +} + +.try-join-with-alias { + display: flex; + align-items: center; + + & >.text:nth-child(2) { + margin: 0 var(--sp-normal); + } } \ No newline at end of file diff --git a/src/client/action/room.js b/src/client/action/room.js index f6a9bab..e18f197 100644 --- a/src/client/action/room.js +++ b/src/client/action/room.js @@ -83,20 +83,24 @@ function guessDMRoomTargetId(room, myUserId) { * @param {string} roomId * @param {boolean} isDM */ -function join(roomId, isDM) { +async function join(roomIdOrAlias, isDM) { const mx = initMatrix.matrixClient; - mx.joinRoom(roomId) - .then(async () => { - if (isDM) { - const targetUserId = guessDMRoomTargetId(mx.getRoom(roomId), mx.getUserId()); - await addRoomToMDirect(roomId, targetUserId); - } - appDispatcher.dispatch({ - type: cons.actions.room.JOIN, - roomId, - isDM, - }); - }).catch(); + try { + const resultRoom = await mx.joinRoom(roomIdOrAlias); + + if (isDM) { + const targetUserId = guessDMRoomTargetId(mx.getRoom(resultRoom.roomId), mx.getUserId()); + await addRoomToMDirect(resultRoom.roomId, targetUserId); + } + appDispatcher.dispatch({ + type: cons.actions.room.JOIN, + roomId: resultRoom.roomId, + isDM, + }); + return resultRoom.roomId; + } catch (e) { + throw new Error(e); + } } /** @@ -104,8 +108,9 @@ function join(roomId, isDM) { * @param {string} roomId * @param {boolean} isDM */ -function leave(roomId, isDM) { +function leave(roomId) { const mx = initMatrix.matrixClient; + const isDM = initMatrix.roomList.directs.has(roomId); mx.leave(roomId) .then(() => { appDispatcher.dispatch({