fix: media gallery encrypted rooms + Ctrl+K double-menu
- MediaGallery: switch from createMessagesRequest (returns raw encrypted events) to room.getLiveTimeline().getEvents() which gives already- decrypted MatrixEvent objects. Load More uses paginateEventTimeline(). - QuickSwitcher: change hotkey from Ctrl+K to Ctrl+P to avoid conflict with the existing SearchModalRenderer mod+k handler Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
config,
|
config,
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
import { Direction, EventType, MatrixEvent, MsgType, Room } from 'matrix-js-sdk';
|
import { EventType, MsgType, Room } from 'matrix-js-sdk';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
||||||
import { mxcUrlToHttp } from '../../utils/matrix';
|
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||||
@@ -65,53 +65,45 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
|||||||
const useAuthentication = useMediaAuthentication();
|
const useAuthentication = useMediaAuthentication();
|
||||||
|
|
||||||
const [tab, setTab] = useState<GalleryTab>('image');
|
const [tab, setTab] = useState<GalleryTab>('image');
|
||||||
const [events, setEvents] = useState<MatrixEvent[]>([]);
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [paginationToken, setPaginationToken] = useState<string | null>(null);
|
const [canLoadMore, setCanLoadMore] = useState(true);
|
||||||
|
|
||||||
const msgtype = TAB_MSGTYPES[tab];
|
const msgtype = TAB_MSGTYPES[tab];
|
||||||
|
|
||||||
const loadMedia = useCallback(
|
// Read already-decrypted events from the live timeline (works for E2EE rooms)
|
||||||
async (fromToken: string | null, append: boolean) => {
|
const getFilteredEvents = useCallback(() => {
|
||||||
setLoading(true);
|
const timeline = room.getLiveTimeline();
|
||||||
try {
|
return timeline
|
||||||
const response = await mx.createMessagesRequest(
|
.getEvents()
|
||||||
room.roomId,
|
.filter((ev) => {
|
||||||
fromToken,
|
if (ev.isRedacted()) return false;
|
||||||
100,
|
const content = ev.getContent();
|
||||||
Direction.Backward,
|
return ev.getType() === EventType.RoomMessage && content.msgtype === msgtype;
|
||||||
undefined,
|
})
|
||||||
);
|
.slice()
|
||||||
const { end, chunk } = response;
|
.reverse(); // newest first
|
||||||
const filtered = chunk
|
}, [room, msgtype]);
|
||||||
.filter(
|
|
||||||
(ev) =>
|
|
||||||
ev.type === EventType.RoomMessage &&
|
|
||||||
ev.content?.msgtype === msgtype &&
|
|
||||||
!ev.unsigned?.redacted_because,
|
|
||||||
)
|
|
||||||
.map((ev) => new MatrixEvent(ev));
|
|
||||||
|
|
||||||
setEvents((prev) => (append ? [...prev, ...filtered] : filtered));
|
const [events, setEvents] = useState(() => getFilteredEvents());
|
||||||
setPaginationToken(end ?? null);
|
|
||||||
} catch {
|
|
||||||
// silently swallow fetch errors — gallery stays showing what it has
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[mx, room.roomId, msgtype],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setEvents([]);
|
setEvents(getFilteredEvents());
|
||||||
setPaginationToken(null);
|
setCanLoadMore(true);
|
||||||
loadMedia(null, false).catch(() => undefined);
|
}, [getFilteredEvents]);
|
||||||
}, [loadMedia]);
|
|
||||||
|
|
||||||
const handleLoadMore = () => {
|
const handleLoadMore = useCallback(async () => {
|
||||||
if (paginationToken) loadMedia(paginationToken, true).catch(() => undefined);
|
setLoading(true);
|
||||||
};
|
try {
|
||||||
|
const timeline = room.getLiveTimeline();
|
||||||
|
const hasMore = await mx.paginateEventTimeline(timeline, { backwards: true, limit: 100 });
|
||||||
|
setEvents(getFilteredEvents());
|
||||||
|
setCanLoadMore(hasMore);
|
||||||
|
} catch {
|
||||||
|
// silently swallow
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, [mx, room, getFilteredEvents]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -306,7 +298,7 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Load more */}
|
{/* Load more */}
|
||||||
{paginationToken !== null && !loading && (
|
{canLoadMore && !loading && events.length > 0 && (
|
||||||
<Box justifyContent="Center" style={{ padding: config.space.S200 }}>
|
<Box justifyContent="Center" style={{ padding: config.space.S200 }}>
|
||||||
<Button
|
<Button
|
||||||
size="300"
|
size="300"
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ function QuickSwitcherFeature() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
if ((e.ctrlKey || e.metaKey) && e.key === 'p') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user