import React, { useCallback, useMemo, useRef } from 'react'; import { Box, Text, config } from 'folds'; import { EventType } from 'matrix-js-sdk'; import { ReactEditor } from 'slate-react'; import { isKeyHotkey } from 'is-hotkey'; import { useStateEvent } from '../../hooks/useStateEvent'; import { StateEvent } from '../../../types/matrix/room'; import { usePowerLevelsContext } from '../../hooks/usePowerLevels'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { useEditor } from '../../components/editor'; import { RoomInputPlaceholder } from './RoomInputPlaceholder'; import { RoomTimeline } from './RoomTimeline'; import { RoomViewTyping } from './RoomViewTyping'; import { RoomTombstone } from './RoomTombstone'; import { RoomInput } from './RoomInput'; import { RoomViewFollowing, RoomViewFollowingPlaceholder } from './RoomViewFollowing'; import { Page } from '../../components/page'; import { useSetting } from '../../state/hooks/settings'; import { settingsAtom } from '../../state/settings'; import { useTheme, ThemeKind } from '../../hooks/useTheme'; import { getChatBg } from '../lotus/chatBackground'; import { useKeyDown } from '../../hooks/useKeyDown'; import { editableActiveElement } from '../../utils/dom'; import { useRoomPermissions } from '../../hooks/useRoomPermissions'; import { useRoomCreators } from '../../hooks/useRoomCreators'; import { useRoom } from '../../hooks/useRoom'; const FN_KEYS_REGEX = /^F\d+$/; const shouldFocusMessageField = (evt: KeyboardEvent): boolean => { const { code } = evt; if (evt.metaKey || evt.altKey || evt.ctrlKey) { return false; } if (FN_KEYS_REGEX.test(code)) return false; if ( code.startsWith('OS') || code.startsWith('Meta') || code.startsWith('Shift') || code.startsWith('Alt') || code.startsWith('Control') || code.startsWith('Arrow') || code.startsWith('Page') || code.startsWith('End') || code.startsWith('Home') || code === 'Tab' || code === 'Space' || code === 'Enter' || code === 'NumLock' || code === 'ScrollLock' ) { return false; } return true; }; export function RoomView({ eventId }: { eventId?: string }) { const roomInputRef = useRef(null) as React.RefObject; const roomViewRef = useRef(null) as React.RefObject; const [chatBackground] = useSetting(settingsAtom, 'chatBackground'); const [lotusTerminal] = useSetting(settingsAtom, 'lotusTerminal'); const [pauseAnimations] = useSetting(settingsAtom, 'pauseAnimations'); const theme = useTheme(); const isDark = theme.kind === ThemeKind.Dark; const [hideActivity] = useSetting(settingsAtom, 'hideActivity'); const room = useRoom(); const { roomId } = room; const editor = useEditor(); const mx = useMatrixClient(); const tombstoneEvent = useStateEvent(room, StateEvent.RoomTombstone); const powerLevels = usePowerLevelsContext(); const creators = useRoomCreators(room); const permissions = useRoomPermissions(creators, powerLevels); const canMessage = permissions.event(EventType.RoomMessage, mx.getSafeUserId()); useKeyDown( window, useCallback( (evt) => { if (editableActiveElement()) return; const portalContainer = document.getElementById('portalContainer'); if (portalContainer && portalContainer.children.length > 0) { return; } if (shouldFocusMessageField(evt) || isKeyHotkey('mod+v', evt)) { ReactEditor.focus(editor); } }, [editor], ), ); // Apply the background directly to Page so it overrides PageRoot's opaque // Background.Container color. SidebarNav mirrors it onto document.body separately // so the glassmorphism sidebar can blur through it. const chatBgStyle = useMemo(() => { if (chatBackground !== 'none') return getChatBg(chatBackground, isDark, pauseAnimations); if (lotusTerminal) return getChatBg('tactical', isDark, pauseAnimations); return {}; }, [chatBackground, lotusTerminal, isDark, pauseAnimations]); return (
{tombstoneEvent ? ( ) : ( <> {canMessage && ( )} {!canMessage && ( You do not have permission to post in this room )} )}
{hideActivity ? : }
); }