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 { atom, WritableAtom } from 'jotai';
|
||||||
import { mx } from '../../client/mx';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { Membership } from '../../types/matrix/room';
|
import { Membership } from '../../types/matrix/room';
|
||||||
import { isDirectInvite, isRoom, isSpace, isUnsupportedRoom } from '../utils/room';
|
import { RoomsAction, useBindRoomsWithMembershipsAtom } from './utils';
|
||||||
import { mDirectAtom } from './mDirectList';
|
|
||||||
import { atomRoomsWithMemberships } from './utils';
|
|
||||||
|
|
||||||
export const allInvitesAtom = atom<string[]>([]);
|
const baseRoomsAtom = atom<string[]>([]);
|
||||||
allInvitesAtom.onMount = (setAtom) => atomRoomsWithMemberships(setAtom, mx(), [Membership.Invite]);
|
export const allInvitesAtom = atom<string[], RoomsAction>(
|
||||||
|
(get) => get(baseRoomsAtom),
|
||||||
export const spaceInvitesAtom = atom((get) =>
|
(get, set, action) => {
|
||||||
get(allInvitesAtom).filter((roomId) => isSpace(mx().getRoom(roomId)))
|
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) =>
|
export const useBindAllInvitesAtom = (
|
||||||
get(allInvitesAtom).filter(
|
mx: MatrixClient,
|
||||||
(roomId) =>
|
allRooms: WritableAtom<string[], RoomsAction>
|
||||||
isRoom(mx().getRoom(roomId)) &&
|
) => {
|
||||||
!(get(mDirectAtom).has(roomId) || isDirectInvite(mx().getRoom(roomId), mx().getUserId()))
|
useBindRoomsWithMembershipsAtom(
|
||||||
)
|
mx,
|
||||||
);
|
allRooms,
|
||||||
|
useMemo(() => [Membership.Invite], [])
|
||||||
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)))
|
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -1,20 +1,47 @@
|
||||||
import { atom } from 'jotai';
|
import { atom, useSetAtom, WritableAtom } from 'jotai';
|
||||||
import { ClientEvent, MatrixEvent } from 'matrix-js-sdk';
|
import { ClientEvent, MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
||||||
import { mx } from '../../client/mx';
|
import { useEffect } from 'react';
|
||||||
import { AccountDataEvent } from '../../types/matrix/accountData';
|
import { AccountDataEvent } from '../../types/matrix/accountData';
|
||||||
import { getAccountData, getMDirects } from '../utils/room';
|
import { getAccountData, getMDirects } from '../utils/room';
|
||||||
|
|
||||||
export const mDirectAtom = atom(new Set<string>());
|
export type MDirectAction = {
|
||||||
mDirectAtom.onMount = (setAtom) => {
|
type: 'INITIALIZE' | 'UPDATE';
|
||||||
const mDirectEvent = getAccountData(mx(), AccountDataEvent.Direct);
|
rooms: Set<string>;
|
||||||
if (mDirectEvent) setAtom(getMDirects(mDirectEvent));
|
};
|
||||||
|
|
||||||
|
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) => {
|
const handleAccountData = (event: MatrixEvent) => {
|
||||||
setAtom(getMDirects(event));
|
setMDirect({
|
||||||
|
type: 'UPDATE',
|
||||||
|
rooms: getMDirects(event),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
mx().on(ClientEvent.AccountData, handleAccountData);
|
mx.on(ClientEvent.AccountData, handleAccountData);
|
||||||
return () => {
|
return () => {
|
||||||
mx().removeListener(ClientEvent.AccountData, handleAccountData);
|
mx.removeListener(ClientEvent.AccountData, handleAccountData);
|
||||||
};
|
};
|
||||||
|
}, [mx, setMDirect]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useEffect } from 'react';
|
||||||
import { MuteChanges } from '../../types/matrix/room';
|
import { MuteChanges } from '../../types/matrix/room';
|
||||||
import { findMutedRule, isMutedRule } from '../utils/room';
|
import { findMutedRule, isMutedRule } from '../utils/room';
|
||||||
|
|
||||||
type MutedRoomsUpdate =
|
export type MutedRoomsUpdate =
|
||||||
| {
|
| {
|
||||||
type: 'INITIALIZE';
|
type: 'INITIALIZE';
|
||||||
addRooms: string[];
|
addRooms: string[];
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
import { atom } from 'jotai';
|
import { atom, WritableAtom } from 'jotai';
|
||||||
import { mx } from '../../client/mx';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { Membership } from '../../types/matrix/room';
|
import { Membership } from '../../types/matrix/room';
|
||||||
import { isRoom, isSpace, isUnsupportedRoom } from '../utils/room';
|
import { RoomsAction, useBindRoomsWithMembershipsAtom } from './utils';
|
||||||
import { mDirectAtom } from './mDirectList';
|
|
||||||
import { atomRoomsWithMemberships } from './utils';
|
|
||||||
|
|
||||||
export const allRoomsAtom = atom<string[]>([]);
|
const baseRoomsAtom = atom<string[]>([]);
|
||||||
allRoomsAtom.onMount = (setAtom) => atomRoomsWithMemberships(setAtom, mx(), [Membership.Join]);
|
export const allRoomsAtom = atom<string[], RoomsAction>(
|
||||||
|
(get) => get(baseRoomsAtom),
|
||||||
export const spacesAtom = atom((get) =>
|
(get, set, action) => {
|
||||||
get(allRoomsAtom).filter((roomId) => isSpace(mx().getRoom(roomId)))
|
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 = (
|
||||||
export const roomsAtom = atom((get) =>
|
mx: MatrixClient,
|
||||||
get(allRoomsAtom).filter(
|
allRooms: WritableAtom<string[], RoomsAction>
|
||||||
(roomId) => isRoom(mx().getRoom(roomId)) && !get(mDirectAtom).has(roomId)
|
) => {
|
||||||
)
|
useBindRoomsWithMembershipsAtom(
|
||||||
);
|
mx,
|
||||||
|
allRooms,
|
||||||
export const directsAtom = atom((get) =>
|
useMemo(() => [Membership.Join], [])
|
||||||
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)))
|
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { atom } from 'jotai';
|
import { atom, useSetAtom, WritableAtom } from 'jotai';
|
||||||
import { ClientEvent, MatrixEvent, Room, RoomEvent, RoomStateEvent } from 'matrix-js-sdk';
|
import {
|
||||||
import { mx } from '../../client/mx';
|
ClientEvent,
|
||||||
|
MatrixClient,
|
||||||
|
MatrixEvent,
|
||||||
|
Room,
|
||||||
|
RoomEvent,
|
||||||
|
RoomStateEvent,
|
||||||
|
} from 'matrix-js-sdk';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { Membership, RoomToParents, StateEvent } from '../../types/matrix/room';
|
import { Membership, RoomToParents, StateEvent } from '../../types/matrix/room';
|
||||||
import {
|
import {
|
||||||
getRoomToParents,
|
getRoomToParents,
|
||||||
|
@ -11,43 +18,73 @@ import {
|
||||||
mapParentWithChildren,
|
mapParentWithChildren,
|
||||||
} from '../utils/room';
|
} from '../utils/room';
|
||||||
|
|
||||||
export const roomToParentsAtom = atom<RoomToParents>(new Map());
|
export type RoomToParentsAction =
|
||||||
roomToParentsAtom.onMount = (setAtom) => {
|
| {
|
||||||
setAtom(getRoomToParents(mx()));
|
type: 'INITIALIZE';
|
||||||
|
roomToParents: RoomToParents;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'PUT';
|
||||||
|
parent: string;
|
||||||
|
children: string[];
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'DELETE';
|
||||||
|
roomId: string;
|
||||||
|
};
|
||||||
|
|
||||||
const deleteFromAtom = (roomId: string) => {
|
const baseRoomToParents = atom<RoomToParents>(new Map());
|
||||||
setAtom(
|
export const roomToParentsAtom = atom<RoomToParents, RoomToParentsAction>(
|
||||||
produce((roomToParents) => {
|
(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[] = [];
|
const noParentRooms: string[] = [];
|
||||||
roomToParents.delete(roomId);
|
draftRoomToParents.delete(action.roomId);
|
||||||
roomToParents.forEach((parents, child) => {
|
draftRoomToParents.forEach((parents, child) => {
|
||||||
parents.delete(roomId);
|
parents.delete(action.roomId);
|
||||||
if (parents.size === 0) noParentRooms.push(child);
|
if (parents.size === 0) noParentRooms.push(child);
|
||||||
});
|
});
|
||||||
noParentRooms.forEach((room) => roomToParents.delete(room));
|
noParentRooms.forEach((room) => draftRoomToParents.delete(room));
|
||||||
return roomToParents;
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const addToAtom = (parent: string, children: string[]) => {
|
export const useBindRoomToParentsAtom = (
|
||||||
setAtom(
|
mx: MatrixClient,
|
||||||
produce((roomToParents) => {
|
roomToParents: WritableAtom<RoomToParents, RoomToParentsAction>
|
||||||
mapParentWithChildren(roomToParents, parent, children);
|
) => {
|
||||||
return roomToParents;
|
const setRoomToParents = useSetAtom(roomToParents);
|
||||||
})
|
|
||||||
);
|
useEffect(() => {
|
||||||
};
|
setRoomToParents({ type: 'INITIALIZE', roomToParents: getRoomToParents(mx) });
|
||||||
|
|
||||||
const handleAddRoom = (room: Room) => {
|
const handleAddRoom = (room: Room) => {
|
||||||
if (isSpace(room) && room.getMyMembership() !== Membership.Invite) {
|
if (isSpace(room) && room.getMyMembership() !== Membership.Invite) {
|
||||||
addToAtom(room.roomId, getSpaceChildren(room));
|
setRoomToParents({ type: 'PUT', parent: room.roomId, children: getSpaceChildren(room) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMembershipChange = (room: Room, membership: string) => {
|
const handleMembershipChange = (room: Room, membership: string) => {
|
||||||
if (isSpace(room) && membership === Membership.Join) {
|
if (isSpace(room) && membership === Membership.Join) {
|
||||||
addToAtom(room.roomId, getSpaceChildren(room));
|
setRoomToParents({ type: 'PUT', parent: room.roomId, children: getSpaceChildren(room) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,24 +93,28 @@ roomToParentsAtom.onMount = (setAtom) => {
|
||||||
const childId = mEvent.getStateKey();
|
const childId = mEvent.getStateKey();
|
||||||
const roomId = mEvent.getRoomId();
|
const roomId = mEvent.getRoomId();
|
||||||
if (childId && roomId) {
|
if (childId && roomId) {
|
||||||
if (isValidChild(mEvent)) addToAtom(roomId, [childId]);
|
if (isValidChild(mEvent)) {
|
||||||
else deleteFromAtom(childId);
|
setRoomToParents({ type: 'PUT', parent: roomId, children: [childId] });
|
||||||
|
} else {
|
||||||
|
setRoomToParents({ type: 'DELETE', roomId: childId });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteRoom = (roomId: string) => {
|
const handleDeleteRoom = (roomId: string) => {
|
||||||
deleteFromAtom(roomId);
|
setRoomToParents({ type: 'DELETE', roomId });
|
||||||
};
|
};
|
||||||
|
|
||||||
mx().on(ClientEvent.Room, handleAddRoom);
|
mx.on(ClientEvent.Room, handleAddRoom);
|
||||||
mx().on(RoomEvent.MyMembership, handleMembershipChange);
|
mx.on(RoomEvent.MyMembership, handleMembershipChange);
|
||||||
mx().on(RoomStateEvent.Events, handleStateChange);
|
mx.on(RoomStateEvent.Events, handleStateChange);
|
||||||
mx().on(ClientEvent.DeleteRoom, handleDeleteRoom);
|
mx.on(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||||
return () => {
|
return () => {
|
||||||
mx().removeListener(ClientEvent.Room, handleAddRoom);
|
mx.removeListener(ClientEvent.Room, handleAddRoom);
|
||||||
mx().removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
mx.removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
||||||
mx().removeListener(RoomStateEvent.Events, handleStateChange);
|
mx.removeListener(RoomStateEvent.Events, handleStateChange);
|
||||||
mx().removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
mx.removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
||||||
};
|
};
|
||||||
|
}, [mx, setRoomToParents]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '../utils/room';
|
} from '../utils/room';
|
||||||
import { roomToParentsAtom } from './roomToParents';
|
import { roomToParentsAtom } from './roomToParents';
|
||||||
|
|
||||||
type RoomToUnreadAction =
|
export type RoomToUnreadAction =
|
||||||
| {
|
| {
|
||||||
type: 'RESET';
|
type: 'RESET';
|
||||||
unreadInfos: UnreadInfo[];
|
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 { ClientEvent, MatrixClient, Room, RoomEvent } from 'matrix-js-sdk';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { Membership } from '../../types/matrix/room';
|
import { Membership } from '../../types/matrix/room';
|
||||||
import { disposable } from '../utils/disposable';
|
|
||||||
|
|
||||||
export const atomRoomsWithMemberships = disposable(
|
export type RoomsAction =
|
||||||
(
|
| {
|
||||||
setAtom: (update: SetStateAction<string[]>) => void,
|
type: 'INITIALIZE';
|
||||||
|
rooms: string[];
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'PUT' | 'DELETE';
|
||||||
|
roomId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useBindRoomsWithMembershipsAtom = (
|
||||||
mx: MatrixClient,
|
mx: MatrixClient,
|
||||||
|
roomsAtom: WritableAtom<string[], RoomsAction>,
|
||||||
memberships: Membership[]
|
memberships: Membership[]
|
||||||
) => {
|
) => {
|
||||||
|
const setRoomsAtom = useSetAtom(roomsAtom);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
const satisfyMembership = (room: Room): boolean =>
|
const satisfyMembership = (room: Room): boolean =>
|
||||||
!!memberships.find((membership) => membership === room.getMyMembership());
|
!!memberships.find((membership) => membership === room.getMyMembership());
|
||||||
|
setRoomsAtom({
|
||||||
setAtom(
|
type: 'INITIALIZE',
|
||||||
mx
|
rooms: mx
|
||||||
.getRooms()
|
.getRooms()
|
||||||
.filter(satisfyMembership)
|
.filter(satisfyMembership)
|
||||||
.map((room) => room.roomId)
|
.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;
|
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const handleAddRoom = (room: Room) => {
|
const handleAddRoom = (room: Room) => {
|
||||||
if (satisfyMembership(room)) {
|
if (satisfyMembership(room)) {
|
||||||
updateAtom('PUT', room.roomId);
|
setRoomsAtom({ type: 'PUT', roomId: room.roomId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMembershipChange = (room: Room) => {
|
const handleMembershipChange = (room: Room) => {
|
||||||
if (!satisfyMembership(room)) {
|
if (!satisfyMembership(room)) {
|
||||||
updateAtom('DELETE', room.roomId);
|
setRoomsAtom({ type: 'DELETE', roomId: room.roomId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteRoom = (roomId: string) => {
|
const handleDeleteRoom = (roomId: string) => {
|
||||||
updateAtom('DELETE', roomId);
|
setRoomsAtom({ type: 'DELETE', roomId });
|
||||||
};
|
};
|
||||||
|
|
||||||
mx.on(ClientEvent.Room, handleAddRoom);
|
mx.on(ClientEvent.Room, handleAddRoom);
|
||||||
|
@ -51,5 +55,10 @@ export const atomRoomsWithMemberships = disposable(
|
||||||
mx.removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
mx.removeListener(RoomEvent.MyMembership, handleMembershipChange);
|
||||||
mx.removeListener(ClientEvent.DeleteRoom, handleDeleteRoom);
|
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