mirror of
https://github.com/RGBCube/cinny
synced 2025-07-30 16:37:46 +00:00
Add room upgrade option in room settings (#2280)
* add room upgrade option in room settings * update upgrade room dialog styles
This commit is contained in:
parent
f688e2d1ae
commit
c16e060f73
2 changed files with 222 additions and 0 deletions
|
@ -8,6 +8,7 @@ import { RoomEncryption } from './RoomEncryption';
|
||||||
import { RoomHistoryVisibility } from './RoomHistoryVisibility';
|
import { RoomHistoryVisibility } from './RoomHistoryVisibility';
|
||||||
import { RoomJoinRules } from './RoomJoinRules';
|
import { RoomJoinRules } from './RoomJoinRules';
|
||||||
import { RoomLocalAddresses, RoomPublishedAddresses } from './RoomAddress';
|
import { RoomLocalAddresses, RoomPublishedAddresses } from './RoomAddress';
|
||||||
|
import { RoomUpgrade } from './RoomUpgrade';
|
||||||
|
|
||||||
type GeneralProps = {
|
type GeneralProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
|
@ -48,6 +49,10 @@ export function General({ requestClose }: GeneralProps) {
|
||||||
<RoomPublishedAddresses powerLevels={powerLevels} />
|
<RoomPublishedAddresses powerLevels={powerLevels} />
|
||||||
<RoomLocalAddresses powerLevels={powerLevels} />
|
<RoomLocalAddresses powerLevels={powerLevels} />
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box direction="Column" gap="100">
|
||||||
|
<Text size="L400">Advance Options</Text>
|
||||||
|
<RoomUpgrade powerLevels={powerLevels} requestClose={requestClose} />
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
</Scroll>
|
</Scroll>
|
||||||
|
|
217
src/app/features/room-settings/general/RoomUpgrade.tsx
Normal file
217
src/app/features/room-settings/general/RoomUpgrade.tsx
Normal file
|
@ -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<RoomCreateEventContent>();
|
||||||
|
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<RoomTombstoneEventContent>();
|
||||||
|
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<HTMLFormElement> = (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 (
|
||||||
|
<SequenceCard
|
||||||
|
className={SequenceCardStyle}
|
||||||
|
variant="SurfaceVariant"
|
||||||
|
direction="Column"
|
||||||
|
gap="400"
|
||||||
|
>
|
||||||
|
<SettingTile
|
||||||
|
title="Upgrade Room"
|
||||||
|
description={
|
||||||
|
replacementRoom
|
||||||
|
? tombstoneContent.body || 'This room has been replaced!'
|
||||||
|
: `Current room version: ${roomVersion}.`
|
||||||
|
}
|
||||||
|
after={
|
||||||
|
<Box alignItems="Center" gap="200">
|
||||||
|
{predecessorRoomId && (
|
||||||
|
<Button
|
||||||
|
size="300"
|
||||||
|
variant="Secondary"
|
||||||
|
fill="Soft"
|
||||||
|
outlined
|
||||||
|
radii="300"
|
||||||
|
onClick={handleOpenOldRoom}
|
||||||
|
>
|
||||||
|
<Text size="B300">Old Room</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{replacementRoom ? (
|
||||||
|
<Button
|
||||||
|
size="300"
|
||||||
|
variant="Success"
|
||||||
|
fill="Solid"
|
||||||
|
radii="300"
|
||||||
|
onClick={handleOpenRoom}
|
||||||
|
>
|
||||||
|
<Text size="B300">Open New Room</Text>
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
size="300"
|
||||||
|
variant="Secondary"
|
||||||
|
fill="Solid"
|
||||||
|
radii="300"
|
||||||
|
disabled={upgrading || !canUpgrade}
|
||||||
|
before={upgrading && <Spinner size="100" variant="Secondary" fill="Solid" />}
|
||||||
|
onClick={() => setPrompt(true)}
|
||||||
|
>
|
||||||
|
<Text size="B300">Upgrade</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{upgradeState.status === AsyncStatus.Error && (
|
||||||
|
<Text style={{ color: color.Critical.Main }} size="T200">
|
||||||
|
{(upgradeState.error as MatrixError).message}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{prompt && (
|
||||||
|
<Overlay open backdrop={<OverlayBackdrop />}>
|
||||||
|
<OverlayCenter>
|
||||||
|
<FocusTrap
|
||||||
|
focusTrapOptions={{
|
||||||
|
initialFocus: false,
|
||||||
|
onDeactivate: () => setPrompt(false),
|
||||||
|
clickOutsideDeactivates: true,
|
||||||
|
escapeDeactivates: stopPropagation,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Dialog variant="Surface" as="form" onSubmit={handleSubmitUpgrade}>
|
||||||
|
<Header
|
||||||
|
style={{
|
||||||
|
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
||||||
|
borderBottomWidth: config.borderWidth.B300,
|
||||||
|
}}
|
||||||
|
variant="Surface"
|
||||||
|
size="500"
|
||||||
|
>
|
||||||
|
<Box grow="Yes">
|
||||||
|
<Text size="H4">Room Upgrade</Text>
|
||||||
|
</Box>
|
||||||
|
<IconButton size="300" onClick={() => setPrompt(false)} radii="300">
|
||||||
|
<Icon src={Icons.Cross} />
|
||||||
|
</IconButton>
|
||||||
|
</Header>
|
||||||
|
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
||||||
|
<Text priority="400" style={{ color: color.Critical.Main }}>
|
||||||
|
<b>This action is irreversible!</b>
|
||||||
|
</Text>
|
||||||
|
<Box direction="Column" gap="100">
|
||||||
|
<Text size="L400">Version</Text>
|
||||||
|
<Input
|
||||||
|
defaultValue={defaultRoomVersion}
|
||||||
|
name="versionInput"
|
||||||
|
variant="Background"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Button type="submit" variant="Secondary">
|
||||||
|
<Text size="B400">Upgrade Room</Text>
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Dialog>
|
||||||
|
</FocusTrap>
|
||||||
|
</OverlayCenter>
|
||||||
|
</Overlay>
|
||||||
|
)}
|
||||||
|
</SettingTile>
|
||||||
|
</SequenceCard>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue