diff --git a/src/app/features/room-settings/general/General.tsx b/src/app/features/room-settings/general/General.tsx index 6d66406..1033c30 100644 --- a/src/app/features/room-settings/general/General.tsx +++ b/src/app/features/room-settings/general/General.tsx @@ -8,6 +8,7 @@ import { RoomEncryption } from './RoomEncryption'; import { RoomHistoryVisibility } from './RoomHistoryVisibility'; import { RoomJoinRules } from './RoomJoinRules'; import { RoomLocalAddresses, RoomPublishedAddresses } from './RoomAddress'; +import { RoomUpgrade } from './RoomUpgrade'; type GeneralProps = { requestClose: () => void; @@ -48,6 +49,10 @@ export function General({ requestClose }: GeneralProps) { + + Advance Options + + diff --git a/src/app/features/room-settings/general/RoomUpgrade.tsx b/src/app/features/room-settings/general/RoomUpgrade.tsx new file mode 100644 index 0000000..fa1fa85 --- /dev/null +++ b/src/app/features/room-settings/general/RoomUpgrade.tsx @@ -0,0 +1,217 @@ +import React, { FormEventHandler, useCallback, useState } from 'react'; +import { + Button, + color, + Spinner, + Text, + Overlay, + OverlayBackdrop, + OverlayCenter, + Dialog, + Header, + config, + Box, + IconButton, + Icon, + Icons, + Input, +} from 'folds'; +import FocusTrap from 'focus-trap-react'; +import { MatrixError } from 'matrix-js-sdk'; +import { RoomCreateEventContent, RoomTombstoneEventContent } from 'matrix-js-sdk/lib/types'; +import { SequenceCard } from '../../../components/sequence-card'; +import { SequenceCardStyle } from '../styles.css'; +import { SettingTile } from '../../../components/setting-tile'; +import { useRoom } from '../../../hooks/useRoom'; +import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; +import { IPowerLevels, powerLevelAPI } from '../../../hooks/usePowerLevels'; +import { StateEvent } from '../../../../types/matrix/room'; +import { useMatrixClient } from '../../../hooks/useMatrixClient'; +import { useStateEvent } from '../../../hooks/useStateEvent'; +import { useRoomNavigate } from '../../../hooks/useRoomNavigate'; +import { useCapabilities } from '../../../hooks/useCapabilities'; +import { stopPropagation } from '../../../utils/keyboard'; + +type RoomUpgradeProps = { + powerLevels: IPowerLevels; + requestClose: () => void; +}; +export function RoomUpgrade({ powerLevels, requestClose }: RoomUpgradeProps) { + const mx = useMatrixClient(); + const room = useRoom(); + const { navigateRoom } = useRoomNavigate(); + const createContent = useStateEvent( + room, + StateEvent.RoomCreate + )?.getContent(); + const roomVersion = createContent?.room_version ?? 1; + const predecessorRoomId = createContent?.predecessor?.room_id; + + const capabilities = useCapabilities(); + const defaultRoomVersion = capabilities['m.room_versions']?.default; + + const tombstoneContent = useStateEvent( + room, + StateEvent.RoomTombstone + )?.getContent(); + const replacementRoom = tombstoneContent?.replacement_room; + + const userPowerLevel = powerLevelAPI.getPowerLevel(powerLevels, mx.getSafeUserId()); + const canUpgrade = powerLevelAPI.canSendStateEvent( + powerLevels, + StateEvent.RoomTombstone, + userPowerLevel + ); + + const handleOpenRoom = () => { + if (replacementRoom) { + requestClose(); + navigateRoom(replacementRoom); + } + }; + + const handleOpenOldRoom = () => { + if (predecessorRoomId) { + requestClose(); + navigateRoom(predecessorRoomId, createContent.predecessor?.event_id); + } + }; + + const [upgradeState, upgrade] = useAsyncCallback( + useCallback( + async (version: string) => { + await mx.upgradeRoom(room.roomId, version); + }, + [mx, room] + ) + ); + + const upgrading = upgradeState.status === AsyncStatus.Loading; + + const [prompt, setPrompt] = useState(false); + + const handleSubmitUpgrade: FormEventHandler = (evt) => { + evt.preventDefault(); + + const target = evt.target as HTMLFormElement | undefined; + const versionInput = target?.versionInput as HTMLInputElement | undefined; + const version = versionInput?.value.trim(); + if (!version) return; + + upgrade(version); + setPrompt(false); + }; + + return ( + + + {predecessorRoomId && ( + + )} + {replacementRoom ? ( + + ) : ( + + )} + + } + > + {upgradeState.status === AsyncStatus.Error && ( + + {(upgradeState.error as MatrixError).message} + + )} + + {prompt && ( + }> + + setPrompt(false), + clickOutsideDeactivates: true, + escapeDeactivates: stopPropagation, + }} + > + +
+ + Room Upgrade + + setPrompt(false)} radii="300"> + + +
+ + + This action is irreversible! + + + Version + + + + +
+
+
+
+ )} +
+
+ ); +}