diff --git a/src/app/features/room/RoomTombstone.tsx b/src/app/features/room/RoomTombstone.tsx
index e3f8251f..24f0b80e 100644
--- a/src/app/features/room/RoomTombstone.tsx
+++ b/src/app/features/room/RoomTombstone.tsx
@@ -3,11 +3,11 @@ import { Box, Button, Spinner, Text, color } from 'folds';
import * as css from './RoomTombstone.css';
import { useMatrixClient } from '../../hooks/useMatrixClient';
-import { genRoomVia } from '../../../util/matrixUtil';
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
import { Membership } from '../../../types/matrix/room';
import { RoomInputPlaceholder } from './RoomInputPlaceholder';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
+import { getViaServers } from '../../plugins/via-servers';
type RoomTombstoneProps = { roomId: string; body?: string; replacementRoomId: string };
export function RoomTombstone({ roomId, body, replacementRoomId }: RoomTombstoneProps) {
@@ -17,7 +17,7 @@ export function RoomTombstone({ roomId, body, replacementRoomId }: RoomTombstone
const [joinState, handleJoin] = useAsyncCallback(
useCallback(() => {
const currentRoom = mx.getRoom(roomId);
- const via = currentRoom ? genRoomVia(currentRoom) : [];
+ const via = currentRoom ? getViaServers(currentRoom) : [];
return mx.joinRoom(replacementRoomId, {
viaServers: via,
});
diff --git a/src/app/features/room/RoomView.tsx b/src/app/features/room/RoomView.tsx
index 3eabd528..250afc93 100644
--- a/src/app/features/room/RoomView.tsx
+++ b/src/app/features/room/RoomView.tsx
@@ -25,6 +25,7 @@ const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
if (evt.metaKey || evt.altKey || evt.ctrlKey) {
return false;
}
+
// do not focus on F keys
if (/^F\d+$/.test(code)) return false;
@@ -36,6 +37,9 @@ const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
code.startsWith('Alt') ||
code.startsWith('Control') ||
code.startsWith('Arrow') ||
+ code.startsWith('Page') ||
+ code.startsWith('End') ||
+ code.startsWith('Home') ||
code === 'Tab' ||
code === 'Space' ||
code === 'Enter' ||
diff --git a/src/app/features/room/RoomViewHeader.tsx b/src/app/features/room/RoomViewHeader.tsx
index 6750f923..eaa90970 100644
--- a/src/app/features/room/RoomViewHeader.tsx
+++ b/src/app/features/room/RoomViewHeader.tsx
@@ -20,7 +20,7 @@ import {
PopOut,
RectCords,
} from 'folds';
-import { useLocation, useNavigate } from 'react-router-dom';
+import { useNavigate } from 'react-router-dom';
import { JoinRule, Room } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai';
@@ -35,15 +35,8 @@ import { useRoom } from '../../hooks/useRoom';
import { useSetSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { useSpaceOptionally } from '../../hooks/useSpace';
-import {
- getHomeSearchPath,
- getOriginBaseUrl,
- getSpaceSearchPath,
- joinPathComponent,
- withOriginBaseUrl,
- withSearchParam,
-} from '../../pages/pathUtils';
-import { getCanonicalAliasOrRoomId } from '../../utils/matrix';
+import { getHomeSearchPath, getSpaceSearchPath, withSearchParam } from '../../pages/pathUtils';
+import { getCanonicalAliasOrRoomId, isRoomAlias, mxcUrlToHttp } from '../../utils/matrix';
import { _SearchPathSearchParams } from '../../pages/paths';
import * as css from './RoomViewHeader.css';
import { useRoomUnread } from '../../state/hooks/unread';
@@ -55,132 +48,135 @@ import { copyToClipboard } from '../../utils/dom';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
import { mDirectAtom } from '../../state/mDirectList';
-import { useClientConfig } from '../../hooks/useClientConfig';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { stopPropagation } from '../../utils/keyboard';
+import { getMatrixToRoom } from '../../plugins/matrix-to';
+import { getViaServers } from '../../plugins/via-servers';
+import { BackRouteHandler } from '../../components/BackRouteHandler';
+import { useSpecVersions } from '../../hooks/useSpecVersions';
type RoomMenuProps = {
room: Room;
- linkPath: string;
requestClose: () => void;
};
-const RoomMenu = forwardRef
(
- ({ room, linkPath, requestClose }, ref) => {
- const mx = useMatrixClient();
- const { hashRouter } = useClientConfig();
- const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
- const powerLevels = usePowerLevelsContext();
- const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
- const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
+const RoomMenu = forwardRef(({ room, requestClose }, ref) => {
+ const mx = useMatrixClient();
+ const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
+ const powerLevels = usePowerLevelsContext();
+ const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
+ const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
- const handleMarkAsRead = () => {
- markAsRead(mx, room.roomId);
- requestClose();
- };
+ const handleMarkAsRead = () => {
+ markAsRead(mx, room.roomId);
+ requestClose();
+ };
- const handleInvite = () => {
- openInviteUser(room.roomId);
- requestClose();
- };
+ const handleInvite = () => {
+ openInviteUser(room.roomId);
+ requestClose();
+ };
- const handleCopyLink = () => {
- copyToClipboard(withOriginBaseUrl(getOriginBaseUrl(hashRouter), linkPath));
- requestClose();
- };
+ const handleCopyLink = () => {
+ const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, room.roomId);
+ const viaServers = isRoomAlias(roomIdOrAlias) ? undefined : getViaServers(room);
+ copyToClipboard(getMatrixToRoom(roomIdOrAlias, viaServers));
+ requestClose();
+ };
- const handleRoomSettings = () => {
- toggleRoomSettings(room.roomId);
- requestClose();
- };
+ const handleRoomSettings = () => {
+ toggleRoomSettings(room.roomId);
+ requestClose();
+ };
- return (
-
- );
- }
-);
+ return (
+
+ );
+});
export function RoomViewHeader() {
const navigate = useNavigate();
const mx = useMatrixClient();
+ const { versions } = useSpecVersions();
+ const useAuthentication = versions.includes('v1.11');
const screenSize = useScreenSizeContext();
const room = useRoom();
const space = useSpaceOptionally();
@@ -192,11 +188,9 @@ export function RoomViewHeader() {
const avatarMxc = useRoomAvatar(room, mDirects.has(room.roomId));
const name = useRoomName(room);
const topic = useRoomTopic(room);
- const avatarUrl = avatarMxc ? mx.mxcUrlToHttp(avatarMxc, 96, 96, 'crop') ?? undefined : undefined;
+ const avatarUrl = avatarMxc ? mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined : undefined;
const setPeopleDrawer = useSetSetting(settingsAtom, 'isPeopleDrawer');
- const location = useLocation();
- const currentPath = joinPathComponent(location);
const handleSearchClick = () => {
const searchParams: _SearchPathSearchParams = {
@@ -213,19 +207,36 @@ export function RoomViewHeader() {
};
return (
-
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+
+
+ )}
+
+ )}
-
- (
-
- )}
- />
-
+ {screenSize !== ScreenSize.Mobile && (
+
+ (
+
+ )}
+ />
+
+ )}
{name}
@@ -336,11 +347,7 @@ export function RoomViewHeader() {
escapeDeactivates: stopPropagation,
}}
>
- setMenuAnchor(undefined)}
- />
+ setMenuAnchor(undefined)} />
}
/>
diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx
index 6db366ac..94a5825c 100644
--- a/src/app/features/room/message/Message.tsx
+++ b/src/app/features/room/message/Message.tsx
@@ -51,7 +51,7 @@ import {
getMemberAvatarMxc,
getMemberDisplayName,
} from '../../../utils/room';
-import { getCanonicalAliasOrRoomId, getMxIdLocalPart } from '../../../utils/matrix';
+import { getCanonicalAliasOrRoomId, getMxIdLocalPart, isRoomAlias, mxcUrlToHttp } from '../../../utils/matrix';
import { MessageLayout, MessageSpacing } from '../../../state/settings';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useRecentEmoji } from '../../../hooks/useRecentEmoji';
@@ -63,18 +63,11 @@ import { EmojiBoard } from '../../../components/emoji-board';
import { ReactionViewer } from '../reaction-viewer';
import { MessageEditor } from './MessageEditor';
import { UserAvatar } from '../../../components/user-avatar';
-import { useSpaceOptionally } from '../../../hooks/useSpace';
-import { useDirectSelected } from '../../../hooks/router/useDirectSelected';
-import {
- getDirectRoomPath,
- getHomeRoomPath,
- getOriginBaseUrl,
- getSpaceRoomPath,
- withOriginBaseUrl,
-} from '../../../pages/pathUtils';
import { copyToClipboard } from '../../../utils/dom';
-import { useClientConfig } from '../../../hooks/useClientConfig';
import { stopPropagation } from '../../../utils/keyboard';
+import { getMatrixToRoomEvent } from '../../../plugins/matrix-to';
+import { getViaServers } from '../../../plugins/via-servers';
+import { useSpecVersions } from '../../../hooks/useSpecVersions';
export type ReactionHandler = (keyOrMxc: string, shortcode: string) => void;
@@ -242,9 +235,9 @@ export const MessageSourceCodeItem = as<
const getContent = (evt: MatrixEvent) =>
evt.isEncrypted()
? {
- [`<== DECRYPTED_EVENT ==>`]: evt.getEffectiveEvent(),
- [`<== ORIGINAL_EVENT ==>`]: evt.event,
- }
+ [`<== DECRYPTED_EVENT ==>`]: evt.getEffectiveEvent(),
+ [`<== ORIGINAL_EVENT ==>`]: evt.event,
+ }
: evt.event;
const getText = (): string => {
@@ -321,23 +314,13 @@ export const MessageCopyLinkItem = as<
}
>(({ room, mEvent, onClose, ...props }, ref) => {
const mx = useMatrixClient();
- const { hashRouter } = useClientConfig();
- const space = useSpaceOptionally();
- const directSelected = useDirectSelected();
const handleCopy = () => {
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, room.roomId);
- let eventPath = getHomeRoomPath(roomIdOrAlias, mEvent.getId());
- if (space) {
- eventPath = getSpaceRoomPath(
- getCanonicalAliasOrRoomId(mx, space.roomId),
- roomIdOrAlias,
- mEvent.getId()
- );
- } else if (directSelected) {
- eventPath = getDirectRoomPath(roomIdOrAlias, mEvent.getId());
- }
- copyToClipboard(withOriginBaseUrl(getOriginBaseUrl(hashRouter), eventPath));
+ const eventId = mEvent.getId();
+ const viaServers = isRoomAlias(roomIdOrAlias) ? undefined : getViaServers(room);
+ if (!eventId) return;
+ copyToClipboard(getMatrixToRoomEvent(roomIdOrAlias, eventId, viaServers));
onClose?.();
};
@@ -668,6 +651,8 @@ export const Message = as<'div', MessageProps>(
ref
) => {
const mx = useMatrixClient();
+ const { versions } = useSpecVersions();
+ const useAuthentication = versions.includes('v1.11');
const senderId = mEvent.getSender() ?? '';
const [hover, setHover] = useState(false);
const { hoverProps } = useHover({ onHoverChange: setHover });
@@ -727,7 +712,7 @@ export const Message = as<'div', MessageProps>(
userId={senderId}
src={
senderAvatarMxc
- ? mx.mxcUrlToHttp(senderAvatarMxc, 48, 48, 'crop') ?? undefined
+ ? mxcUrlToHttp(mx, senderAvatarMxc, useAuthentication, 48, 48, 'crop') ?? undefined
: undefined
}
alt={senderDisplayName}
@@ -968,26 +953,26 @@ export const Message = as<'div', MessageProps>(
{((!mEvent.isRedacted() && canDelete) ||
mEvent.getSender() !== mx.getUserId()) && (
- <>
-
-
- {!mEvent.isRedacted() && canDelete && (
-
- )}
- {mEvent.getSender() !== mx.getUserId() && (
-
- )}
-
- >
- )}
+ <>
+
+
+ {!mEvent.isRedacted() && canDelete && (
+
+ )}
+ {mEvent.getSender() !== mx.getUserId() && (
+
+ )}
+
+ >
+ )}
}
@@ -1111,26 +1096,26 @@ export const Event = as<'div', EventProps>(
{((!mEvent.isRedacted() && canDelete && !stateEvent) ||
(mEvent.getSender() !== mx.getUserId() && !stateEvent)) && (
- <>
-
-
- {!mEvent.isRedacted() && canDelete && (
-
- )}
- {mEvent.getSender() !== mx.getUserId() && (
-
- )}
-
- >
- )}
+ <>
+
+
+ {!mEvent.isRedacted() && canDelete && (
+
+ )}
+ {mEvent.getSender() !== mx.getUserId() && (
+
+ )}
+
+ >
+ )}
}
diff --git a/src/app/features/room/message/Reactions.tsx b/src/app/features/room/message/Reactions.tsx
index a6d7f553..258ab629 100644
--- a/src/app/features/room/message/Reactions.tsx
+++ b/src/app/features/room/message/Reactions.tsx
@@ -22,6 +22,7 @@ import { useRelations } from '../../../hooks/useRelations';
import * as css from './styles.css';
import { ReactionViewer } from '../reaction-viewer';
import { stopPropagation } from '../../../utils/keyboard';
+import { useSpecVersions } from '../../../hooks/useSpecVersions';
export type ReactionsProps = {
room: Room;
@@ -33,6 +34,8 @@ export type ReactionsProps = {
export const Reactions = as<'div', ReactionsProps>(
({ className, room, relations, mEventId, canSendReaction, onReactionToggle, ...props }, ref) => {
const mx = useMatrixClient();
+ const { versions } = useSpecVersions();
+ const useAuthentication = versions.includes('v1.11');
const [viewer, setViewer] = useState(false);
const myUserId = mx.getUserId();
const reactions = useRelations(
@@ -86,6 +89,7 @@ export const Reactions = as<'div', ReactionsProps>(
onClick={canSendReaction ? () => onReactionToggle(mEventId, key) : undefined}
onContextMenu={handleViewReaction}
aria-disabled={!canSendReaction}
+ useAuthentication={useAuthentication}
/>
)}
diff --git a/src/app/features/room/reaction-viewer/ReactionViewer.tsx b/src/app/features/room/reaction-viewer/ReactionViewer.tsx
index 1c1b79a7..9e166a9e 100644
--- a/src/app/features/room/reaction-viewer/ReactionViewer.tsx
+++ b/src/app/features/room/reaction-viewer/ReactionViewer.tsx
@@ -25,6 +25,7 @@ import { useRelations } from '../../../hooks/useRelations';
import { Reaction } from '../../../components/message';
import { getHexcodeForEmoji, getShortcodeFor } from '../../../plugins/emoji';
import { UserAvatar } from '../../../components/user-avatar';
+import { useSpecVersions } from '../../../hooks/useSpecVersions';
export type ReactionViewerProps = {
room: Room;
@@ -35,6 +36,8 @@ export type ReactionViewerProps = {
export const ReactionViewer = as<'div', ReactionViewerProps>(
({ className, room, initialKey, relations, requestClose, ...props }, ref) => {
const mx = useMatrixClient();
+ const { versions } = useSpecVersions();
+ const useAuthentication = versions.includes('v1.11');
const reactions = useRelations(
relations,
useCallback((rel) => [...(rel.getSortedAnnotationsByKey() ?? [])], [])
@@ -81,6 +84,7 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
count={evts.size}
aria-selected={key === selectedKey}
onClick={() => setSelectedKey(key)}
+ useAuthentication={useAuthentication}
/>
);
})}
@@ -107,14 +111,16 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
const member = room.getMember(senderId);
const name = (member ? getName(member) : getMxIdLocalPart(senderId)) ?? senderId;
- const avatarUrl = member?.getAvatarUrl(
- mx.baseUrl,
+ const avatarMxcUrl = member?.getMxcAvatarUrl();
+ const avatarUrl = avatarMxcUrl ? mx.mxcUrlToHttp(
+ avatarMxcUrl,
100,
100,
'crop',
undefined,
- false
- );
+ false,
+ useAuthentication
+ ) : undefined;
return (