move settings developer tool to new sdk
This commit is contained in:
parent
bd5d4f8958
commit
c4f58415db
4 changed files with 73 additions and 68 deletions
|
|
@ -14,6 +14,7 @@ import {
|
|||
Scroll,
|
||||
config,
|
||||
} from 'folds';
|
||||
import { AccountDataEvent } from 'neurone/lib/api/types';
|
||||
import { Cursor } from '../plugins/text-area';
|
||||
import { syntaxErrorPosition } from '../utils/dom';
|
||||
import { AsyncStatus, useAsyncCallback } from '../hooks/useAsyncCallback';
|
||||
|
|
@ -27,17 +28,12 @@ const EDITOR_INTENT_SPACE_COUNT = 2;
|
|||
|
||||
export type AccountDataSubmitCallback = (type: string, content: object) => Promise<void>;
|
||||
|
||||
type AccountDataInfo = {
|
||||
type: string;
|
||||
content: object;
|
||||
};
|
||||
|
||||
type AccountDataEditProps = {
|
||||
type: string;
|
||||
defaultContent: string;
|
||||
submitChange: AccountDataSubmitCallback;
|
||||
onCancel: () => void;
|
||||
onSave: (info: AccountDataInfo) => void;
|
||||
onSave: (info: AccountDataEvent) => void;
|
||||
};
|
||||
function AccountDataEdit({
|
||||
type,
|
||||
|
|
@ -243,34 +239,30 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
|||
}
|
||||
|
||||
export type AccountDataEditorProps = {
|
||||
type?: string;
|
||||
content?: object;
|
||||
event?: AccountDataEvent;
|
||||
submitChange: AccountDataSubmitCallback;
|
||||
requestClose: () => void;
|
||||
};
|
||||
|
||||
export function AccountDataEditor({
|
||||
type,
|
||||
content,
|
||||
submitChange,
|
||||
requestClose,
|
||||
}: AccountDataEditorProps) {
|
||||
const [data, setData] = useState<AccountDataInfo>({
|
||||
type: type ?? '',
|
||||
content: content ?? {},
|
||||
});
|
||||
export function AccountDataEditor({ event, submitChange, requestClose }: AccountDataEditorProps) {
|
||||
const [data, setData] = useState<AccountDataEvent>(
|
||||
event ?? {
|
||||
type: '',
|
||||
content: {},
|
||||
}
|
||||
);
|
||||
|
||||
const [edit, setEdit] = useState(!type);
|
||||
const [edit, setEdit] = useState(!data.type);
|
||||
|
||||
const closeEdit = useCallback(() => {
|
||||
if (!type) {
|
||||
if (!event) {
|
||||
requestClose();
|
||||
return;
|
||||
}
|
||||
setEdit(false);
|
||||
}, [type, requestClose]);
|
||||
}, [event, requestClose]);
|
||||
|
||||
const handleSave = useCallback((info: AccountDataInfo) => {
|
||||
const handleSave = useCallback((info: AccountDataEvent) => {
|
||||
setData(info);
|
||||
setEdit(false);
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -1,29 +1,20 @@
|
|||
import React, { useCallback, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Box, Text, Icon, Icons, Button, MenuItem } from 'folds';
|
||||
import { AccountDataEvent } from 'neurone/lib/api/types';
|
||||
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';
|
||||
import { useAccountDataEvents } from '../../../hooks/storage/useAccountData';
|
||||
|
||||
type AccountDataProps = {
|
||||
expand: boolean;
|
||||
onExpandToggle: (expand: boolean) => void;
|
||||
onSelect: (type: string | null) => void;
|
||||
onSelect: (type: AccountDataEvent | 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])
|
||||
);
|
||||
const accountDataEventsResult = useAccountDataEvents();
|
||||
const accountDataEvents = accountDataEventsResult.value;
|
||||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
|
|
@ -57,7 +48,7 @@ export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataPro
|
|||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {accountDataTypes.length}</Text>
|
||||
{accountDataEvents && <Text size="L400">Total: {accountDataEvents.length}</Text>}
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
|
|
@ -74,23 +65,25 @@ export function AccountData({ expand, onExpandToggle, onSelect }: AccountDataPro
|
|||
</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>
|
||||
))}
|
||||
{accountDataEvents
|
||||
?.sort((e1, e2) => (e1 < e2 ? -1 : 1))
|
||||
.map((event) => (
|
||||
<MenuItem
|
||||
key={event.type}
|
||||
variant="Surface"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="0"
|
||||
after={<Icon size="50" src={Icons.ChevronRight} />}
|
||||
onClick={() => onSelect(event)}
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{event.type}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
))}
|
||||
</CutoutCard>
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,42 +1,52 @@
|
|||
import React, { useCallback, useState } from 'react';
|
||||
import { Box, Text, IconButton, Icon, Icons, Scroll, Switch, Button } from 'folds';
|
||||
import { putAccountData } from 'neurone/lib/api/matrix/client/v3/user';
|
||||
import { parseMatrixResp } from 'neurone/lib/matrix-request';
|
||||
import { AccountDataEvent } from 'neurone/lib/api/types';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { useSetting } from '../../../state/hooks/settings';
|
||||
import { settingsAtom } from '../../../state/settings';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import {
|
||||
AccountDataEditor,
|
||||
AccountDataSubmitCallback,
|
||||
} from '../../../components/AccountDataEditor';
|
||||
import { copyToClipboard } from '../../../utils/dom';
|
||||
import { useClient } from '../../../hooks/useClient';
|
||||
import { AccountData } from './AccountData';
|
||||
|
||||
type DeveloperToolsProps = {
|
||||
requestClose: () => void;
|
||||
};
|
||||
export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
||||
const mx = useMatrixClient();
|
||||
const ct = useClient();
|
||||
const [developerTools, setDeveloperTools] = useSetting(settingsAtom, 'developerTools');
|
||||
|
||||
const [expand, setExpend] = useState(false);
|
||||
const [accountDataType, setAccountDataType] = useState<string | null>();
|
||||
const [editAccountData, setEditAccountData] = useState<AccountDataEvent | null>();
|
||||
|
||||
const submitAccountData: AccountDataSubmitCallback = useCallback(
|
||||
async (type, content) => {
|
||||
await mx.setAccountData(type, content);
|
||||
const resp = await ct.requestAuthJSON(
|
||||
putAccountData({
|
||||
pathParams: { type, userId: ct.session.userId },
|
||||
body: content,
|
||||
})
|
||||
);
|
||||
const [err] = await parseMatrixResp(resp);
|
||||
if (err) throw new Error(err.data.error ?? err.data.errcode);
|
||||
},
|
||||
[mx]
|
||||
[ct]
|
||||
);
|
||||
|
||||
if (accountDataType !== undefined) {
|
||||
if (editAccountData !== undefined) {
|
||||
return (
|
||||
<AccountDataEditor
|
||||
type={accountDataType ?? undefined}
|
||||
content={accountDataType ? mx.getAccountData(accountDataType)?.getContent() : undefined}
|
||||
event={editAccountData ?? undefined}
|
||||
submitChange={submitAccountData}
|
||||
requestClose={() => setAccountDataType(undefined)}
|
||||
requestClose={() => setEditAccountData(undefined)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -92,9 +102,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
description="Copy access token to clipboard."
|
||||
after={
|
||||
<Button
|
||||
onClick={() =>
|
||||
copyToClipboard(mx.getAccessToken() ?? '<NO_ACCESS_TOKEN_FOUND>')
|
||||
}
|
||||
onClick={() => copyToClipboard(ct.session.accessToken)}
|
||||
variant="Secondary"
|
||||
fill="Soft"
|
||||
size="300"
|
||||
|
|
@ -112,7 +120,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
<AccountData
|
||||
expand={expand}
|
||||
onExpandToggle={setExpend}
|
||||
onSelect={setAccountDataType}
|
||||
onSelect={setEditAccountData}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -23,3 +23,15 @@ export function useAccountData<T extends AccountDataEvent>(
|
|||
useCallback((v) => v?.event as T | undefined, [])
|
||||
);
|
||||
}
|
||||
|
||||
export function useAccountDataEvents(): PendingObservableResult<AccountDataEvent[]> {
|
||||
const ct = useClient();
|
||||
const observablePromise = useMemo(() => ct.storage.accountData.observableRead.getAll(), [ct]);
|
||||
|
||||
const result = useObservableValuePromise(observablePromise);
|
||||
|
||||
return useComputedPendingObservableResult(
|
||||
result,
|
||||
useCallback((objs) => objs.map((o) => o.event), [])
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue