mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-09-13 14:22:25 +03:00
New create chat screen (#2463)
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
Some checks are pending
Deploy to Netlify (dev) / Deploy to Netlify (push) Waiting to run
* fix dm invite appears in home * use migrated function for convert to dm/room commands * add new create chat screen
This commit is contained in:
parent
23aa5c6f94
commit
b4266c26b0
8 changed files with 246 additions and 66 deletions
|
@ -1,7 +1,8 @@
|
|||
import { Box, Button, color, config, Icon, Icons, Spinner, Text } from 'folds';
|
||||
import React, { useCallback } from 'react';
|
||||
import { Box, Button, config, Icon, Icons, Text } from 'folds';
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { UserHero, UserHeroName } from './UserHero';
|
||||
import { getDMRoomFor, getMxIdServer, mxcUrlToHttp } from '../../utils/matrix';
|
||||
import { getMxIdServer, mxcUrlToHttp } from '../../utils/matrix';
|
||||
import { getMemberAvatarMxc, getMemberDisplayName } from '../../utils/room';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
||||
|
@ -9,11 +10,6 @@ import { usePowerLevels } from '../../hooks/usePowerLevels';
|
|||
import { useRoom } from '../../hooks/useRoom';
|
||||
import { useUserPresence } from '../../hooks/useUserPresence';
|
||||
import { IgnoredUserAlert, MutualRoomsChip, OptionsChip, ServerChip, ShareChip } from './UserChips';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
import { createDM } from '../../../client/action/room';
|
||||
import { hasDevices } from '../../../util/matrixUtil';
|
||||
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
|
||||
import { useAlive } from '../../hooks/useAlive';
|
||||
import { useCloseUserRoomProfile } from '../../state/hooks/userRoomProfile';
|
||||
import { PowerChip } from './PowerChip';
|
||||
import { UserInviteAlert, UserBanAlert, UserModeration, UserKickAlert } from './UserModeration';
|
||||
|
@ -24,6 +20,8 @@ import { useRoomCreators } from '../../hooks/useRoomCreators';
|
|||
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
|
||||
import { useMemberPowerCompare } from '../../hooks/useMemberPowerCompare';
|
||||
import { CreatorChip } from './CreatorChip';
|
||||
import { getDirectCreatePath, withSearchParam } from '../../pages/pathUtils';
|
||||
import { DirectCreateSearchParams } from '../../pages/paths';
|
||||
|
||||
type UserRoomProfileProps = {
|
||||
userId: string;
|
||||
|
@ -31,8 +29,7 @@ type UserRoomProfileProps = {
|
|||
export function UserRoomProfile({ userId }: UserRoomProfileProps) {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const { navigateRoom } = useRoomNavigate();
|
||||
const alive = useAlive();
|
||||
const navigate = useNavigate();
|
||||
const closeUserRoomProfile = useCloseUserRoomProfile();
|
||||
const ignoredUsers = useIgnoredUsers();
|
||||
const ignored = ignoredUsers.includes(userId);
|
||||
|
@ -62,26 +59,12 @@ export function UserRoomProfile({ userId }: UserRoomProfileProps) {
|
|||
|
||||
const presence = useUserPresence(userId);
|
||||
|
||||
const [directMessageState, directMessage] = useAsyncCallback<string, Error, []>(
|
||||
useCallback(async () => {
|
||||
const result = await createDM(mx, userId, await hasDevices(mx, userId));
|
||||
return result.room_id as string;
|
||||
}, [userId, mx])
|
||||
);
|
||||
|
||||
const handleMessage = () => {
|
||||
const dmRoomId = getDMRoomFor(mx, userId)?.roomId;
|
||||
if (dmRoomId) {
|
||||
navigateRoom(dmRoomId);
|
||||
closeUserRoomProfile();
|
||||
return;
|
||||
}
|
||||
directMessage().then((rId) => {
|
||||
if (alive()) {
|
||||
navigateRoom(rId);
|
||||
closeUserRoomProfile();
|
||||
}
|
||||
});
|
||||
const directSearchParam: DirectCreateSearchParams = {
|
||||
userId,
|
||||
};
|
||||
navigate(withSearchParam(getDirectCreatePath(), directSearchParam));
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -102,14 +85,7 @@ export function UserRoomProfile({ userId }: UserRoomProfileProps) {
|
|||
variant="Primary"
|
||||
fill="Solid"
|
||||
radii="300"
|
||||
disabled={directMessageState.status === AsyncStatus.Loading}
|
||||
before={
|
||||
directMessageState.status === AsyncStatus.Loading ? (
|
||||
<Spinner size="50" variant="Primary" fill="Solid" />
|
||||
) : (
|
||||
<Icon size="50" src={Icons.Message} filled />
|
||||
)
|
||||
}
|
||||
before={<Icon size="50" src={Icons.Message} filled />}
|
||||
onClick={handleMessage}
|
||||
>
|
||||
<Text size="B300">Message</Text>
|
||||
|
@ -117,11 +93,6 @@ export function UserRoomProfile({ userId }: UserRoomProfileProps) {
|
|||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{directMessageState.status === AsyncStatus.Error && (
|
||||
<Text style={{ color: color.Critical.Main }}>
|
||||
<b>{directMessageState.error.message}</b>
|
||||
</Text>
|
||||
)}
|
||||
<Box alignItems="Center" gap="200" wrap="Wrap">
|
||||
{server && <ServerChip server={server} />}
|
||||
<ShareChip userId={userId} />
|
||||
|
|
150
src/app/features/create-chat/CreateChat.tsx
Normal file
150
src/app/features/create-chat/CreateChat.tsx
Normal file
|
@ -0,0 +1,150 @@
|
|||
import { Box, Button, color, config, Icon, Icons, Input, Spinner, Switch, Text } from 'folds';
|
||||
import React, { FormEventHandler, useCallback, useState } from 'react';
|
||||
import { ICreateRoomStateEvent, MatrixError, Preset, Visibility } from 'matrix-js-sdk';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { SettingTile } from '../../components/setting-tile';
|
||||
import { SequenceCard } from '../../components/sequence-card';
|
||||
import { addRoomIdToMDirect, isUserId } from '../../utils/matrix';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
import { ErrorCode } from '../../cs-errorcode';
|
||||
import { millisecondsToMinutes } from '../../utils/common';
|
||||
import { createRoomEncryptionState } from '../../components/create-room';
|
||||
import { useAlive } from '../../hooks/useAlive';
|
||||
import { getDirectRoomPath } from '../../pages/pathUtils';
|
||||
|
||||
type CreateChatProps = {
|
||||
defaultUserId?: string;
|
||||
};
|
||||
export function CreateChat({ defaultUserId }: CreateChatProps) {
|
||||
const mx = useMatrixClient();
|
||||
const alive = useAlive();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [encryption, setEncryption] = useState(true);
|
||||
const [invalidUserId, setInvalidUserId] = useState(false);
|
||||
|
||||
const [createState, create] = useAsyncCallback<string, Error | MatrixError, [string, boolean]>(
|
||||
useCallback(
|
||||
async (userId, encrypted) => {
|
||||
const initialState: ICreateRoomStateEvent[] = [];
|
||||
|
||||
if (encrypted) initialState.push(createRoomEncryptionState());
|
||||
|
||||
const result = await mx.createRoom({
|
||||
is_direct: true,
|
||||
invite: [userId],
|
||||
visibility: Visibility.Private,
|
||||
preset: Preset.TrustedPrivateChat,
|
||||
initial_state: initialState,
|
||||
});
|
||||
|
||||
addRoomIdToMDirect(mx, result.room_id, userId);
|
||||
|
||||
return result.room_id;
|
||||
},
|
||||
[mx]
|
||||
)
|
||||
);
|
||||
const loading = createState.status === AsyncStatus.Loading;
|
||||
const error = createState.status === AsyncStatus.Error ? createState.error : undefined;
|
||||
const disabled = createState.status === AsyncStatus.Loading;
|
||||
|
||||
const handleSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
|
||||
evt.preventDefault();
|
||||
setInvalidUserId(false);
|
||||
|
||||
const target = evt.target as HTMLFormElement | undefined;
|
||||
const userIdInput = target?.userIdInput as HTMLInputElement | undefined;
|
||||
const userId = userIdInput?.value.trim();
|
||||
|
||||
if (!userIdInput || !userId) return;
|
||||
if (!isUserId(userId)) {
|
||||
setInvalidUserId(true);
|
||||
return;
|
||||
}
|
||||
|
||||
create(userId, encryption).then((roomId) => {
|
||||
if (alive()) {
|
||||
userIdInput.value = '';
|
||||
navigate(getDirectRoomPath(roomId));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Box as="form" onSubmit={handleSubmit} grow="Yes" direction="Column" gap="500">
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">User ID</Text>
|
||||
<Input
|
||||
defaultValue={defaultUserId}
|
||||
placeholder="@john:server"
|
||||
name="userIdInput"
|
||||
variant="SurfaceVariant"
|
||||
size="500"
|
||||
radii="400"
|
||||
required
|
||||
autoFocus
|
||||
autoComplete="off"
|
||||
disabled={disabled}
|
||||
/>
|
||||
{invalidUserId && (
|
||||
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
|
||||
<Icon src={Icons.Warning} filled size="50" />
|
||||
<Text size="T200" style={{ color: color.Critical.Main }}>
|
||||
<b>Please enter a valid User ID.</b>
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">Options</Text>
|
||||
<SequenceCard
|
||||
style={{ padding: config.space.S300 }}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="500"
|
||||
>
|
||||
<SettingTile
|
||||
title="End-to-End Encryption"
|
||||
description="Once this feature is enabled, it can't be disabled after the room is created."
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
value={encryption}
|
||||
onChange={setEncryption}
|
||||
disabled={disabled}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
</Box>
|
||||
{error && (
|
||||
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="200">
|
||||
<Icon src={Icons.Warning} filled size="100" />
|
||||
<Text size="T300" style={{ color: color.Critical.Main }}>
|
||||
<b>
|
||||
{error instanceof MatrixError && error.name === ErrorCode.M_LIMIT_EXCEEDED
|
||||
? `Server rate-limited your request for ${millisecondsToMinutes(
|
||||
(error.data.retry_after_ms as number | undefined) ?? 0
|
||||
)} minutes!`
|
||||
: error.message}
|
||||
</b>
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
<Box shrink="No" direction="Column" gap="200">
|
||||
<Button
|
||||
type="submit"
|
||||
size="500"
|
||||
variant="Primary"
|
||||
radii="400"
|
||||
disabled={disabled}
|
||||
before={loading && <Spinner variant="Primary" fill="Solid" size="200" />}
|
||||
>
|
||||
<Text size="B500">Create</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
1
src/app/features/create-chat/index.ts
Normal file
1
src/app/features/create-chat/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './CreateChat';
|
|
@ -2,12 +2,15 @@ import { Direction, IContextResponse, MatrixClient, Method, Room, RoomMember } f
|
|||
import { RoomServerAclEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
addRoomIdToMDirect,
|
||||
getDMRoomFor,
|
||||
guessDmRoomUserId,
|
||||
isRoomAlias,
|
||||
isRoomId,
|
||||
isServerName,
|
||||
isUserId,
|
||||
rateLimitedActions,
|
||||
removeRoomIdFromMDirect,
|
||||
} from '../utils/matrix';
|
||||
import { hasDevices } from '../../util/matrixUtil';
|
||||
import * as roomActions from '../../client/action/room';
|
||||
|
@ -348,14 +351,15 @@ export const useCommands = (mx: MatrixClient, room: Room): CommandRecord => {
|
|||
name: Command.ConvertToDm,
|
||||
description: 'Convert room to direct message',
|
||||
exe: async () => {
|
||||
roomActions.convertToDm(mx, room.roomId);
|
||||
const dmUserId = guessDmRoomUserId(room, mx.getSafeUserId());
|
||||
await addRoomIdToMDirect(mx, room.roomId, dmUserId);
|
||||
},
|
||||
},
|
||||
[Command.ConvertToRoom]: {
|
||||
name: Command.ConvertToRoom,
|
||||
description: 'Convert direct message to room',
|
||||
exe: async () => {
|
||||
roomActions.convertToRoom(mx, room.roomId);
|
||||
await removeRoomIdFromMDirect(mx, room.roomId);
|
||||
},
|
||||
},
|
||||
[Command.Delete]: {
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from 'folds';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { factoryRoomIdByActivity } from '../../../utils/sort';
|
||||
import {
|
||||
|
@ -28,7 +29,7 @@ import {
|
|||
NavItem,
|
||||
NavItemContent,
|
||||
} from '../../../components/nav';
|
||||
import { getDirectRoomPath } from '../../pathUtils';
|
||||
import { getDirectCreatePath, getDirectRoomPath } from '../../pathUtils';
|
||||
import { getCanonicalAliasOrRoomId } from '../../../utils/matrix';
|
||||
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
||||
import { VirtualTile } from '../../../components/virtualizer';
|
||||
|
@ -38,7 +39,6 @@ import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
|||
import { useCategoryHandler } from '../../../hooks/useCategoryHandler';
|
||||
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
|
||||
import { useDirectRooms } from './useDirectRooms';
|
||||
import { openInviteUser } from '../../../../client/action/navigation';
|
||||
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
|
||||
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
|
||||
import { useRoomsUnread } from '../../../state/hooks/unread';
|
||||
|
@ -50,6 +50,7 @@ import {
|
|||
getRoomNotificationMode,
|
||||
useRoomsNotificationPreferencesContext,
|
||||
} from '../../../hooks/useRoomsNotificationPreferences';
|
||||
import { useDirectCreateSelected } from '../../../hooks/router/useDirectSelected';
|
||||
|
||||
type DirectMenuProps = {
|
||||
requestClose: () => void;
|
||||
|
@ -138,6 +139,8 @@ function DirectHeader() {
|
|||
}
|
||||
|
||||
function DirectEmpty() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<NavEmptyCenter>
|
||||
<NavEmptyLayout
|
||||
|
@ -153,7 +156,7 @@ function DirectEmpty() {
|
|||
</Text>
|
||||
}
|
||||
options={
|
||||
<Button variant="Secondary" size="300" onClick={() => openInviteUser()}>
|
||||
<Button variant="Secondary" size="300" onClick={() => navigate(getDirectCreatePath())}>
|
||||
<Text size="B300" truncate>
|
||||
Direct Message
|
||||
</Text>
|
||||
|
@ -172,6 +175,9 @@ export function Direct() {
|
|||
const directs = useDirectRooms();
|
||||
const notificationPreferences = useRoomsNotificationPreferencesContext();
|
||||
const roomToUnread = useAtomValue(roomToUnreadAtom);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const createDirectSelected = useDirectCreateSelected();
|
||||
|
||||
const selectedRoomId = useSelectedRoom();
|
||||
const noRoomToDisplay = directs.length === 0;
|
||||
|
@ -205,8 +211,8 @@ export function Direct() {
|
|||
<PageNavContent scrollRef={scrollRef}>
|
||||
<Box direction="Column" gap="300">
|
||||
<NavCategory>
|
||||
<NavItem variant="Background" radii="400">
|
||||
<NavButton onClick={() => openInviteUser()}>
|
||||
<NavItem variant="Background" radii="400" aria-selected={createDirectSelected}>
|
||||
<NavButton onClick={() => navigate(getDirectCreatePath())}>
|
||||
<NavItemContent>
|
||||
<Box as="span" grow="Yes" alignItems="Center" gap="200">
|
||||
<Avatar size="200" radii="400">
|
||||
|
|
|
@ -1,33 +1,75 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { WelcomePage } from '../WelcomePage';
|
||||
import { Box, Icon, IconButton, Icons, Scroll } from 'folds';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { getDirectCreateSearchParams } from '../../pathSearchParam';
|
||||
import { getDirectPath, getDirectRoomPath } from '../../pathUtils';
|
||||
import { getDirectRoomPath } from '../../pathUtils';
|
||||
import { getDMRoomFor } from '../../../utils/matrix';
|
||||
import { openInviteUser } from '../../../../client/action/navigation';
|
||||
import { useDirectRooms } from './useDirectRooms';
|
||||
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
||||
import {
|
||||
Page,
|
||||
PageContent,
|
||||
PageContentCenter,
|
||||
PageHeader,
|
||||
PageHero,
|
||||
PageHeroSection,
|
||||
} from '../../../components/page';
|
||||
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
||||
import { CreateChat } from '../../../features/create-chat';
|
||||
|
||||
export function DirectCreate() {
|
||||
const mx = useMatrixClient();
|
||||
const screenSize = useScreenSizeContext();
|
||||
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const { userId } = getDirectCreateSearchParams(searchParams);
|
||||
|
||||
const directs = useDirectRooms();
|
||||
|
||||
useEffect(() => {
|
||||
if (userId) {
|
||||
const room = getDMRoomFor(mx, userId);
|
||||
const { roomId } = room ?? {};
|
||||
const roomId = getDMRoomFor(mx, userId)?.roomId;
|
||||
if (roomId && directs.includes(roomId)) {
|
||||
navigate(getDirectRoomPath(roomId), { replace: true });
|
||||
} else {
|
||||
openInviteUser(undefined, userId);
|
||||
}
|
||||
} else {
|
||||
navigate(getDirectPath(), { replace: true });
|
||||
}
|
||||
}, [mx, navigate, directs, userId]);
|
||||
|
||||
return <WelcomePage />;
|
||||
return (
|
||||
<Page>
|
||||
{screenSize === ScreenSize.Mobile && (
|
||||
<PageHeader balance outlined={false}>
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<BackRouteHandler>
|
||||
{(onBack) => (
|
||||
<IconButton onClick={onBack}>
|
||||
<Icon src={Icons.ArrowLeft} />
|
||||
</IconButton>
|
||||
)}
|
||||
</BackRouteHandler>
|
||||
</Box>
|
||||
</PageHeader>
|
||||
)}
|
||||
<Box grow="Yes">
|
||||
<Scroll hideTrack visibility="Hover">
|
||||
<PageContent>
|
||||
<PageContentCenter>
|
||||
<PageHeroSection>
|
||||
<Box direction="Column" gap="700">
|
||||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Mention} />}
|
||||
title="Create Chat"
|
||||
subTitle="Start a private, encrypted chat by entering a user ID."
|
||||
/>
|
||||
<CreateChat defaultUserId={userId} />
|
||||
</Box>
|
||||
</PageHeroSection>
|
||||
</PageContentCenter>
|
||||
</PageContent>
|
||||
</Scroll>
|
||||
</Box>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ export function HomeCreateRoom() {
|
|||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Hash} />}
|
||||
title="Create Room"
|
||||
subTitle="Build a Room for Real-Time Conversations"
|
||||
subTitle="Build a Room for Real-Time Conversations."
|
||||
/>
|
||||
<CreateRoomForm onCreate={navigateRoom} />
|
||||
</Box>
|
||||
|
|
|
@ -230,8 +230,11 @@ export const addRoomIdToMDirect = async (
|
|||
roomId: string,
|
||||
userId: string
|
||||
): Promise<void> => {
|
||||
const mDirectsEvent = mx.getAccountData(AccountDataEvent.Direct);
|
||||
const userIdToRoomIds: Record<string, string[]> = mDirectsEvent?.getContent() ?? {};
|
||||
const mDirectsEvent = mx.getAccountData(AccountDataEvent.Direct as any);
|
||||
let userIdToRoomIds: Record<string, string[]> = {};
|
||||
|
||||
if (typeof mDirectsEvent !== 'undefined')
|
||||
userIdToRoomIds = structuredClone(mDirectsEvent.getContent());
|
||||
|
||||
// remove it from the lists of any others users
|
||||
// (it can only be a DM room for one person)
|
||||
|
@ -252,12 +255,15 @@ export const addRoomIdToMDirect = async (
|
|||
}
|
||||
userIdToRoomIds[userId] = roomIds;
|
||||
|
||||
await mx.setAccountData(AccountDataEvent.Direct, userIdToRoomIds);
|
||||
await mx.setAccountData(AccountDataEvent.Direct as any, userIdToRoomIds as any);
|
||||
};
|
||||
|
||||
export const removeRoomIdFromMDirect = async (mx: MatrixClient, roomId: string): Promise<void> => {
|
||||
const mDirectsEvent = mx.getAccountData(AccountDataEvent.Direct);
|
||||
const userIdToRoomIds: Record<string, string[]> = mDirectsEvent?.getContent() ?? {};
|
||||
const mDirectsEvent = mx.getAccountData(AccountDataEvent.Direct as any);
|
||||
let userIdToRoomIds: Record<string, string[]> = {};
|
||||
|
||||
if (typeof mDirectsEvent !== 'undefined')
|
||||
userIdToRoomIds = structuredClone(mDirectsEvent.getContent());
|
||||
|
||||
Object.keys(userIdToRoomIds).forEach((targetUserId) => {
|
||||
const roomIds = userIdToRoomIds[targetUserId];
|
||||
|
@ -267,7 +273,7 @@ export const removeRoomIdFromMDirect = async (mx: MatrixClient, roomId: string):
|
|||
}
|
||||
});
|
||||
|
||||
await mx.setAccountData(AccountDataEvent.Direct, userIdToRoomIds);
|
||||
await mx.setAccountData(AccountDataEvent.Direct as any, userIdToRoomIds as any);
|
||||
};
|
||||
|
||||
export const mxcUrlToHttp = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue