move space settings to new sdk

This commit is contained in:
Ajay Bura 2026-07-24 20:58:25 +05:30
commit 4da96b68f1
7 changed files with 152 additions and 119 deletions

View file

@ -66,7 +66,7 @@ export function UserHeroCover({
avatarUrl === bannerUrl && css.UserHeroCoverBlurred
)}
src={bannerUrl}
alt="{userId}"
alt={userId}
draggable="false"
onError={() => setError(true)}
/>

View file

@ -22,6 +22,7 @@ export const UserHeroCover = style({
height: '100%',
width: '100%',
objectFit: 'cover',
fontSize: 1,
});
export const UserHeroCoverBlurred = style({
filter: 'blur(16px)',

View file

@ -1,14 +1,8 @@
import React, { useMemo, useState } from 'react';
import { useAtomValue } from 'jotai';
import { Avatar, Box, config, Icon, IconButton, Icons, IconSrc, MenuItem, Text } from 'folds';
import { JoinRule } from 'matrix-js-sdk';
import { PageNav, PageNavContent, PageNavHeader, PageRoot } from '../../components/page';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { mxcUrlToHttp } from '../../utils/matrix';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useRoomAvatar, useRoomJoinRule, useRoomName } from '../../hooks/useRoomMeta';
import { mDirectAtom } from '../../state/mDirectList';
import { RoomAvatar, RoomIcon } from '../../components/room-avatar';
import { SpaceSettingsPage } from '../../state/spaceSettings';
import { useRoom } from '../../hooks/useRoom';
@ -17,6 +11,24 @@ import { Members } from '../common-settings/members';
import { DeveloperTools } from '../common-settings/developer-tools';
import { General } from './general';
import { Permissions } from './permissions';
import { useClient } from '../../hooks/useClient';
import { useRoomHeroes } from '../../hooks/storage/useRoomHeros';
import { useGetRoomName } from '../../hooks/storage/useGetRoomName';
import { useGetRoomAvatar } from '../../hooks/storage/useGetRoomAvatar';
import {
PowerLevelsContextProvider,
usePowerLevels,
usePowerLevelsState,
} from '../../hooks/usePowerLevels';
import {
PowerLevelTagsContextProvider,
usePowerLevelTags,
usePowerLevelTagsState,
} from '../../hooks/usePowerLevelTags';
import { RoomMembersAPIProvider, useCreateRoomMembersAPI } from '../../hooks/useRoomMembers';
import { usePendingMemberLoader, usePendingMembers } from '../../hooks/usePendingMembers';
import { useObservableValue } from '../../hooks/useObservableValue';
import { mxcToHttp } from '../../../client/mxcToHttp';
type SpaceSettingsMenuItem = {
page: SpaceSettingsPage;
@ -61,17 +73,33 @@ type SpaceSettingsProps = {
requestClose: () => void;
};
export function SpaceSettings({ initialPage, requestClose }: SpaceSettingsProps) {
const room = useRoom();
const mx = useMatrixClient();
const ct = useClient();
const roomId = useRoom();
const useAuthentication = useMediaAuthentication();
const mDirects = useAtomValue(mDirectAtom);
const roomAvatar = useRoomAvatar(room, mDirects.has(room.roomId));
const roomName = useRoomName(room);
const joinRuleContent = useRoomJoinRule(room);
const [getRoomHeroes, roomToHeroMembersResult] = useRoomHeroes(roomId);
const getRoomName = useGetRoomName(getRoomHeroes, roomToHeroMembersResult.value);
const getRoomAvatar = useGetRoomAvatar(getRoomHeroes, roomToHeroMembersResult.value);
const roomAvatar = getRoomAvatar(roomId);
const roomName = getRoomName(roomId);
const stateObjResult = usePowerLevelsState(roomId);
const powerLevels = usePowerLevels(stateObjResult.value);
const powerLevelTagsResult = usePowerLevelTagsState(roomId);
const powerLevelTags = usePowerLevelTags(powerLevels, powerLevelTagsResult.value);
const membersAPI = useCreateRoomMembersAPI(roomId);
const membersPending = usePendingMembers(roomId);
usePendingMemberLoader(roomId, membersPending);
const roomToJoinRule = useObservableValue(ct.roomToJoinRule);
const avatarUrl = roomAvatar
? mxcUrlToHttp(mx, roomAvatar, useAuthentication, 96, 96, 'crop') ?? undefined
? mxcToHttp(ct.session.baseUrl, roomAvatar, useAuthentication).thumbnail({
width: 96,
height: 96,
method: 'crop',
})
: undefined;
const screenSize = useScreenSizeContext();
@ -90,84 +118,93 @@ export function SpaceSettings({ initialPage, requestClose }: SpaceSettingsProps)
};
return (
<PageRoot
nav={
screenSize === ScreenSize.Mobile && activePage !== undefined ? undefined : (
<PageNav size="300">
<PageNavHeader outlined={false}>
<Box grow="Yes" gap="200">
<Avatar size="200" radii="300">
<RoomAvatar
roomId={room.roomId}
src={avatarUrl}
alt={roomName}
renderFallback={() => (
<RoomIcon
roomType={room.getType()}
size="50"
joinRule={joinRuleContent?.join_rule ?? JoinRule.Invite}
filled
/>
)}
/>
</Avatar>
<Text size="H4" truncate>
{roomName}
</Text>
</Box>
<Box shrink="No">
{screenSize === ScreenSize.Mobile && (
<IconButton onClick={requestClose} variant="Background">
<Icon src={Icons.Cross} />
</IconButton>
)}
</Box>
</PageNavHeader>
<Box grow="Yes" direction="Column">
<PageNavContent>
<div style={{ flexGrow: 1 }}>
{menuItems.map((item) => (
<MenuItem
key={item.name}
variant="Background"
radii="400"
aria-pressed={activePage === item.page}
before={<Icon src={item.icon} size="100" filled={activePage === item.page} />}
onClick={() => setActivePage(item.page)}
>
<Text
style={{
fontWeight: activePage === item.page ? config.fontWeight.W600 : undefined,
}}
size="T300"
truncate
>
{item.name}
<RoomMembersAPIProvider value={membersAPI}>
<PowerLevelsContextProvider value={powerLevels}>
<PowerLevelTagsContextProvider value={powerLevelTags}>
<PageRoot
nav={
screenSize === ScreenSize.Mobile && activePage !== undefined ? undefined : (
<PageNav size="300">
<PageNavHeader outlined={false}>
<Box grow="Yes" gap="200">
<Avatar size="200" radii="300">
<RoomAvatar
roomId={roomId}
src={avatarUrl}
alt={roomName}
renderFallback={() => (
<RoomIcon
roomType={ct.roomToType.read.get(roomId)}
size="50"
joinRule={roomToJoinRule.get(roomId)}
filled
/>
)}
/>
</Avatar>
<Text size="H4" truncate>
{roomName}
</Text>
</MenuItem>
))}
</div>
</PageNavContent>
</Box>
</PageNav>
)
}
>
{activePage === SpaceSettingsPage.GeneralPage && (
<General requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.MembersPage && (
<Members requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.PermissionsPage && (
<Permissions requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.EmojisStickersPage && (
<EmojisStickers requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.DeveloperToolsPage && (
<DeveloperTools requestClose={handlePageRequestClose} />
)}
</PageRoot>
</Box>
<Box shrink="No">
{screenSize === ScreenSize.Mobile && (
<IconButton onClick={requestClose} variant="Background">
<Icon src={Icons.Cross} />
</IconButton>
)}
</Box>
</PageNavHeader>
<Box grow="Yes" direction="Column">
<PageNavContent>
<div style={{ flexGrow: 1 }}>
{menuItems.map((item) => (
<MenuItem
key={item.name}
variant="Background"
radii="400"
aria-pressed={activePage === item.page}
before={
<Icon src={item.icon} size="100" filled={activePage === item.page} />
}
onClick={() => setActivePage(item.page)}
>
<Text
style={{
fontWeight:
activePage === item.page ? config.fontWeight.W600 : undefined,
}}
size="T300"
truncate
>
{item.name}
</Text>
</MenuItem>
))}
</div>
</PageNavContent>
</Box>
</PageNav>
)
}
>
{activePage === SpaceSettingsPage.GeneralPage && (
<General requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.MembersPage && (
<Members requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.PermissionsPage && (
<Permissions requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.EmojisStickersPage && (
<EmojisStickers requestClose={handlePageRequestClose} />
)}
{activePage === SpaceSettingsPage.DeveloperToolsPage && (
<DeveloperTools requestClose={handlePageRequestClose} />
)}
</PageRoot>
</PowerLevelTagsContextProvider>
</PowerLevelsContextProvider>
</RoomMembersAPIProvider>
);
}

View file

@ -2,10 +2,11 @@ import React from 'react';
import { SpaceSettings } from './SpaceSettings';
import { Modal500 } from '../../components/Modal500';
import { useCloseSpaceSettings, useSpaceSettingsState } from '../../state/hooks/spaceSettings';
import { useAllJoinedRoomsSet, useGetRoom } from '../../hooks/useGetRoom';
import { SpaceSettingsState } from '../../state/spaceSettings';
import { RoomProvider } from '../../hooks/useRoom';
import { SpaceProvider } from '../../hooks/useSpace';
import { useClient } from '../../hooks/useClient';
import { useObservableValue } from '../../hooks/useObservableValue';
type RenderSettingsProps = {
state: SpaceSettingsState;
@ -13,17 +14,16 @@ type RenderSettingsProps = {
function RenderSettings({ state }: RenderSettingsProps) {
const { roomId, spaceId, page } = state;
const closeSettings = useCloseSpaceSettings();
const allJoinedRooms = useAllJoinedRoomsSet();
const getRoom = useGetRoom(allJoinedRooms);
const room = getRoom(roomId);
const space = spaceId && spaceId !== roomId ? getRoom(spaceId) : undefined;
if (!room) return null;
const ct = useClient();
const spaceRooms = useObservableValue(ct.spaceRooms);
if (!spaceRooms.has(roomId)) return null;
return (
<Modal500 requestClose={closeSettings}>
<SpaceProvider value={space ?? null}>
<RoomProvider value={room}>
<SpaceProvider value={spaceId ?? null}>
<RoomProvider value={roomId}>
<SpaceSettings initialPage={page} requestClose={closeSettings} />
</RoomProvider>
</SpaceProvider>

View file

@ -1,7 +1,7 @@
import React from 'react';
import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { usePowerLevels } from '../../../hooks/usePowerLevels';
import { usePowerLevelsContext } from '../../../hooks/usePowerLevels';
import { useRoom } from '../../../hooks/useRoom';
import {
RoomProfile,
@ -19,7 +19,7 @@ type GeneralProps = {
};
export function General({ requestClose }: GeneralProps) {
const room = useRoom();
const powerLevels = usePowerLevels(room);
const powerLevels = usePowerLevelsContext();
const creators = useRoomCreators(room);
const permissions = useRoomPermissions(creators, powerLevels);

View file

@ -2,27 +2,27 @@ import React, { useState } from 'react';
import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { useRoom } from '../../../hooks/useRoom';
import { usePowerLevels } from '../../../hooks/usePowerLevels';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { usePowerLevelsContext } from '../../../hooks/usePowerLevels';
import { StateEvent } from '../../../../types/matrix/room';
import { usePermissionGroups } from './usePermissionItems';
import { PermissionGroups, Powers, PowersEditor } from '../../common-settings/permissions';
import { useRoomCreators } from '../../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../../hooks/useRoomPermissions';
import { useClient } from '../../../hooks/useClient';
type PermissionsProps = {
requestClose: () => void;
};
export function Permissions({ requestClose }: PermissionsProps) {
const mx = useMatrixClient();
const room = useRoom();
const powerLevels = usePowerLevels(room);
const creators = useRoomCreators(room);
const ct = useClient();
const roomId = useRoom();
const powerLevels = usePowerLevelsContext();
const creators = useRoomCreators(roomId);
const permissions = useRoomPermissions(creators, powerLevels);
const canEditPowers = permissions.stateEvent(StateEvent.PowerLevelTags, mx.getSafeUserId());
const canEditPermissions = permissions.stateEvent(StateEvent.RoomPowerLevels, mx.getSafeUserId());
const canEditPowers = permissions.stateEvent(StateEvent.PowerLevelTags, ct.session.userId);
const canEditPermissions = permissions.stateEvent(StateEvent.RoomPowerLevels, ct.session.userId);
const permissionGroups = usePermissionGroups();
const [powerEditor, setPowerEditor] = useState(false);
@ -32,7 +32,7 @@ export function Permissions({ requestClose }: PermissionsProps) {
};
if (canEditPowers && powerEditor) {
return <PowersEditor powerLevels={powerLevels} requestClose={() => setPowerEditor(false)} />;
return <PowersEditor requestClose={() => setPowerEditor(false)} />;
}
return (
@ -56,15 +56,10 @@ export function Permissions({ requestClose }: PermissionsProps) {
<PageContent>
<Box direction="Column" gap="700">
<Powers
powerLevels={powerLevels}
onEdit={canEditPowers ? handleEditPowers : undefined}
permissionGroups={permissionGroups}
/>
<PermissionGroups
canEdit={canEditPermissions}
powerLevels={powerLevels}
permissionGroups={permissionGroups}
/>
<PermissionGroups canEdit={canEditPermissions} permissionGroups={permissionGroups} />
</Box>
</PageContent>
</Scroll>

View file

@ -140,8 +140,8 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize)
<CreateRoomModalRenderer />
<CreateSpaceModalRenderer />
<RoomSettingsRenderer />
{/*<SpaceSettingsRenderer />
<ReceiveSelfDeviceVerification />
<SpaceSettingsRenderer />
{/*<ReceiveSelfDeviceVerification />
<AutoRestoreBackupOnVerification /> */}
</ClientRoomsNotificationPreferences>
</ClientInitStorageAtom>