New invite user to room dialog (#2460)

* fix 0 displayed in invite with no timestamp

* support displaying invite reason for receiver

* show invite reason as compact message

* remove unused import

* revert: show invite reason as compact message

* remove unused import

* add new invite prompt
This commit is contained in:
Ajay Bura 2025-08-24 18:04:21 +05:30 committed by GitHub
parent c881b59957
commit 13cdcbcdb1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 434 additions and 56 deletions

View file

@ -18,7 +18,6 @@ import {
import { HierarchyItem } from '../../hooks/useSpaceHierarchy';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { MSpaceChildContent, StateEvent } from '../../../types/matrix/room';
import { openInviteUser } from '../../../client/action/navigation';
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
import { UseStateProvider } from '../../components/UseStateProvider';
import { LeaveSpacePrompt } from '../../components/leave-space-prompt';
@ -30,6 +29,7 @@ import { useOpenSpaceSettings } from '../../state/hooks/spaceSettings';
import { IPowerLevels } from '../../hooks/usePowerLevels';
import { getRoomCreatorsForRoomId } from '../../hooks/useRoomCreators';
import { getRoomPermissionsAPI } from '../../hooks/useRoomPermissions';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
type HierarchyItemWithParent = HierarchyItem & {
parentId: string;
@ -126,24 +126,39 @@ function InviteMenuItem({
requestClose: () => void;
disabled?: boolean;
}) {
const mx = useMatrixClient();
const room = mx.getRoom(item.roomId);
const [invitePrompt, setInvitePrompt] = useState(false);
const handleInvite = () => {
openInviteUser(item.roomId);
requestClose();
setInvitePrompt(true);
};
return (
<MenuItem
onClick={handleInvite}
size="300"
radii="300"
variant="Primary"
fill="None"
disabled={disabled}
>
<Text as="span" size="T300" truncate>
Invite
</Text>
</MenuItem>
<>
<MenuItem
onClick={handleInvite}
size="300"
radii="300"
variant="Primary"
fill="None"
aria-pressed={invitePrompt}
disabled={disabled || !room}
>
<Text as="span" size="T300" truncate>
Invite
</Text>
</MenuItem>
{invitePrompt && room && (
<InviteUserPrompt
room={room}
requestClose={() => {
setInvitePrompt(false);
requestClose();
}}
/>
)}
</>
);
}

View file

@ -26,7 +26,6 @@ import { useMatrixClient } from '../../hooks/useMatrixClient';
import { RoomAvatar } from '../../components/room-avatar';
import { nameInitials } from '../../utils/common';
import * as css from './LobbyHeader.css';
import { openInviteUser } from '../../../client/action/navigation';
import { IPowerLevels } from '../../hooks/usePowerLevels';
import { UseStateProvider } from '../../components/UseStateProvider';
import { LeaveSpacePrompt } from '../../components/leave-space-prompt';
@ -38,6 +37,7 @@ import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useOpenSpaceSettings } from '../../state/hooks/spaceSettings';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
type LobbyMenuProps = {
powerLevels: IPowerLevels;
@ -53,9 +53,10 @@ const LobbyMenu = forwardRef<HTMLDivElement, LobbyMenuProps>(
const canInvite = permissions.action('invite', mx.getSafeUserId());
const openSpaceSettings = useOpenSpaceSettings();
const [invitePrompt, setInvitePrompt] = useState(false);
const handleInvite = () => {
openInviteUser(space.roomId);
requestClose();
setInvitePrompt(true);
};
const handleRoomSettings = () => {
@ -65,6 +66,15 @@ const LobbyMenu = forwardRef<HTMLDivElement, LobbyMenuProps>(
return (
<Menu ref={ref} style={{ maxWidth: toRem(160), width: '100vw' }}>
{invitePrompt && (
<InviteUserPrompt
room={space}
requestClose={() => {
setInvitePrompt(false);
requestClose();
}}
/>
)}
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
<MenuItem
onClick={handleInvite}
@ -73,6 +83,7 @@ const LobbyMenu = forwardRef<HTMLDivElement, LobbyMenuProps>(
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
radii="300"
aria-pressed={invitePrompt}
disabled={!canInvite}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>

View file

@ -30,7 +30,6 @@ import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { usePowerLevels } from '../../hooks/usePowerLevels';
import { copyToClipboard } from '../../utils/dom';
import { markAsRead } from '../../../client/action/notifications';
import { openInviteUser } from '../../../client/action/navigation';
import { UseStateProvider } from '../../components/UseStateProvider';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers';
@ -51,6 +50,7 @@ import {
import { RoomNotificationModeSwitcher } from '../../components/RoomNotificationSwitcher';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
type RoomNavItemMenuProps = {
room: Room;
@ -70,14 +70,15 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
const openRoomSettings = useOpenRoomSettings();
const space = useSpaceOptionally();
const [invitePrompt, setInvitePrompt] = useState(false);
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
requestClose();
};
const handleInvite = () => {
openInviteUser(room.roomId);
requestClose();
setInvitePrompt(true);
};
const handleCopyLink = () => {
@ -94,6 +95,15 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
return (
<Menu ref={ref} style={{ maxWidth: toRem(160), width: '100vw' }}>
{invitePrompt && room && (
<InviteUserPrompt
room={room}
requestClose={() => {
setInvitePrompt(false);
requestClose();
}}
/>
)}
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
<MenuItem
onClick={handleMarkAsRead}
@ -137,6 +147,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
radii="300"
aria-pressed={invitePrompt}
disabled={!canInvite}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>

View file

@ -45,7 +45,6 @@ import { useRoomUnread } from '../../state/hooks/unread';
import { usePowerLevelsContext } from '../../hooks/usePowerLevels';
import { markAsRead } from '../../../client/action/notifications';
import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { openInviteUser } from '../../../client/action/navigation';
import { copyToClipboard } from '../../utils/dom';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
@ -69,6 +68,7 @@ import { JumpToTime } from './jump-to-time';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
type RoomMenuProps = {
room: Room;
@ -87,14 +87,15 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
const notificationMode = getRoomNotificationMode(notificationPreferences, room.roomId);
const { navigateRoom } = useRoomNavigate();
const [invitePrompt, setInvitePrompt] = useState(false);
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
requestClose();
};
const handleInvite = () => {
openInviteUser(room.roomId);
requestClose();
setInvitePrompt(true);
};
const handleCopyLink = () => {
@ -113,6 +114,15 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
return (
<Menu ref={ref} style={{ maxWidth: toRem(160), width: '100vw' }}>
{invitePrompt && (
<InviteUserPrompt
room={room}
requestClose={() => {
setInvitePrompt(false);
requestClose();
}}
/>
)}
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
<MenuItem
onClick={handleMarkAsRead}
@ -156,6 +166,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
radii="300"
aria-pressed={invitePrompt}
disabled={!canInvite}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>