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,
+ };
+};