added support for alias search in public channels
authorunknown <ajbura@gmail.com>
Sun, 8 Aug 2021 08:58:22 +0000 (14:28 +0530)
committerunknown <ajbura@gmail.com>
Sun, 8 Aug 2021 08:58:22 +0000 (14:28 +0530)
src/app/organisms/public-channels/PublicChannels.jsx
src/app/organisms/public-channels/PublicChannels.scss
src/client/action/room.js

index 6527798b2b622310dcf207ddb6a85ac88840e244..2f02ba0f139344715d432e7afbdf50270bff9b0c 100644 (file)
@@ -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 (
+    <div className="try-join-with-alias">
+      {status.roomId === null && !status.isJoining && status.error === null && (
+        <Button onClick={() => joinWithAlias()}>{`Try joining ${alias}`}</Button>
+      )}
+      {status.isJoining && (
+        <>
+          <Spinner size="small" />
+          <Text>{`Joining ${alias}...`}</Text>
+        </>
+      )}
+      {status.roomId !== null && (
+        <Button onClick={() => { onRequestClose(); selectRoom(status.roomId); }}>Open</Button>
+      )}
+      {status.error !== null && <Text variant="b2"><span style={{ color: 'var(--bg-danger)' }}>{status.error}</span></Text>}
+    </div>
+  );
+}
+
+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 }) {
       <div className="public-channels">
         <form className="public-channels__form" onSubmit={(e) => { e.preventDefault(); searchChannels(); }}>
           <div className="public-channels__input-wrapper">
-            <Input forwardRef={channelNameRef} label="Channel name" />
+            <Input forwardRef={channelNameRef} label="Channel name or alias" />
             <Input forwardRef={hsRef} value={userId.slice(userId.indexOf(':') + 1)} label="Homeserver" required />
           </div>
           <Button disabled={isSearching} iconSrc={HashSearchIC} variant="primary" type="submit">Search</Button>
@@ -169,9 +244,14 @@ function PublicChannels({ isOpen, onRequestClose }) {
                 : <Text variant="b2">{`Search result for "${searchQuery.name}" on ${searchQuery.homeserver}.`}</Text>
             )
           }
-          {
-            searchQuery.error && <Text className="public-channels__search-error" variant="b2">{searchQuery.error}</Text>
-          }
+          { searchQuery.error && (
+            <>
+              <Text className="public-channels__search-error" variant="b2">{searchQuery.error}</Text>
+              {searchQuery.alias !== null && (
+                <TryJoinWithAlias onRequestClose={onRequestClose} alias={searchQuery.alias} />
+              )}
+            </>
+          )}
         </div>
         { publicChannels.length !== 0 && (
           <div className="public-channels__content">
index 21309ab299351aa596bc0af590a618c11b96d3a3..3eef31017f777babd8b68c642236495c91cae807 100644 (file)
     & .donut-spinner {
       margin: 0 var(--sp-tight);
     }
+
+    .try-join-with-alias {
+      margin-top: var(--sp-normal);
+    }
   }
   &__search-error {
     color: var(--bg-danger);
       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
index f6a9bab3d0c10d64c8a06a01584101f89045b192..e18f1973dd7dd635bb5eb0c9e8808e04a9b3813f 100644 (file)
@@ -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({