From 074a5e855d2c112615f0b5a095f6cafbdf1dce41 Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Thu, 20 Mar 2025 20:25:31 +1100 Subject: [PATCH] Add publish to directory toggle in room settings (#2279) --- .../room-settings/general/General.tsx | 2 + .../room-settings/general/RoomPublish.tsx | 70 +++++++++++++++++++ src/app/hooks/useRoomDirectoryVisibility.ts | 35 ++++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/app/features/room-settings/general/RoomPublish.tsx create mode 100644 src/app/hooks/useRoomDirectoryVisibility.ts diff --git a/src/app/features/room-settings/general/General.tsx b/src/app/features/room-settings/general/General.tsx index 1033c30..3d217f3 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 { RoomPublish } from './RoomPublish'; import { RoomUpgrade } from './RoomUpgrade'; type GeneralProps = { @@ -43,6 +44,7 @@ export function General({ requestClose }: GeneralProps) { + Addresses diff --git a/src/app/features/room-settings/general/RoomPublish.tsx b/src/app/features/room-settings/general/RoomPublish.tsx new file mode 100644 index 0000000..d17f70e --- /dev/null +++ b/src/app/features/room-settings/general/RoomPublish.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { Box, color, Spinner, Switch, Text } from 'folds'; +import { MatrixError } from 'matrix-js-sdk'; +import { SequenceCard } from '../../../components/sequence-card'; +import { SequenceCardStyle } from '../styles.css'; +import { SettingTile } from '../../../components/setting-tile'; +import { useRoom } from '../../../hooks/useRoom'; +import { useRoomDirectoryVisibility } from '../../../hooks/useRoomDirectoryVisibility'; +import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback'; +import { IPowerLevels, powerLevelAPI } from '../../../hooks/usePowerLevels'; +import { StateEvent } from '../../../../types/matrix/room'; +import { useMatrixClient } from '../../../hooks/useMatrixClient'; + +type RoomPublishProps = { + powerLevels: IPowerLevels; +}; +export function RoomPublish({ powerLevels }: RoomPublishProps) { + const mx = useMatrixClient(); + const room = useRoom(); + const userPowerLevel = powerLevelAPI.getPowerLevel(powerLevels, mx.getSafeUserId()); + const canEditCanonical = powerLevelAPI.canSendStateEvent( + powerLevels, + StateEvent.RoomCanonicalAlias, + userPowerLevel + ); + + const { visibilityState, setVisibility } = useRoomDirectoryVisibility(room.roomId); + + const [toggleState, toggleVisibility] = useAsyncCallback(setVisibility); + + const loading = + visibilityState.status === AsyncStatus.Loading || toggleState.status === AsyncStatus.Loading; + + return ( + + + {loading && } + {!loading && visibilityState.status === AsyncStatus.Success && ( + + )} + + } + > + {visibilityState.status === AsyncStatus.Error && ( + + {(visibilityState.error as MatrixError).message} + + )} + + {toggleState.status === AsyncStatus.Error && ( + + {(toggleState.error as MatrixError).message} + + )} + + + ); +} diff --git a/src/app/hooks/useRoomDirectoryVisibility.ts b/src/app/hooks/useRoomDirectoryVisibility.ts new file mode 100644 index 0000000..6a60601 --- /dev/null +++ b/src/app/hooks/useRoomDirectoryVisibility.ts @@ -0,0 +1,35 @@ +import { useCallback, useEffect } from 'react'; +import { Visibility } from 'matrix-js-sdk'; +import { useAsyncCallback } from './useAsyncCallback'; +import { useMatrixClient } from './useMatrixClient'; + +export const useRoomDirectoryVisibility = (roomId: string) => { + const mx = useMatrixClient(); + + const [visibilityState, loadVisibility] = useAsyncCallback( + useCallback(async () => { + const v = await mx.getRoomDirectoryVisibility(roomId); + return v.visibility === Visibility.Public; + }, [mx, roomId]) + ); + + useEffect(() => { + loadVisibility(); + }, [loadVisibility]); + + const setVisibility = useCallback( + async (visibility: boolean) => { + await mx.setRoomDirectoryVisibility( + roomId, + visibility ? Visibility.Public : Visibility.Private + ); + await loadVisibility(); + }, + [mx, roomId, loadVisibility] + ); + + return { + visibilityState, + setVisibility, + }; +};