import React, { MouseEventHandler, useCallback, useMemo, useState } from 'react'; import { Button, color, config, Icon, Icons, Menu, MenuItem, PopOut, RectCords, Spinner, Text, } from 'folds'; import { HistoryVisibility, MatrixError } from 'matrix-js-sdk'; import { RoomHistoryVisibilityEventContent } from 'matrix-js-sdk/lib/types'; import FocusTrap from 'focus-trap-react'; import { useTranslation } from 'react-i18next'; import { SequenceCard } from '../../../components/sequence-card'; import { SequenceCardStyle } from '../../room-settings/styles.css'; import { SettingTile } from '../../../components/setting-tile'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { useRoom } from '../../../hooks/useRoom'; import { StateEvent } from '../../../../types/matrix/room'; import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; import { useStateEvent } from '../../../hooks/useStateEvent'; import { stopPropagation } from '../../../utils/keyboard'; import { RoomPermissionsAPI } from '../../../hooks/useRoomPermissions'; const useVisibilityStr = () => { const { t } = useTranslation(); return useMemo( () => ({ [HistoryVisibility.Invited]: t('RoomSettings.visibility_after_invite'), [HistoryVisibility.Joined]: t('RoomSettings.visibility_after_join'), [HistoryVisibility.Shared]: t('RoomSettings.visibility_all_messages'), [HistoryVisibility.WorldReadable]: t('RoomSettings.visibility_all_messages_guests'), }), [t] ); }; const useVisibilityMenu = () => useMemo( () => [ HistoryVisibility.Shared, HistoryVisibility.Invited, HistoryVisibility.Joined, HistoryVisibility.WorldReadable, ], [] ); type RoomHistoryVisibilityProps = { permissions: RoomPermissionsAPI; }; export function RoomHistoryVisibility({ permissions }: RoomHistoryVisibilityProps) { const { t } = useTranslation(); const mx = useMatrixClient(); const room = useRoom(); const canEdit = permissions.stateEvent(StateEvent.RoomHistoryVisibility, mx.getSafeUserId()); const visibilityEvent = useStateEvent(room, StateEvent.RoomHistoryVisibility); const historyVisibility: HistoryVisibility = visibilityEvent?.getContent().history_visibility ?? HistoryVisibility.Shared; const visibilityMenu = useVisibilityMenu(); const visibilityStr = useVisibilityStr(); const [menuAnchor, setMenuAnchor] = useState(); const handleOpenMenu: MouseEventHandler = (evt) => { setMenuAnchor(evt.currentTarget.getBoundingClientRect()); }; const [submitState, submit] = useAsyncCallback( useCallback( async (visibility: HistoryVisibility) => { const content: RoomHistoryVisibilityEventContent = { history_visibility: visibility, }; await mx.sendStateEvent(room.roomId, StateEvent.RoomHistoryVisibility as any, content); }, [mx, room.roomId] ) ); const submitting = submitState.status === AsyncStatus.Loading; const handleChange = (visibility: HistoryVisibility) => { submit(visibility); setMenuAnchor(undefined); }; return ( setMenuAnchor(undefined), clickOutsideDeactivates: true, isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown', isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp', escapeDeactivates: stopPropagation, }} > {visibilityMenu.map((visibility) => ( handleChange(visibility)} aria-pressed={visibility === historyVisibility} > {visibilityStr[visibility]} ))} } > } > {submitState.status === AsyncStatus.Error && ( {(submitState.error as MatrixError).message} )} ); }