Fix bugs in dm tab

This commit is contained in:
Ajay Bura 2022-05-04 14:22:16 +05:30
parent b7c322d473
commit 06bae231ef
5 changed files with 86 additions and 110 deletions

View file

@ -56,9 +56,10 @@ function InviteList({ isOpen, onRequestClose }) {
function renderRoomTile(roomId) { function renderRoomTile(roomId) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const myRoom = mx.getRoom(roomId); const myRoom = mx.getRoom(roomId);
if (!myRoom) return null;
const roomName = myRoom.name; const roomName = myRoom.name;
let roomAlias = myRoom.getCanonicalAlias(); let roomAlias = myRoom.getCanonicalAlias();
if (roomAlias === null) roomAlias = myRoom.roomId; if (!roomAlias) roomAlias = myRoom.roomId;
const inviterName = myRoom.getMember(mx.getUserId())?.events?.member?.getSender?.() ?? ''; const inviterName = myRoom.getMember(mx.getUserId())?.events?.member?.getSender?.() ?? '';
return ( return (
<RoomTile <RoomTile
@ -97,12 +98,13 @@ function InviteList({ isOpen, onRequestClose }) {
{ {
Array.from(initMatrix.roomList.inviteDirects).map((roomId) => { Array.from(initMatrix.roomList.inviteDirects).map((roomId) => {
const myRoom = initMatrix.matrixClient.getRoom(roomId); const myRoom = initMatrix.matrixClient.getRoom(roomId);
if (myRoom === null) return null;
const roomName = myRoom.name; const roomName = myRoom.name;
return ( return (
<RoomTile <RoomTile
key={myRoom.roomId} key={myRoom.roomId}
name={roomName} name={roomName}
id={myRoom.getDMInviter()} id={myRoom.getDMInviter() || roomId}
options={ options={
procInvite.has(myRoom.roomId) procInvite.has(myRoom.roomId)
? (<Spinner size="small" />) ? (<Spinner size="small" />)

View file

@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import initMatrix from '../../../client/initMatrix'; import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons'; import cons from '../../../client/state/cons';
@ -9,12 +10,12 @@ import { roomIdByActivity } from '../../../util/sort';
import RoomsCategory from './RoomsCategory'; import RoomsCategory from './RoomsCategory';
const drawerPostie = new Postie(); const drawerPostie = new Postie();
function Directs() { function Directs({ size }) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const { roomList, notifications } = initMatrix; const { roomList, notifications } = initMatrix;
const [directIds, setDirectIds] = useState([]); const [directIds, setDirectIds] = useState([]);
useEffect(() => setDirectIds([...roomList.directs].sort(roomIdByActivity)), []); useEffect(() => setDirectIds([...roomList.directs].sort(roomIdByActivity)), [size]);
useEffect(() => { useEffect(() => {
const handleTimeline = (event, room, toStartOfTimeline, removed, data) => { const handleTimeline = (event, room, toStartOfTimeline, removed, data) => {
@ -63,5 +64,8 @@ function Directs() {
return <RoomsCategory name="People" hideHeader roomIds={directIds} drawerPostie={drawerPostie} />; return <RoomsCategory name="People" hideHeader roomIds={directIds} drawerPostie={drawerPostie} />;
} }
Directs.propTypes = {
size: PropTypes.number.isRequired,
};
export default Directs; export default Directs;

View file

@ -42,12 +42,15 @@ function Drawer() {
const [spaceId] = useSelectedSpace(); const [spaceId] = useSelectedSpace();
const [, forceUpdate] = useForceUpdate(); const [, forceUpdate] = useForceUpdate();
const scrollRef = useRef(null); const scrollRef = useRef(null);
const { roomList } = initMatrix;
useEffect(() => { useEffect(() => {
const { roomList } = initMatrix; const handleUpdate = () => {
roomList.on(cons.events.roomList.ROOMLIST_UPDATED, forceUpdate); forceUpdate();
};
roomList.on(cons.events.roomList.ROOMLIST_UPDATED, handleUpdate);
return () => { return () => {
roomList.removeListener(cons.events.roomList.ROOMLIST_UPDATED, forceUpdate); roomList.removeListener(cons.events.roomList.ROOMLIST_UPDATED, handleUpdate);
}; };
}, []); }, []);
@ -68,7 +71,7 @@ function Drawer() {
{ {
selectedTab !== cons.tabs.DIRECTS selectedTab !== cons.tabs.DIRECTS
? <Home spaceId={spaceId} /> ? <Home spaceId={spaceId} />
: <Directs /> : <Directs size={roomList.directs.size} />
} }
</div> </div>
</ScrollView> </ScrollView>

View file

@ -113,17 +113,20 @@ async function join(roomIdOrAlias, isDM, via) {
* @param {string} roomId * @param {string} roomId
* @param {boolean} isDM * @param {boolean} isDM
*/ */
function leave(roomId) { async function leave(roomId) {
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const isDM = initMatrix.roomList.directs.has(roomId); const isDM = initMatrix.roomList.directs.has(roomId);
mx.leave(roomId) try {
.then(() => { await mx.leave(roomId);
await mx.forget(roomId);
appDispatcher.dispatch({ appDispatcher.dispatch({
type: cons.actions.room.LEAVE, type: cons.actions.room.LEAVE,
roomId, roomId,
isDM, isDM,
}); });
}).catch(); } catch {
console.error('Unable to leave room.');
}
} }
async function create(options, isDM = false) { async function create(options, isDM = false) {

View file

@ -6,6 +6,21 @@ function isMEventSpaceChild(mEvent) {
return mEvent.getType() === 'm.space.child' && Object.keys(mEvent.getContent()).length > 0; return mEvent.getType() === 'm.space.child' && Object.keys(mEvent.getContent()).length > 0;
} }
/**
* @param {() => boolean} callback if return true wait will over else callback will be called again.
* @param {number} timeout timeout to callback
* @param {number} maxTry maximum callback try > 0. -1 means no limit
*/
async function waitFor(callback, timeout = 400, maxTry = -1) {
if (maxTry === 0) return false;
const isOver = async () => new Promise((resolve) => {
setTimeout(() => resolve(callback()), timeout);
});
if (await isOver()) return true;
return waitFor(callback, timeout, maxTry - 1);
}
class RoomList extends EventEmitter { class RoomList extends EventEmitter {
constructor(matrixClient) { constructor(matrixClient) {
super(); super();
@ -228,6 +243,7 @@ class RoomList extends EventEmitter {
} }
_isDMInvite(room) { _isDMInvite(room) {
if (this.mDirects.has(room.roomId)) return true;
const me = room.getMember(this.matrixClient.getUserId()); const me = room.getMember(this.matrixClient.getUserId());
const myEventContent = me.events.member.getContent(); const myEventContent = me.events.member.getContent();
return myEventContent.membership === 'invite' && myEventContent.is_direct; return myEventContent.membership === 'invite' && myEventContent.is_direct;
@ -243,22 +259,11 @@ class RoomList extends EventEmitter {
latestMDirects.forEach((directId) => { latestMDirects.forEach((directId) => {
const myRoom = this.matrixClient.getRoom(directId); const myRoom = this.matrixClient.getRoom(directId);
if (this.mDirects.has(directId)) return; if (this.mDirects.has(directId)) return;
// Update mDirects
this.mDirects.add(directId); this.mDirects.add(directId);
if (myRoom === null) return; if (myRoom === null) return;
if (myRoom.getMyMembership() === 'join') {
if (this._isDMInvite(myRoom)) return;
if (myRoom.getMyMembership === 'join' && !this.directs.has(directId)) {
this.directs.add(directId); this.directs.add(directId);
}
// Newly added room.
// at this time my membership can be invite | join
if (myRoom.getMyMembership() === 'join' && this.rooms.has(directId)) {
// found a DM which accidentally gets added to this.rooms
this.rooms.delete(directId); this.rooms.delete(directId);
this.emit(cons.events.roomList.ROOMLIST_UPDATED); this.emit(cons.events.roomList.ROOMLIST_UPDATED);
} }
@ -298,23 +303,17 @@ class RoomList extends EventEmitter {
} }
}); });
this.matrixClient.on('Room.myMembership', (room, membership, prevMembership) => { this.matrixClient.on('Room.myMembership', async (room, membership, prevMembership) => {
// room => prevMembership = null | invite | join | leave | kick | ban | unban // room => prevMembership = null | invite | join | leave | kick | ban | unban
// room => membership = invite | join | leave | kick | ban | unban // room => membership = invite | join | leave | kick | ban | unban
const { roomId } = room; const { roomId } = room;
const isRoomReady = () => this.matrixClient.getRoom(roomId) !== null;
if (['join', 'invite'].includes(membership) && isRoomReady() === false) {
if (await waitFor(isRoomReady, 200, 100) === false) return;
}
if (membership === 'unban') return; if (membership === 'unban') return;
// When user_reject/sender_undo room invite
if (prevMembership === 'invite') {
if (this.inviteDirects.has(roomId)) this.inviteDirects.delete(roomId);
else if (this.inviteSpaces.has(roomId)) this.inviteSpaces.delete(roomId);
else this.inviteRooms.delete(roomId);
this.emit(cons.events.roomList.INVITELIST_UPDATED, roomId);
}
// When user get invited
if (membership === 'invite') { if (membership === 'invite') {
if (this._isDMInvite(room)) this.inviteDirects.add(roomId); if (this._isDMInvite(room)) this.inviteDirects.add(roomId);
else if (room.isSpaceRoom()) this.inviteSpaces.add(roomId); else if (room.isSpaceRoom()) this.inviteSpaces.add(roomId);
@ -324,13 +323,26 @@ class RoomList extends EventEmitter {
return; return;
} }
// When user join room (first time) or start DM. if (prevMembership === 'invite') {
if ((prevMembership === null || prevMembership === 'invite') && membership === 'join') { if (this.inviteDirects.has(roomId)) this.inviteDirects.delete(roomId);
else if (this.inviteSpaces.has(roomId)) this.inviteSpaces.delete(roomId);
else this.inviteRooms.delete(roomId);
this.emit(cons.events.roomList.INVITELIST_UPDATED, roomId);
}
if (['leave', 'kick', 'ban'].includes(membership)) {
if (this.directs.has(roomId)) this.directs.delete(roomId);
else if (this.spaces.has(roomId)) this.deleteFromSpaces(roomId);
else this.rooms.delete(roomId);
this.emit(cons.events.roomList.ROOM_LEAVED, roomId);
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
return;
}
// when user create room/DM OR accept room/dm invite from this client. // when user create room/DM OR accept room/dm invite from this client.
// we will update this.rooms/this.directs with user action // we will update this.rooms/this.directs with user action
if (this.directs.has(roomId) || this.spaces.has(roomId) || this.rooms.has(roomId)) return; if (membership === 'join' && this.processingRooms.has(roomId)) {
if (this.processingRooms.has(roomId)) {
const procRoomInfo = this.processingRooms.get(roomId); const procRoomInfo = this.processingRooms.get(roomId);
if (procRoomInfo.isDM) this.directs.add(roomId); if (procRoomInfo.isDM) this.directs.add(roomId);
@ -344,68 +356,20 @@ class RoomList extends EventEmitter {
this.processingRooms.delete(roomId); this.processingRooms.delete(roomId);
return; return;
} }
if (room.isSpaceRoom()) {
this.addToSpaces(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId); if (this.mDirects.has(roomId) && membership === 'join') {
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
return;
}
// below code intented to work when user create room/DM
// OR accept room/dm invite from other client.
// and we have to update our client. (it's ok to have 10sec delay)
// create a buffer of 10sec and HOPE client.accoundData get updated
// then accoundData event listener will update this.mDirects.
// and we will be able to know if it's a DM.
// ----------
// less likely situation:
// if we don't get accountData with 10sec then:
// we will temporary add it to this.rooms.
// and in future when accountData get updated
// accountData listener will automatically goona REMOVE it from this.rooms
// and will ADD it to this.directs
// and emit the cons.events.roomList.ROOMLIST_UPDATED to update the UI.
setTimeout(() => {
if (this.directs.has(roomId) || this.spaces.has(roomId) || this.rooms.has(roomId)) return;
if (this.mDirects.has(roomId)) this.directs.add(roomId);
else this.rooms.add(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId);
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
}, 10000);
return;
}
// when room is a DM add/remove it from DM's and return.
if (this.directs.has(roomId)) {
if (membership === 'leave' || membership === 'kick' || membership === 'ban') {
this.directs.delete(roomId);
this.emit(cons.events.roomList.ROOM_LEAVED, roomId);
}
}
if (this.mDirects.has(roomId)) {
if (membership === 'join') {
this.directs.add(roomId); this.directs.add(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId); this.emit(cons.events.roomList.ROOM_JOINED, roomId);
}
this.emit(cons.events.roomList.ROOMLIST_UPDATED); this.emit(cons.events.roomList.ROOMLIST_UPDATED);
return; return;
} }
// when room is not a DM add/remove it from rooms.
if (membership === 'leave' || membership === 'kick' || membership === 'ban') {
if (room.isSpaceRoom()) this.deleteFromSpaces(roomId);
else this.rooms.delete(roomId);
this.emit(cons.events.roomList.ROOM_LEAVED, roomId);
}
if (membership === 'join') { if (membership === 'join') {
if (room.isSpaceRoom()) this.addToSpaces(roomId); if (room.isSpaceRoom()) this.addToSpaces(roomId);
else this.rooms.add(roomId); else this.rooms.add(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId); this.emit(cons.events.roomList.ROOM_JOINED, roomId);
}
this.emit(cons.events.roomList.ROOMLIST_UPDATED); this.emit(cons.events.roomList.ROOMLIST_UPDATED);
}
}); });
} }
} }