Use hook to bind atoms with sdk
This commit is contained in:
parent
67cd2fc5c4
commit
147a6065d0
9 changed files with 356 additions and 158 deletions
63
src/app/state/hooks/inviteList.ts
Normal file
63
src/app/state/hooks/inviteList.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { useAtomValue, WritableAtom } from 'jotai';
|
||||
import { selectAtom } from 'jotai/utils';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import { useCallback } from 'react';
|
||||
import { isDirectInvite, isRoom, isSpace, isUnsupportedRoom } from '../../utils/room';
|
||||
import { compareRoomsEqual, RoomsAction } from '../utils';
|
||||
import { MDirectAction } from '../mDirectList';
|
||||
|
||||
export const useSpaceInvites = (
|
||||
mx: MatrixClient,
|
||||
allInvitesAtom: WritableAtom<string[], RoomsAction>
|
||||
) => {
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) => rooms.filter((roomId) => isSpace(mx.getRoom(roomId))),
|
||||
[mx]
|
||||
);
|
||||
return useAtomValue(selectAtom(allInvitesAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useRoomInvites = (
|
||||
mx: MatrixClient,
|
||||
allInvitesAtom: WritableAtom<string[], RoomsAction>,
|
||||
mDirectAtom: WritableAtom<Set<string>, MDirectAction>
|
||||
) => {
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) =>
|
||||
rooms.filter(
|
||||
(roomId) =>
|
||||
isRoom(mx.getRoom(roomId)) &&
|
||||
!(mDirects.has(roomId) || isDirectInvite(mx.getRoom(roomId), mx.getUserId()))
|
||||
),
|
||||
[mx, mDirects]
|
||||
);
|
||||
return useAtomValue(selectAtom(allInvitesAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useDirectInvites = (
|
||||
mx: MatrixClient,
|
||||
allInvitesAtom: WritableAtom<string[], RoomsAction>,
|
||||
mDirectAtom: WritableAtom<Set<string>, MDirectAction>
|
||||
) => {
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) =>
|
||||
rooms.filter(
|
||||
(roomId) => mDirects.has(roomId) || isDirectInvite(mx.getRoom(roomId), mx.getUserId())
|
||||
),
|
||||
[mx, mDirects]
|
||||
);
|
||||
return useAtomValue(selectAtom(allInvitesAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useUnsupportedInvites = (
|
||||
mx: MatrixClient,
|
||||
allInvitesAtom: WritableAtom<string[], RoomsAction>
|
||||
) => {
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) => rooms.filter((roomId) => isUnsupportedRoom(mx.getRoom(roomId))),
|
||||
[mx]
|
||||
);
|
||||
return useAtomValue(selectAtom(allInvitesAtom, selector, compareRoomsEqual));
|
||||
};
|
54
src/app/state/hooks/roomList.ts
Normal file
54
src/app/state/hooks/roomList.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { useAtomValue, WritableAtom } from 'jotai';
|
||||
import { selectAtom } from 'jotai/utils';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import { useCallback } from 'react';
|
||||
import { isRoom, isSpace, isUnsupportedRoom } from '../../utils/room';
|
||||
import { compareRoomsEqual, RoomsAction } from '../utils';
|
||||
import { MDirectAction } from '../mDirectList';
|
||||
|
||||
export const useSpaces = (mx: MatrixClient, allRoomsAtom: WritableAtom<string[], RoomsAction>) => {
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) => rooms.filter((roomId) => isSpace(mx.getRoom(roomId))),
|
||||
[mx]
|
||||
);
|
||||
return useAtomValue(selectAtom(allRoomsAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useRooms = (
|
||||
mx: MatrixClient,
|
||||
allRoomsAtom: WritableAtom<string[], RoomsAction>,
|
||||
mDirectAtom: WritableAtom<Set<string>, MDirectAction>
|
||||
) => {
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) =>
|
||||
rooms.filter((roomId) => isRoom(mx.getRoom(roomId)) && !mDirects.has(roomId)),
|
||||
[mx, mDirects]
|
||||
);
|
||||
return useAtomValue(selectAtom(allRoomsAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useDirects = (
|
||||
mx: MatrixClient,
|
||||
allRoomsAtom: WritableAtom<string[], RoomsAction>,
|
||||
mDirectAtom: WritableAtom<Set<string>, MDirectAction>
|
||||
) => {
|
||||
const mDirects = useAtomValue(mDirectAtom);
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) =>
|
||||
rooms.filter((roomId) => isRoom(mx.getRoom(roomId)) && mDirects.has(roomId)),
|
||||
[mx, mDirects]
|
||||
);
|
||||
return useAtomValue(selectAtom(allRoomsAtom, selector, compareRoomsEqual));
|
||||
};
|
||||
|
||||
export const useUnsupportedRooms = (
|
||||
mx: MatrixClient,
|
||||
allRoomsAtom: WritableAtom<string[], RoomsAction>
|
||||
) => {
|
||||
const selector = useCallback(
|
||||
(rooms: string[]) => rooms.filter((roomId) => isUnsupportedRoom(mx.getRoom(roomId))),
|
||||
[mx]
|
||||
);
|
||||
return useAtomValue(selectAtom(allRoomsAtom, selector, compareRoomsEqual));
|
||||
};
|
|
@ -1,32 +1,32 @@
|
|||
import { atom } from 'jotai';
|
||||
import { mx } from '../../client/mx';
|
||||
import { atom, WritableAtom } from 'jotai';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { Membership } from '../../types/matrix/room';
|
||||
import { isDirectInvite, isRoom, isSpace, isUnsupportedRoom } from '../utils/room';
|
||||
import { mDirectAtom } from './mDirectList';
|
||||
import { atomRoomsWithMemberships } from './utils';
|
||||
import { RoomsAction, useBindRoomsWithMembershipsAtom } from './utils';
|
||||
|
||||
export const allInvitesAtom = atom<string[]>([]);
|
||||
allInvitesAtom.onMount = (setAtom) => atomRoomsWithMemberships(setAtom, mx(), [Membership.Invite]);
|
||||
|
||||
export const spaceInvitesAtom = atom((get) =>
|
||||
get(allInvitesAtom).filter((roomId) => isSpace(mx().getRoom(roomId)))
|
||||
const baseRoomsAtom = atom<string[]>([]);
|
||||
export const allInvitesAtom = atom<string[], RoomsAction>(
|
||||
(get) => get(baseRoomsAtom),
|
||||
(get, set, action) => {
|
||||
if (action.type === 'INITIALIZE') {
|
||||
set(baseRoomsAtom, action.rooms);
|
||||
return;
|
||||
}
|
||||
set(baseRoomsAtom, (ids) => {
|
||||
const newIds = ids.filter((id) => id !== action.roomId);
|
||||
if (action.type === 'PUT') newIds.push(action.roomId);
|
||||
return newIds;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export const roomInvitesAtom = atom((get) =>
|
||||
get(allInvitesAtom).filter(
|
||||
(roomId) =>
|
||||
isRoom(mx().getRoom(roomId)) &&
|
||||
!(get(mDirectAtom).has(roomId) || isDirectInvite(mx().getRoom(roomId), mx().getUserId()))
|
||||
)
|
||||
);
|
||||
|
||||
export const directInvitesAtom = atom((get) =>
|
||||
get(allInvitesAtom).filter(
|
||||
(roomId) =>
|
||||
get(mDirectAtom).has(roomId) || isDirectInvite(mx().getRoom(roomId), mx().getUserId())
|
||||
)
|
||||
);
|
||||
|
||||
export const unsupportedInvitesAtom = atom((get) =>
|
||||
get(allInvitesAtom).filter((roomId) => isUnsupportedRoom(mx().getRoom(roomId)))
|
||||
);
|
||||
export const useBindAllInvitesAtom = (
|
||||
mx: MatrixClient,
|
||||
allRooms: WritableAtom<string[], RoomsAction>
|
||||
) => {
|
||||
useBindRoomsWithMembershipsAtom(
|
||||
mx,
|
||||
allRooms,
|
||||
useMemo(() => [Membership.Invite], [])
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,20 +1,47 @@
|
|||
import { atom } from 'jotai';
|
||||
import { ClientEvent, MatrixEvent } from 'matrix-js-sdk';
|
||||
import { mx } from '../../client/mx';
|
||||
import { atom, useSetAtom, WritableAtom } from 'jotai';
|
||||
import { ClientEvent, MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
||||
import { useEffect } from 'react';
|
||||
import { AccountDataEvent } from '../../types/matrix/accountData';
|
||||
import { getAccountData, getMDirects } from '../utils/room';
|
||||
|
||||
export const mDirectAtom = atom(new Set<string>());
|
||||
mDirectAtom.onMount = (setAtom) => {
|
||||
const mDirectEvent = getAccountData(mx(), AccountDataEvent.Direct);
|
||||
if (mDirectEvent) setAtom(getMDirects(mDirectEvent));
|
||||
|
||||
const handleAccountData = (event: MatrixEvent) => {
|
||||
setAtom(getMDirects(event));
|
||||
};
|
||||
|
||||
mx().on(ClientEvent.AccountData, handleAccountData);
|
||||
return () => {
|
||||
mx().removeListener(ClientEvent.AccountData, handleAccountData);
|
||||
};
|
||||
export type MDirectAction = {
|
||||
type: 'INITIALIZE' | 'UPDATE';
|
||||
rooms: Set<string>;
|
||||
};
|
||||
|
||||
const baseMDirectAtom = atom(new Set<string>());
|
||||
export const mDirectAtom = atom<Set<string>, MDirectAction>(
|
||||
(get) => get(baseMDirectAtom),
|
||||
(get, set, action) => {
|
||||
set(baseMDirectAtom, action.rooms);
|
||||
}
|
||||
);
|
||||
|
||||
export const useBindMDirectAtom = (
|
||||
mx: MatrixClient,
|
||||
mDirect: WritableAtom<Set<string>, MDirectAction>
|
||||
) => {
|
||||
const setMDirect = useSetAtom(mDirect);
|
||||
|
||||
useEffect(() => {
|
||||
const mDirectEvent = getAccountData(mx, AccountDataEvent.Direct);
|
||||
if (mDirectEvent) {
|
||||
setMDirect({
|
||||
type: 'INITIALIZE',
|
||||
rooms: getMDirects(mDirectEvent),
|
||||
});
|
||||
}
|
||||
|
||||
const handleAccountData = (event: MatrixEvent) => {
|
||||
setMDirect({
|
||||
type: 'UPDATE',
|
||||
rooms: getMDirects(event),
|
||||
});
|
||||
};
|
||||
|
||||
mx.on(ClientEvent.AccountData, handleAccountData);
|
||||
return () => {
|
||||
mx.removeListener(ClientEvent.AccountData, handleAccountData);
|
||||
};
|
||||
}, [mx, setMDirect]);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useEffect } from 'react';
|
|||
import { MuteChanges } from '../../types/matrix/room';
|
||||
import { findMutedRule, isMutedRule } from '../utils/room';
|
||||
|
||||
type MutedRoomsUpdate =
|
||||
export type MutedRoomsUpdate =
|
||||
| {
|
||||
type: 'INITIALIZE';
|
||||
addRooms: string[];
|
||||
|
|
|
@ -1,27 +1,31 @@
|
|||
import { atom } from 'jotai';
|
||||
import { mx } from '../../client/mx';
|
||||
import { atom, WritableAtom } from 'jotai';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { Membership } from '../../types/matrix/room';
|
||||
import { isRoom, isSpace, isUnsupportedRoom } from '../utils/room';
|
||||
import { mDirectAtom } from './mDirectList';
|
||||
import { atomRoomsWithMemberships } from './utils';
|
||||
import { RoomsAction, useBindRoomsWithMembershipsAtom } from './utils';
|
||||
|
||||
export const allRoomsAtom = atom<string[]>([]);
|
||||
allRoomsAtom.onMount = (setAtom) => atomRoomsWithMemberships(setAtom, mx(), [Membership.Join]);
|
||||
|
||||
export const spacesAtom = atom((get) =>
|
||||
get(allRoomsAtom).filter((roomId) => isSpace(mx().getRoom(roomId)))
|
||||
);
|
||||
|
||||
export const roomsAtom = atom((get) =>
|
||||
get(allRoomsAtom).filter(
|
||||
(roomId) => isRoom(mx().getRoom(roomId)) && !get(mDirectAtom).has(roomId)
|
||||
)
|
||||
);
|
||||
|
||||
export const directsAtom = atom((get) =>
|
||||
get(allRoomsAtom).filter((roomId) => isRoom(mx().getRoom(roomId)) && get(mDirectAtom).has(roomId))
|
||||
);
|
||||
|
||||
export const unsupportedRoomsAtom = atom((get) =>
|
||||
get(allRoomsAtom).filter((roomId) => isUnsupportedRoom(mx().getRoom(roomId)))
|
||||
const baseRoomsAtom = atom<string[]>([]);
|
||||
export const allRoomsAtom = atom<string[], RoomsAction>(
|
||||
(get) => get(baseRoomsAtom),
|
||||
(get, set, action) => {
|
||||
if (action.type === 'INITIALIZE') {
|
||||
set(baseRoomsAtom, action.rooms);
|
||||
return;
|
||||
}
|
||||
set(baseRoomsAtom, (ids) => {
|
||||
const newIds = ids.filter((id) => id !== action.roomId);
|
||||
if (action.type === 'PUT') newIds.push(action.roomId);
|
||||
return newIds;
|
||||
});
|
||||
}
|
||||
);
|
||||
export const useBindAllRoomsAtom = (
|
||||
mx: MatrixClient,
|
||||
allRooms: WritableAtom<string[], RoomsAction>
|
||||
) => {
|
||||
useBindRoomsWithMembershipsAtom(
|
||||
mx,
|
||||
allRooms,
|
||||
useMemo(() => [Membership.Join], [])
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
import produce from 'immer';
|
||||
import { atom } from 'jotai';
|
||||
import { ClientEvent, MatrixEvent, Room, RoomEvent, RoomStateEvent } from 'matrix-js-sdk';
|
||||
import { mx } from '../../client/mx';
|
||||
import { atom, useSetAtom, WritableAtom } from 'jotai';
|
||||
import {
|
||||
ClientEvent,
|
||||
MatrixClient,
|
||||
MatrixEvent,
|
||||
Room,
|
||||
RoomEvent,
|
||||
RoomStateEvent,
|
||||
} from 'matrix-js-sdk';
|
||||
import { useEffect } from 'react';
|
||||
import { Membership, RoomToParents, StateEvent } from '../../types/matrix/room';
|
||||
import {
|
||||
getRoomToParents,
|
||||
|
@ -11,69 +18,103 @@ import {
|
|||
mapParentWithChildren,
|
||||
} from '../utils/room';
|
||||
|
||||
export const roomToParentsAtom = atom<RoomToParents>(new Map());
|
||||
roomToParentsAtom.onMount = (setAtom) => {
|
||||
setAtom(getRoomToParents(mx()));
|
||||
|
||||
const deleteFromAtom = (roomId: string) => {
|
||||
setAtom(
|
||||
produce((roomToParents) => {
|
||||
const noParentRooms: string[] = [];
|
||||
roomToParents.delete(roomId);
|
||||
roomToParents.forEach((parents, child) => {
|
||||
parents.delete(roomId);
|
||||
if (parents.size === 0) noParentRooms.push(child);
|
||||
});
|
||||
noParentRooms.forEach((room) => roomToParents.delete(room));
|
||||
return roomToParents;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const addToAtom = (parent: string, children: string[]) => {
|
||||
setAtom(
|
||||
produce((roomToParents) => {
|
||||
mapParentWithChildren(roomToParents, parent, children);
|
||||
return roomToParents;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleAddRoom = (room: Room) => {
|
||||
if (isSpace(room) && room.getMyMembership() !== Membership.Invite) {
|
||||
addToAtom(room.roomId, getSpaceChildren(room));
|
||||
export type RoomToParentsAction =
|
||||
| {
|
||||
type: 'INITIALIZE';
|
||||
roomToParents: RoomToParents;
|
||||
}
|
||||
};
|
||||
|
||||
const handleMembershipChange = (room: Room, membership: string) => {
|
||||
if (isSpace(room) && membership === Membership.Join) {
|
||||
addToAtom(room.roomId, getSpaceChildren(room));
|
||||
| {
|
||||
type: 'PUT';
|
||||
parent: string;
|
||||
children: string[];
|
||||
}
|
||||
};
|
||||
| {
|
||||
type: 'DELETE';
|
||||
roomId: string;
|
||||
};
|
||||
|
||||
const handleStateChange = (mEvent: MatrixEvent) => {
|
||||
if (mEvent.getType() === StateEvent.SpaceChild) {
|
||||
const childId = mEvent.getStateKey();
|
||||
const roomId = mEvent.getRoomId();
|
||||
if (childId && roomId) {
|
||||
if (isValidChild(mEvent)) addToAtom(roomId, [childId]);
|
||||
else deleteFromAtom(childId);
|
||||
const baseRoomToParents = atom<RoomToParents>(new Map());
|
||||
export const roomToParentsAtom = atom<RoomToParents, RoomToParentsAction>(
|
||||
(get) => get(baseRoomToParents),
|
||||
(get, set, action) => {
|
||||
if (action.type === 'INITIALIZE') {
|
||||
set(baseRoomToParents, action.roomToParents);
|
||||
return;
|
||||
}
|
||||
if (action.type === 'PUT') {
|
||||
set(
|
||||
baseRoomToParents,
|
||||
produce(get(baseRoomToParents), (draftRoomToParents) => {
|
||||
mapParentWithChildren(draftRoomToParents, action.parent, action.children);
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (action.type === 'DELETE') {
|
||||
set(
|
||||
baseRoomToParents,
|
||||
produce(get(baseRoomToParents), (draftRoomToParents) => {
|
||||
const noParentRooms: string[] = [];
|
||||
draftRoomToParents.delete(action.roomId);
|
||||
draftRoomToParents.forEach((parents, child) => {
|
||||
parents.delete(action.roomId);
|
||||
if (parents.size === 0) noParentRooms.push(child);
|
||||
});
|
||||
noParentRooms.forEach((room) => draftRoomToParents.delete(room));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const useBindRoomToParentsAtom = (
|
||||
mx: MatrixClient,
|
||||
roomToParents: WritableAtom<RoomToParents, RoomToParentsAction>
|
||||
) => {
|
||||
const setRoomToParents = useSetAtom(roomToParents);
|
||||
|
||||
useEffect(() => {
|
||||
setRoomToParents({ type: 'INITIALIZE', roomToParents: getRoomToParents(mx) });
|
||||
|
||||
const handleAddRoom = (room: Room) => {
|
||||
if (isSpace(room) && room.getMyMembership() !== Membership.Invite) {
|
||||
setRoomToParents({ type: 'PUT', parent: room.roomId, children: getSpaceChildren(room) });
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleDeleteRoom = (roomId: string) => {
|
||||
deleteFromAtom(roomId);
|
||||
};
|
||||
const handleMembershipChange = (room: Room, membership: string) => {
|
||||
if (isSpace(room) && membership === Membership.Join) {
|
||||
setRoomToParents({ type: 'PUT', parent: room.roomId, children: getSpaceChildren(room) });
|
||||
}
|
||||
};
|
||||
|
||||
mx().on(ClientEvent.Room, handleAddRoom);
|
||||
mx().on(RoomEvent.MyMembership, handleMembershipChange);
|
||||
mx().on(RoomStateEvent.Events, handleStateChange);
|
||||
mx().on(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||
return () => {
|
||||
mx().removeListener(ClientEvent.Room, handleAddRoom);
|
||||
mx().removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
||||
mx().removeListener(RoomStateEvent.Events, handleStateChange);
|
||||
mx().removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||
};
|
||||
const handleStateChange = (mEvent: MatrixEvent) => {
|
||||
if (mEvent.getType() === StateEvent.SpaceChild) {
|
||||
const childId = mEvent.getStateKey();
|
||||
const roomId = mEvent.getRoomId();
|
||||
if (childId && roomId) {
|
||||
if (isValidChild(mEvent)) {
|
||||
setRoomToParents({ type: 'PUT', parent: roomId, children: [childId] });
|
||||
} else {
|
||||
setRoomToParents({ type: 'DELETE', roomId: childId });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteRoom = (roomId: string) => {
|
||||
setRoomToParents({ type: 'DELETE', roomId });
|
||||
};
|
||||
|
||||
mx.on(ClientEvent.Room, handleAddRoom);
|
||||
mx.on(RoomEvent.MyMembership, handleMembershipChange);
|
||||
mx.on(RoomStateEvent.Events, handleStateChange);
|
||||
mx.on(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||
return () => {
|
||||
mx.removeListener(ClientEvent.Room, handleAddRoom);
|
||||
mx.removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
||||
mx.removeListener(RoomStateEvent.Events, handleStateChange);
|
||||
mx.removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||
};
|
||||
}, [mx, setRoomToParents]);
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
} from '../utils/room';
|
||||
import { roomToParentsAtom } from './roomToParents';
|
||||
|
||||
type RoomToUnreadAction =
|
||||
export type RoomToUnreadAction =
|
||||
| {
|
||||
type: 'RESET';
|
||||
unreadInfos: UnreadInfo[];
|
||||
|
|
|
@ -1,46 +1,50 @@
|
|||
import { SetStateAction } from 'jotai';
|
||||
import { useSetAtom, WritableAtom } from 'jotai';
|
||||
import { ClientEvent, MatrixClient, Room, RoomEvent } from 'matrix-js-sdk';
|
||||
import { useEffect } from 'react';
|
||||
import { Membership } from '../../types/matrix/room';
|
||||
import { disposable } from '../utils/disposable';
|
||||
|
||||
export const atomRoomsWithMemberships = disposable(
|
||||
(
|
||||
setAtom: (update: SetStateAction<string[]>) => void,
|
||||
mx: MatrixClient,
|
||||
memberships: Membership[]
|
||||
) => {
|
||||
export type RoomsAction =
|
||||
| {
|
||||
type: 'INITIALIZE';
|
||||
rooms: string[];
|
||||
}
|
||||
| {
|
||||
type: 'PUT' | 'DELETE';
|
||||
roomId: string;
|
||||
};
|
||||
|
||||
export const useBindRoomsWithMembershipsAtom = (
|
||||
mx: MatrixClient,
|
||||
roomsAtom: WritableAtom<string[], RoomsAction>,
|
||||
memberships: Membership[]
|
||||
) => {
|
||||
const setRoomsAtom = useSetAtom(roomsAtom);
|
||||
|
||||
useEffect(() => {
|
||||
const satisfyMembership = (room: Room): boolean =>
|
||||
!!memberships.find((membership) => membership === room.getMyMembership());
|
||||
|
||||
setAtom(
|
||||
mx
|
||||
setRoomsAtom({
|
||||
type: 'INITIALIZE',
|
||||
rooms: mx
|
||||
.getRooms()
|
||||
.filter(satisfyMembership)
|
||||
.map((room) => room.roomId)
|
||||
);
|
||||
|
||||
const updateAtom = (type: 'PUT' | 'DELETE', roomId: string) => {
|
||||
setAtom((ids) => {
|
||||
const newIds = ids.filter((id) => id !== roomId);
|
||||
if (type === 'PUT') newIds.push(roomId);
|
||||
return newIds;
|
||||
});
|
||||
};
|
||||
.map((room) => room.roomId),
|
||||
});
|
||||
|
||||
const handleAddRoom = (room: Room) => {
|
||||
if (satisfyMembership(room)) {
|
||||
updateAtom('PUT', room.roomId);
|
||||
setRoomsAtom({ type: 'PUT', roomId: room.roomId });
|
||||
}
|
||||
};
|
||||
|
||||
const handleMembershipChange = (room: Room) => {
|
||||
if (!satisfyMembership(room)) {
|
||||
updateAtom('DELETE', room.roomId);
|
||||
setRoomsAtom({ type: 'DELETE', roomId: room.roomId });
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteRoom = (roomId: string) => {
|
||||
updateAtom('DELETE', roomId);
|
||||
setRoomsAtom({ type: 'DELETE', roomId });
|
||||
};
|
||||
|
||||
mx.on(ClientEvent.Room, handleAddRoom);
|
||||
|
@ -51,5 +55,10 @@ export const atomRoomsWithMemberships = disposable(
|
|||
mx.removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
||||
mx.removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||
};
|
||||
}
|
||||
);
|
||||
}, [mx, memberships, setRoomsAtom]);
|
||||
};
|
||||
|
||||
export const compareRoomsEqual = (a: string[], b: string[]) => {
|
||||
if (a.length !== b.length) return false;
|
||||
return a.every((roomId, roomIdIndex) => roomId === b[roomIdIndex]);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue