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 { SequenceCard } from '../../../components/sequence-card'; import { SequenceCardStyle } from '../../room-settings/styles.css'; import { SettingTile } from '../../../components/setting-tile'; import { IPowerLevels, powerLevelAPI } from '../../../hooks/usePowerLevels'; 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'; const useVisibilityStr = () => useMemo( () => ({ [HistoryVisibility.Invited]: 'After Invite', [HistoryVisibility.Joined]: 'After Join', [HistoryVisibility.Shared]: 'All Messages', [HistoryVisibility.WorldReadable]: 'All Messages (Guests)', }), [] ); const useVisibilityMenu = () => useMemo( () => [ HistoryVisibility.Shared, HistoryVisibility.Invited, HistoryVisibility.Joined, HistoryVisibility.WorldReadable, ], [] ); type RoomHistoryVisibilityProps = { powerLevels: IPowerLevels; }; export function RoomHistoryVisibility({ powerLevels }: RoomHistoryVisibilityProps) { const mx = useMatrixClient(); const room = useRoom(); const userPowerLevel = powerLevelAPI.getPowerLevel(powerLevels, mx.getSafeUserId()); const canEdit = powerLevelAPI.canSendStateEvent( powerLevels, StateEvent.RoomHistoryVisibility, userPowerLevel ); 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} )} ); }