mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-16 20:20:29 +03:00
Add a panel in Developer Tools for editing profile fields
This commit is contained in:
parent
4e7b64eb5f
commit
5bc9654d32
5 changed files with 287 additions and 201 deletions
|
|
@ -27,6 +27,7 @@ import { useTextAreaCodeEditor } from '../hooks/useTextAreaCodeEditor';
|
||||||
const EDITOR_INTENT_SPACE_COUNT = 2;
|
const EDITOR_INTENT_SPACE_COUNT = 2;
|
||||||
|
|
||||||
export type AccountDataSubmitCallback = (type: string, content: object) => Promise<void>;
|
export type AccountDataSubmitCallback = (type: string, content: object) => Promise<void>;
|
||||||
|
export type AccountDataDeleteCallback = (type: string) => Promise<void>;
|
||||||
|
|
||||||
type AccountDataInfo = {
|
type AccountDataInfo = {
|
||||||
type: string;
|
type: string;
|
||||||
|
|
@ -83,8 +84,7 @@ function AccountDataEdit({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!typeStr ||
|
!typeStr ||
|
||||||
parsedContent === null ||
|
parsedContent === null
|
||||||
defaultContent === JSON.stringify(parsedContent, null, EDITOR_INTENT_SPACE_COUNT)
|
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +121,7 @@ function AccountDataEdit({
|
||||||
aria-disabled={submitting}
|
aria-disabled={submitting}
|
||||||
>
|
>
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Text size="L400">Account Data</Text>
|
<Text size="L400">Field Name</Text>
|
||||||
<Box gap="300">
|
<Box gap="300">
|
||||||
<Box grow="Yes" direction="Column">
|
<Box grow="Yes" direction="Column">
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -196,8 +196,21 @@ type AccountDataViewProps = {
|
||||||
type: string;
|
type: string;
|
||||||
defaultContent: string;
|
defaultContent: string;
|
||||||
onEdit: () => void;
|
onEdit: () => void;
|
||||||
|
requestClose: () => void;
|
||||||
|
submitDelete?: AccountDataDeleteCallback;
|
||||||
};
|
};
|
||||||
function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps) {
|
function AccountDataView({ type, defaultContent, onEdit, requestClose, submitDelete }: AccountDataViewProps) {
|
||||||
|
const [deleteState, deleteCallback] = useAsyncCallback<void, MatrixError, []>(useCallback(
|
||||||
|
async () => {
|
||||||
|
if (submitDelete !== undefined) {
|
||||||
|
await submitDelete(type);
|
||||||
|
requestClose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[type, submitDelete, requestClose],
|
||||||
|
));
|
||||||
|
const deleting = deleteState.status === AsyncStatus.Loading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
direction="Column"
|
direction="Column"
|
||||||
|
|
@ -208,7 +221,7 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
||||||
>
|
>
|
||||||
<Box shrink="No" gap="300" alignItems="End">
|
<Box shrink="No" gap="300" alignItems="End">
|
||||||
<Box grow="Yes" direction="Column" gap="100">
|
<Box grow="Yes" direction="Column" gap="100">
|
||||||
<Text size="L400">Account Data</Text>
|
<Text size="L400">Field Name</Text>
|
||||||
<Input
|
<Input
|
||||||
variant="SurfaceVariant"
|
variant="SurfaceVariant"
|
||||||
size="400"
|
size="400"
|
||||||
|
|
@ -221,6 +234,18 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
||||||
<Button variant="Secondary" size="400" radii="300" onClick={onEdit}>
|
<Button variant="Secondary" size="400" radii="300" onClick={onEdit}>
|
||||||
<Text size="B400">Edit</Text>
|
<Text size="B400">Edit</Text>
|
||||||
</Button>
|
</Button>
|
||||||
|
{submitDelete && (
|
||||||
|
<Button
|
||||||
|
variant="Critical"
|
||||||
|
size="400"
|
||||||
|
radii="300"
|
||||||
|
disabled={deleting}
|
||||||
|
before={deleting && <Spinner variant="Critical" fill="Solid" size="300" />}
|
||||||
|
onClick={deleteCallback}
|
||||||
|
>
|
||||||
|
<Text size="B400">Delete</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box grow="Yes" direction="Column" gap="100">
|
<Box grow="Yes" direction="Column" gap="100">
|
||||||
<Text size="L400">JSON Content</Text>
|
<Text size="L400">JSON Content</Text>
|
||||||
|
|
@ -243,8 +268,9 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
||||||
|
|
||||||
export type AccountDataEditorProps = {
|
export type AccountDataEditorProps = {
|
||||||
type?: string;
|
type?: string;
|
||||||
content?: object;
|
content?: unknown;
|
||||||
submitChange: AccountDataSubmitCallback;
|
submitChange: AccountDataSubmitCallback;
|
||||||
|
submitDelete?: AccountDataDeleteCallback;
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -252,6 +278,7 @@ export function AccountDataEditor({
|
||||||
type,
|
type,
|
||||||
content,
|
content,
|
||||||
submitChange,
|
submitChange,
|
||||||
|
submitDelete,
|
||||||
requestClose,
|
requestClose,
|
||||||
}: AccountDataEditorProps) {
|
}: AccountDataEditorProps) {
|
||||||
const [data, setData] = useState<AccountDataInfo>({
|
const [data, setData] = useState<AccountDataInfo>({
|
||||||
|
|
@ -314,6 +341,8 @@ export function AccountDataEditor({
|
||||||
type={data.type}
|
type={data.type}
|
||||||
defaultContent={contentJSONStr}
|
defaultContent={contentJSONStr}
|
||||||
onEdit={() => setEdit(true)}
|
onEdit={() => setEdit(true)}
|
||||||
|
requestClose={requestClose}
|
||||||
|
submitDelete={submitDelete}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ export function Profile() {
|
||||||
// once the profile request completes
|
// once the profile request completes
|
||||||
await refreshExtendedProfile();
|
await refreshExtendedProfile();
|
||||||
|
|
||||||
// synthesise a profile update for ourselves to update our name and avatr in the rest
|
// synthesize a profile update for ourselves to update our name and avatar in the rest
|
||||||
// of the UI. code copied from matrix-js-sdk
|
// of the UI. code copied from matrix-js-sdk
|
||||||
const user = mx.getUser(userId);
|
const user = mx.getUser(userId);
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
import React, { useCallback, useState } 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 { useMatrixClient } from '../../../hooks/useMatrixClient';
|
|
||||||
import { useAccountDataCallback } from '../../../hooks/useAccountDataCallback';
|
|
||||||
import { CutoutCard } from '../../../components/cutout-card';
|
|
||||||
|
|
||||||
type AccountDataProps = {
|
|
||||||
expand: boolean;
|
|
||||||
onExpandToggle: (expand: boolean) => void;
|
|
||||||
onSelect: (type: string | null) => void;
|
|
||||||
};
|
|
||||||
export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataProps) {
|
|
||||||
const mx = useMatrixClient();
|
|
||||||
const [accountDataTypes, setAccountDataKeys] = useState(() =>
|
|
||||||
Array.from(mx.store.accountData.keys())
|
|
||||||
);
|
|
||||||
|
|
||||||
useAccountDataCallback(
|
|
||||||
mx,
|
|
||||||
useCallback(() => {
|
|
||||||
setAccountDataKeys(Array.from(mx.store.accountData.keys()));
|
|
||||||
}, [mx])
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box direction="Column" gap="100">
|
|
||||||
<Text size="L400">Account Data</Text>
|
|
||||||
<SequenceCard
|
|
||||||
className={SequenceCardStyle}
|
|
||||||
variant="SurfaceVariant"
|
|
||||||
direction="Column"
|
|
||||||
gap="400"
|
|
||||||
>
|
|
||||||
<SettingTile
|
|
||||||
title="Global"
|
|
||||||
description="Data stored in your global account data."
|
|
||||||
after={
|
|
||||||
<Button
|
|
||||||
onClick={() => onExpandToggle(!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">Events</Text>
|
|
||||||
<Text size="L400">Total: {accountDataTypes.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>
|
|
||||||
</MenuItem>
|
|
||||||
{accountDataTypes.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>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
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 { 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) {
|
||||||
|
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>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Button } from 'folds';
|
import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Button } from 'folds';
|
||||||
|
import { AccountDataEvents } from 'matrix-js-sdk';
|
||||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||||
import { SequenceCard } from '../../../components/sequence-card';
|
import { SequenceCard } from '../../../components/sequence-card';
|
||||||
import { SequenceCardStyle } from '../styles.css';
|
import { SequenceCardStyle } from '../styles.css';
|
||||||
|
|
@ -8,117 +9,187 @@ import { useSetting } from '../../../state/hooks/settings';
|
||||||
import { settingsAtom } from '../../../state/settings';
|
import { settingsAtom } from '../../../state/settings';
|
||||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||||
import {
|
import {
|
||||||
|
AccountDataDeleteCallback,
|
||||||
AccountDataEditor,
|
AccountDataEditor,
|
||||||
AccountDataSubmitCallback,
|
AccountDataSubmitCallback,
|
||||||
} from '../../../components/AccountDataEditor';
|
} from '../../../components/AccountDataEditor';
|
||||||
import { copyToClipboard } from '../../../utils/dom';
|
import { copyToClipboard } from '../../../utils/dom';
|
||||||
import { AccountData } from './AccountData';
|
import { AccountDataList } from './AccountDataList';
|
||||||
|
import { useExtendedProfile } from '../../../hooks/useExtendedProfile';
|
||||||
|
import { useAccountDataCallback } from '../../../hooks/useAccountDataCallback';
|
||||||
|
|
||||||
|
type DeveloperToolsPage =
|
||||||
|
| { name: 'index' }
|
||||||
|
| { name: 'account-data'; type: string | null }
|
||||||
|
| { name: 'profile-field'; type: string | null };
|
||||||
|
|
||||||
type DeveloperToolsProps = {
|
type DeveloperToolsProps = {
|
||||||
requestClose: () => void;
|
requestClose: () => void;
|
||||||
};
|
};
|
||||||
export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const userId = mx.getUserId() as string;
|
||||||
|
|
||||||
|
const [accountDataTypes, setAccountDataKeys] = useState(() =>
|
||||||
|
Array.from(mx.store.accountData.keys())
|
||||||
|
);
|
||||||
|
|
||||||
|
useAccountDataCallback(
|
||||||
|
mx,
|
||||||
|
useCallback(() => {
|
||||||
|
setAccountDataKeys(Array.from(mx.store.accountData.keys()));
|
||||||
|
}, [mx])
|
||||||
|
);
|
||||||
|
const [extendedProfile, refreshExtendedProfile] = useExtendedProfile(userId);
|
||||||
|
|
||||||
const [developerTools, setDeveloperTools] = useSetting(settingsAtom, 'developerTools');
|
const [developerTools, setDeveloperTools] = useSetting(settingsAtom, 'developerTools');
|
||||||
const [expand, setExpend] = useState(false);
|
const [page, setPage] = useState<DeveloperToolsPage>({ name: 'index' });
|
||||||
const [accountDataType, setAccountDataType] = useState<string | null>();
|
const [globalExpand, setGlobalExpand] = useState(false);
|
||||||
|
const [profileExpand, setProfileExpand] = useState(false);
|
||||||
|
|
||||||
const submitAccountData: AccountDataSubmitCallback = useCallback(
|
const submitAccountData: AccountDataSubmitCallback = useCallback(
|
||||||
async (type, content) => {
|
async (type, content) => {
|
||||||
await mx.setAccountData(type, content);
|
await mx.setAccountData(type as keyof AccountDataEvents, content);
|
||||||
},
|
},
|
||||||
[mx]
|
[mx]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (accountDataType !== undefined) {
|
const submitProfileField: AccountDataSubmitCallback = useCallback(
|
||||||
return (
|
async (type, content) => {
|
||||||
<AccountDataEditor
|
await mx.setExtendedProfileProperty(type, content);
|
||||||
type={accountDataType ?? undefined}
|
await refreshExtendedProfile();
|
||||||
content={accountDataType ? mx.getAccountData(accountDataType)?.getContent() : undefined}
|
},
|
||||||
submitChange={submitAccountData}
|
[mx, refreshExtendedProfile]
|
||||||
requestClose={() => setAccountDataType(undefined)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Page>
|
|
||||||
<PageHeader outlined={false}>
|
|
||||||
<Box grow="Yes" gap="200">
|
|
||||||
<Box grow="Yes" alignItems="Center" gap="200">
|
|
||||||
<Text size="H3" truncate>
|
|
||||||
Developer Tools
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
<Box shrink="No">
|
|
||||||
<IconButton onClick={requestClose} variant="Surface">
|
|
||||||
<Icon src={Icons.Cross} />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</PageHeader>
|
|
||||||
<Box grow="Yes">
|
|
||||||
<Scroll hideTrack visibility="Hover">
|
|
||||||
<PageContent>
|
|
||||||
<Box direction="Column" gap="700">
|
|
||||||
<Box direction="Column" gap="100">
|
|
||||||
<Text size="L400">Options</Text>
|
|
||||||
<SequenceCard
|
|
||||||
className={SequenceCardStyle}
|
|
||||||
variant="SurfaceVariant"
|
|
||||||
direction="Column"
|
|
||||||
gap="400"
|
|
||||||
>
|
|
||||||
<SettingTile
|
|
||||||
title="Enable Developer Tools"
|
|
||||||
after={
|
|
||||||
<Switch
|
|
||||||
variant="Primary"
|
|
||||||
value={developerTools}
|
|
||||||
onChange={setDeveloperTools}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</SequenceCard>
|
|
||||||
{developerTools && (
|
|
||||||
<SequenceCard
|
|
||||||
className={SequenceCardStyle}
|
|
||||||
variant="SurfaceVariant"
|
|
||||||
direction="Column"
|
|
||||||
gap="400"
|
|
||||||
>
|
|
||||||
<SettingTile
|
|
||||||
title="Access Token"
|
|
||||||
description="Copy access token to clipboard."
|
|
||||||
after={
|
|
||||||
<Button
|
|
||||||
onClick={() =>
|
|
||||||
copyToClipboard(mx.getAccessToken() ?? '<NO_ACCESS_TOKEN_FOUND>')
|
|
||||||
}
|
|
||||||
variant="Secondary"
|
|
||||||
fill="Soft"
|
|
||||||
size="300"
|
|
||||||
radii="300"
|
|
||||||
outlined
|
|
||||||
>
|
|
||||||
<Text size="B300">Copy</Text>
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</SequenceCard>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
{developerTools && (
|
|
||||||
<AccountData
|
|
||||||
expand={expand}
|
|
||||||
onExpandToggle={setExpend}
|
|
||||||
onSelect={setAccountDataType}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</PageContent>
|
|
||||||
</Scroll>
|
|
||||||
</Box>
|
|
||||||
</Page>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const deleteProfileField: AccountDataDeleteCallback = useCallback(
|
||||||
|
async (type) => {
|
||||||
|
await mx.deleteExtendedProfileProperty(type);
|
||||||
|
await refreshExtendedProfile();
|
||||||
|
},
|
||||||
|
[mx, refreshExtendedProfile]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleClose = useCallback(() => setPage({ name: 'index' }), [setPage]);
|
||||||
|
|
||||||
|
switch (page.name) {
|
||||||
|
case 'account-data':
|
||||||
|
return (
|
||||||
|
<AccountDataEditor
|
||||||
|
type={page.type ?? undefined}
|
||||||
|
content={page.type ? mx.getAccountData(page.type as keyof AccountDataEvents)?.getContent() : undefined}
|
||||||
|
submitChange={submitAccountData}
|
||||||
|
requestClose={handleClose}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
case 'profile-field':
|
||||||
|
return (
|
||||||
|
<AccountDataEditor
|
||||||
|
type={page.type ?? undefined}
|
||||||
|
content={page.type ? extendedProfile?.[page.type] : undefined}
|
||||||
|
submitChange={submitProfileField}
|
||||||
|
submitDelete={deleteProfileField}
|
||||||
|
requestClose={handleClose}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<PageHeader outlined={false}>
|
||||||
|
<Box grow="Yes" gap="200">
|
||||||
|
<Box grow="Yes" alignItems="Center" gap="200">
|
||||||
|
<Text size="H3" truncate>
|
||||||
|
Developer Tools
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box shrink="No">
|
||||||
|
<IconButton onClick={requestClose} variant="Surface">
|
||||||
|
<Icon src={Icons.Cross} />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</PageHeader>
|
||||||
|
<Box grow="Yes">
|
||||||
|
<Scroll hideTrack visibility="Hover">
|
||||||
|
<PageContent>
|
||||||
|
<Box direction="Column" gap="700">
|
||||||
|
<Box direction="Column" gap="100">
|
||||||
|
<Text size="L400">Options</Text>
|
||||||
|
<SequenceCard
|
||||||
|
className={SequenceCardStyle}
|
||||||
|
variant="SurfaceVariant"
|
||||||
|
direction="Column"
|
||||||
|
gap="400"
|
||||||
|
>
|
||||||
|
<SettingTile
|
||||||
|
title="Enable Developer Tools"
|
||||||
|
after={
|
||||||
|
<Switch
|
||||||
|
variant="Primary"
|
||||||
|
value={developerTools}
|
||||||
|
onChange={setDeveloperTools}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SequenceCard>
|
||||||
|
{developerTools && (
|
||||||
|
<SequenceCard
|
||||||
|
className={SequenceCardStyle}
|
||||||
|
variant="SurfaceVariant"
|
||||||
|
direction="Column"
|
||||||
|
gap="400"
|
||||||
|
>
|
||||||
|
<SettingTile
|
||||||
|
title="Access Token"
|
||||||
|
description="Copy access token to clipboard."
|
||||||
|
after={
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
copyToClipboard(mx.getAccessToken() ?? '<NO_ACCESS_TOKEN_FOUND>')
|
||||||
|
}
|
||||||
|
variant="Secondary"
|
||||||
|
fill="Soft"
|
||||||
|
size="300"
|
||||||
|
radii="300"
|
||||||
|
outlined
|
||||||
|
>
|
||||||
|
<Text size="B300">Copy</Text>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SequenceCard>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
{developerTools && (
|
||||||
|
<Box direction="Column" gap="100">
|
||||||
|
<Text size="L400">Account Data</Text>
|
||||||
|
<AccountDataList
|
||||||
|
title="Account"
|
||||||
|
description="Private data stored in your account."
|
||||||
|
expand={globalExpand}
|
||||||
|
setExpand={setGlobalExpand}
|
||||||
|
types={accountDataTypes}
|
||||||
|
onSelect={(type) => setPage({ name: 'account-data', type })}
|
||||||
|
/>
|
||||||
|
{extendedProfile && (
|
||||||
|
<AccountDataList
|
||||||
|
title="Profile"
|
||||||
|
description="Public data attached to your Matrix profile."
|
||||||
|
expand={profileExpand}
|
||||||
|
setExpand={setProfileExpand}
|
||||||
|
types={Object.keys(extendedProfile)}
|
||||||
|
onSelect={(type) => setPage({ name: 'profile-field', type })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</PageContent>
|
||||||
|
</Scroll>
|
||||||
|
</Box>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue