mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-04 22:40:29 +03:00
Use a common CollapsibleCard element for collapsible settings cards
This commit is contained in:
parent
af9460ef8b
commit
d42bcc6e3d
7 changed files with 322 additions and 390 deletions
|
|
@ -195,8 +195,8 @@ function AccountDataEdit({
|
|||
type AccountDataViewProps = {
|
||||
type: string;
|
||||
defaultContent: string;
|
||||
onEdit: () => void;
|
||||
requestClose: () => void;
|
||||
onEdit?: () => void;
|
||||
submitDelete?: AccountDataDeleteCallback;
|
||||
};
|
||||
function AccountDataView({ type, defaultContent, onEdit, requestClose, submitDelete }: AccountDataViewProps) {
|
||||
|
|
@ -231,9 +231,11 @@ function AccountDataView({ type, defaultContent, onEdit, requestClose, submitDel
|
|||
required
|
||||
/>
|
||||
</Box>
|
||||
<Button variant="Secondary" size="400" radii="300" onClick={onEdit}>
|
||||
<Text size="B400">Edit</Text>
|
||||
</Button>
|
||||
{onEdit && (
|
||||
<Button variant="Secondary" size="400" radii="300" onClick={onEdit}>
|
||||
<Text size="B400">Edit</Text>
|
||||
</Button>
|
||||
)}
|
||||
{submitDelete && (
|
||||
<Button
|
||||
variant="Critical"
|
||||
|
|
@ -269,7 +271,7 @@ function AccountDataView({ type, defaultContent, onEdit, requestClose, submitDel
|
|||
export type AccountDataEditorProps = {
|
||||
type?: string;
|
||||
content?: unknown;
|
||||
submitChange: AccountDataSubmitCallback;
|
||||
submitChange?: AccountDataSubmitCallback;
|
||||
submitDelete?: AccountDataDeleteCallback;
|
||||
requestClose: () => void;
|
||||
};
|
||||
|
|
@ -328,7 +330,7 @@ export function AccountDataEditor({
|
|||
</Box>
|
||||
</PageHeader>
|
||||
<Box grow="Yes" direction="Column">
|
||||
{edit ? (
|
||||
{(edit && submitChange) ? (
|
||||
<AccountDataEdit
|
||||
type={data.type}
|
||||
defaultContent={contentJSONStr}
|
||||
|
|
@ -340,8 +342,8 @@ export function AccountDataEditor({
|
|||
<AccountDataView
|
||||
type={data.type}
|
||||
defaultContent={contentJSONStr}
|
||||
onEdit={() => setEdit(true)}
|
||||
requestClose={requestClose}
|
||||
onEdit={submitChange ? () => setEdit(true) : undefined}
|
||||
submitDelete={submitDelete}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
54
src/app/components/CollapsibleCard.tsx
Normal file
54
src/app/components/CollapsibleCard.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { Button, Icon, Icons, Text } from 'folds';
|
||||
import { SequenceCard } from './sequence-card';
|
||||
import { SequenceCardStyle } from '../features/settings/styles.css';
|
||||
import { SettingTile } from './setting-tile';
|
||||
|
||||
type CollapsibleCardProps = {
|
||||
expand: boolean;
|
||||
setExpand: (expand: boolean) => void;
|
||||
title?: ReactNode;
|
||||
description?: ReactNode;
|
||||
before?: ReactNode;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export function CollapsibleCard({
|
||||
expand,
|
||||
setExpand,
|
||||
title,
|
||||
description,
|
||||
before,
|
||||
children,
|
||||
}: CollapsibleCardProps) {
|
||||
return (
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title={title}
|
||||
description={description}
|
||||
before={before}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpand(!expand)}
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
size="300"
|
||||
radii="300"
|
||||
outlined
|
||||
before={
|
||||
<Icon src={expand ? Icons.ChevronTop : Icons.ChevronBottom} size="100" filled />
|
||||
}
|
||||
>
|
||||
<Text size="B300">{expand ? 'Collapse' : 'Expand'}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expand && children}
|
||||
</SequenceCard>
|
||||
);
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ import {
|
|||
AccountDataSubmitCallback,
|
||||
} from '../../../components/AccountDataEditor';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { CollapsibleCard } from '../../../components/CollapsibleCard';
|
||||
|
||||
type DeveloperToolsProps = {
|
||||
requestClose: () => void;
|
||||
|
|
@ -175,216 +176,166 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
<CollapsibleCard
|
||||
expand={expandState}
|
||||
setExpand={setExpandState}
|
||||
title="Room State"
|
||||
description="State events of the room."
|
||||
>
|
||||
<SettingTile
|
||||
title="Room State"
|
||||
description="State events of the room."
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpandState(!expandState)}
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {roomState.size}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
onClick={() => setComposeEvent({ stateKey: '' })}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="300"
|
||||
outlined
|
||||
before={
|
||||
<Icon
|
||||
src={expandState ? Icons.ChevronTop : Icons.ChevronBottom}
|
||||
size="100"
|
||||
filled
|
||||
/>
|
||||
}
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
>
|
||||
<Text size="B300">{expandState ? 'Collapse' : 'Expand'}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expandState && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {roomState.size}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
onClick={() => setComposeEvent({ stateKey: '' })}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(roomState.keys())
|
||||
.sort()
|
||||
.map((eventType) => {
|
||||
const expanded = eventType === expandStateType;
|
||||
const stateKeyToEvents = roomState.get(eventType);
|
||||
if (!stateKeyToEvents) return null;
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(roomState.keys())
|
||||
.sort()
|
||||
.map((eventType) => {
|
||||
const expanded = eventType === expandStateType;
|
||||
const stateKeyToEvents = roomState.get(eventType);
|
||||
if (!stateKeyToEvents) return null;
|
||||
|
||||
return (
|
||||
<Box id={eventType} key={eventType} direction="Column" gap="100">
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
setExpandStateType(expanded ? undefined : eventType)
|
||||
}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={
|
||||
<Icon
|
||||
size="50"
|
||||
src={expanded ? Icons.ChevronBottom : Icons.ChevronRight}
|
||||
/>
|
||||
}
|
||||
after={<Text size="L400">{stateKeyToEvents.size}</Text>}
|
||||
return (
|
||||
<Box id={eventType} key={eventType} direction="Column" gap="100">
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
setExpandStateType(expanded ? undefined : eventType)
|
||||
}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={
|
||||
<Icon
|
||||
size="50"
|
||||
src={expanded ? Icons.ChevronBottom : Icons.ChevronRight}
|
||||
/>
|
||||
}
|
||||
after={<Text size="L400">{stateKeyToEvents.size}</Text>}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{eventType}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{expanded && (
|
||||
<div
|
||||
style={{
|
||||
marginLeft: config.space.S400,
|
||||
borderLeft: `${config.borderWidth.B300} solid ${color.Surface.ContainerLine}`,
|
||||
}}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{eventType}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{expanded && (
|
||||
<div
|
||||
style={{
|
||||
marginLeft: config.space.S400,
|
||||
borderLeft: `${config.borderWidth.B300} solid ${color.Surface.ContainerLine}`,
|
||||
}}
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
setComposeEvent({ type: eventType, stateKey: '' })
|
||||
}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
setComposeEvent({ type: eventType, stateKey: '' })
|
||||
}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(stateKeyToEvents.keys())
|
||||
.sort()
|
||||
.map((stateKey) => (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setOpenStateEvent({
|
||||
type: eventType,
|
||||
stateKey,
|
||||
});
|
||||
}}
|
||||
key={stateKey}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{stateKey ? `"${stateKey}"` : 'Default'}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
)}
|
||||
</SequenceCard>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(stateKeyToEvents.keys())
|
||||
.sort()
|
||||
.map((stateKey) => (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setOpenStateEvent({
|
||||
type: eventType,
|
||||
stateKey,
|
||||
});
|
||||
}}
|
||||
key={stateKey}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{stateKey ? `"${stateKey}"` : 'Default'}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
</CollapsibleCard>
|
||||
<CollapsibleCard
|
||||
expand={expandAccountData}
|
||||
setExpand={setExpandAccountData}
|
||||
title="Account Data"
|
||||
description="Private personalization data stored within room"
|
||||
>
|
||||
<SettingTile
|
||||
title="Account Data"
|
||||
description="Private personalization data stored within room."
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpandAccountData(!expandAccountData)}
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
size="300"
|
||||
radii="300"
|
||||
outlined
|
||||
before={
|
||||
<Icon
|
||||
src={expandAccountData ? Icons.ChevronTop : Icons.ChevronBottom}
|
||||
size="100"
|
||||
filled
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Text size="B300">{expandAccountData ? 'Collapse' : 'Expand'}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expandAccountData && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {accountData.size}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
onClick={() => setAccountDataType(null)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(accountData.keys())
|
||||
.sort()
|
||||
.map((type) => (
|
||||
<MenuItem
|
||||
key={type}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
onClick={() => setAccountDataType(type)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{type}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</CutoutCard>
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {accountData.size}</Text>
|
||||
</Box>
|
||||
)}
|
||||
</SequenceCard>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
onClick={() => setAccountDataType(null)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{Array.from(accountData.keys())
|
||||
.sort()
|
||||
.map((type) => (
|
||||
<MenuItem
|
||||
key={type}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
onClick={() => setAccountDataType(type)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{type}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
</CollapsibleCard>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import {
|
|||
Chip,
|
||||
color,
|
||||
config,
|
||||
Icon,
|
||||
Icons,
|
||||
Input,
|
||||
Spinner,
|
||||
Text,
|
||||
|
|
@ -33,6 +31,7 @@ import { useAlive } from '../../../hooks/useAlive';
|
|||
import { StateEvent } from '../../../../types/matrix/room';
|
||||
import { RoomPermissionsAPI } from '../../../hooks/useRoomPermissions';
|
||||
import { getMxIdServer } from '../../../utils/matrix';
|
||||
import { CollapsibleCard } from '../../../components/CollapsibleCard';
|
||||
|
||||
type RoomPublishedAddressesProps = {
|
||||
permissions: RoomPermissionsAPI;
|
||||
|
|
@ -373,64 +372,40 @@ export function RoomLocalAddresses({ permissions }: { permissions: RoomPermissio
|
|||
const { localAliasesState, addLocalAlias, removeLocalAlias } = useLocalAliases(room.roomId);
|
||||
|
||||
return (
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
<CollapsibleCard
|
||||
expand={expand}
|
||||
setExpand={setExpand}
|
||||
title="Local Addresses"
|
||||
description="Set local address so users can join through your homeserver."
|
||||
>
|
||||
<SettingTile
|
||||
title="Local Addresses"
|
||||
description="Set local address so users can join through your homeserver."
|
||||
after={
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setExpand(!expand)}
|
||||
size="300"
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
outlined
|
||||
radii="300"
|
||||
before={
|
||||
<Icon size="100" src={expand ? Icons.ChevronTop : Icons.ChevronBottom} filled />
|
||||
}
|
||||
>
|
||||
<Text as="span" size="B300" truncate>
|
||||
{expand ? 'Collapse' : 'Expand'}
|
||||
<CutoutCard variant="Surface" style={{ padding: config.space.S300 }}>
|
||||
{localAliasesState.status === AsyncStatus.Loading && (
|
||||
<Box gap="100">
|
||||
<Spinner variant="Secondary" size="100" />
|
||||
<Text size="T200">Loading...</Text>
|
||||
</Box>
|
||||
)}
|
||||
{localAliasesState.status === AsyncStatus.Success &&
|
||||
(localAliasesState.data.length === 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">No Addresses</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<LocalAddressesList
|
||||
localAliases={localAliasesState.data}
|
||||
removeLocalAlias={removeLocalAlias}
|
||||
canEditCanonical={canEditCanonical}
|
||||
/>
|
||||
))}
|
||||
{localAliasesState.status === AsyncStatus.Error && (
|
||||
<Box gap="100">
|
||||
<Text size="T200" style={{ color: color.Critical.Main }}>
|
||||
{localAliasesState.error.message}
|
||||
</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expand && (
|
||||
<CutoutCard variant="Surface" style={{ padding: config.space.S300 }}>
|
||||
{localAliasesState.status === AsyncStatus.Loading && (
|
||||
<Box gap="100">
|
||||
<Spinner variant="Secondary" size="100" />
|
||||
<Text size="T200">Loading...</Text>
|
||||
</Box>
|
||||
)}
|
||||
{localAliasesState.status === AsyncStatus.Success &&
|
||||
(localAliasesState.data.length === 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">No Addresses</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<LocalAddressesList
|
||||
localAliases={localAliasesState.data}
|
||||
removeLocalAlias={removeLocalAlias}
|
||||
canEditCanonical={canEditCanonical}
|
||||
/>
|
||||
))}
|
||||
{localAliasesState.status === AsyncStatus.Error && (
|
||||
<Box gap="100">
|
||||
<Text size="T200" style={{ color: color.Critical.Main }}>
|
||||
{localAliasesState.error.message}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</CutoutCard>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</CutoutCard>
|
||||
{expand && <LocalAddressInput addLocalAlias={addLocalAlias} />}
|
||||
</SequenceCard>
|
||||
</CollapsibleCard>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,86 +1,54 @@
|
|||
import React from 'react';
|
||||
import { Box, Text, Icon, Icons, Button, MenuItem } from 'folds';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { Box, Text, Icon, Icons, MenuItem } from 'folds';
|
||||
import { CutoutCard } from '../../../components/cutout-card';
|
||||
|
||||
type AccountDataListProps = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
expand: boolean;
|
||||
setExpand: (expand: boolean) => void;
|
||||
types: string[];
|
||||
onSelect: (type: string | null) => void;
|
||||
};
|
||||
export function AccountDataList({ types, onSelect, expand, setExpand, title, description }: AccountDataListProps) {
|
||||
export function AccountDataList({
|
||||
types,
|
||||
onSelect,
|
||||
}: AccountDataListProps) {
|
||||
return (
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title={title}
|
||||
description={description}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpand(!expand)}
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
size="300"
|
||||
radii="300"
|
||||
outlined
|
||||
before={
|
||||
<Icon src={expand ? Icons.ChevronTop : Icons.ChevronBottom} size="100" filled />
|
||||
}
|
||||
>
|
||||
<Text size="B300">{expand ? 'Collapse' : 'Expand'}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expand && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Fields</Text>
|
||||
<Text size="L400">Total: {types.length}</Text>
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Fields</Text>
|
||||
<Text size="L400">Total: {types.length}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
onClick={() => onSelect(null)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
before={<Icon size="50" src={Icons.Plus} />}
|
||||
onClick={() => onSelect(null)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
{types.sort().map((type) => (
|
||||
<MenuItem
|
||||
key={type}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
onClick={() => onSelect(type)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{type}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
)}
|
||||
</SequenceCard>
|
||||
</MenuItem>
|
||||
{types.sort().map((type) => (
|
||||
<MenuItem
|
||||
key={type}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
onClick={() => onSelect(type)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{type}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { copyToClipboard } from '../../../utils/dom';
|
|||
import { AccountDataList } from './AccountDataList';
|
||||
import { useExtendedProfile } from '../../../hooks/useExtendedProfile';
|
||||
import { useAccountDataCallback } from '../../../hooks/useAccountDataCallback';
|
||||
import { CollapsibleCard } from '../../../components/CollapsibleCard';
|
||||
|
||||
type DeveloperToolsPage =
|
||||
| { name: 'index' }
|
||||
|
|
@ -165,23 +166,29 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
{developerTools && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Account Data</Text>
|
||||
<AccountDataList
|
||||
title="Account"
|
||||
description="Private data stored in your account."
|
||||
<CollapsibleCard
|
||||
expand={globalExpand}
|
||||
setExpand={setGlobalExpand}
|
||||
types={accountDataTypes}
|
||||
onSelect={(type) => setPage({ name: 'account-data', type })}
|
||||
/>
|
||||
{extendedProfile && (
|
||||
title="Account"
|
||||
description="Private data stored in your account."
|
||||
>
|
||||
<AccountDataList
|
||||
title="Profile"
|
||||
description="Public data attached to your Matrix profile."
|
||||
types={accountDataTypes}
|
||||
onSelect={(type) => setPage({ name: 'account-data', type })}
|
||||
/>
|
||||
</CollapsibleCard>
|
||||
{extendedProfile && (
|
||||
<CollapsibleCard
|
||||
expand={profileExpand}
|
||||
setExpand={setProfileExpand}
|
||||
types={Object.keys(extendedProfile)}
|
||||
onSelect={(type) => setPage({ name: 'profile-field', type })}
|
||||
/>
|
||||
title="Profile"
|
||||
description="Public data attached to your Matrix profile."
|
||||
>
|
||||
<AccountDataList
|
||||
types={Object.keys(extendedProfile)}
|
||||
onSelect={(type) => setPage({ name: 'profile-field', type })}
|
||||
/>
|
||||
</CollapsibleCard>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
|||
import { decryptMegolmKeyFile, encryptMegolmKeyFile } from '../../../../util/cryptE2ERoomKeys';
|
||||
import { useAlive } from '../../../hooks/useAlive';
|
||||
import { useFilePicker } from '../../../hooks/useFilePicker';
|
||||
import { CollapsibleCard } from '../../../components/CollapsibleCard';
|
||||
|
||||
function ExportKeys() {
|
||||
const mx = useMatrixClient();
|
||||
|
|
@ -121,37 +122,18 @@ function ExportKeys() {
|
|||
);
|
||||
}
|
||||
|
||||
function ExportKeysTile() {
|
||||
function ExportKeysCard() {
|
||||
const [expand, setExpand] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingTile
|
||||
title="Export Messages Data"
|
||||
description="Save password protected copy of encryption data on your device to decrypt messages later."
|
||||
after={
|
||||
<Box>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setExpand(!expand)}
|
||||
size="300"
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
outlined
|
||||
radii="300"
|
||||
before={
|
||||
<Icon size="100" src={expand ? Icons.ChevronTop : Icons.ChevronBottom} filled />
|
||||
}
|
||||
>
|
||||
<Text as="span" size="B300" truncate>
|
||||
{expand ? 'Collapse' : 'Expand'}
|
||||
</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
{expand && <ExportKeys />}
|
||||
</>
|
||||
<CollapsibleCard
|
||||
expand={expand}
|
||||
setExpand={setExpand}
|
||||
title="Export Messages Data"
|
||||
description="Save password protected copy of encryption data on your device to decrypt messages later."
|
||||
>
|
||||
<ExportKeys />
|
||||
</CollapsibleCard>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -304,14 +286,7 @@ export function LocalBackup() {
|
|||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Local Backup</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<ExportKeysTile />
|
||||
</SequenceCard>
|
||||
<ExportKeysCard />
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue