mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-07 01:15:28 +00:00
chore: refactor account UI
This commit is contained in:
@@ -4,12 +4,7 @@ import { ContextMenuTrigger } from "preact-context-menu";
|
||||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import {
|
||||
LinkProvider,
|
||||
Preloader,
|
||||
TextProvider,
|
||||
TrigProvider,
|
||||
} from "@revoltchat/ui";
|
||||
import { Preloader, UIProvider } from "@revoltchat/ui";
|
||||
|
||||
import { hydrateState } from "../mobx/State";
|
||||
|
||||
@@ -20,6 +15,13 @@ import ModalRenderer from "./modals/ModalRenderer";
|
||||
import Client from "./revoltjs/RevoltClient";
|
||||
import SyncManager from "./revoltjs/SyncManager";
|
||||
|
||||
const uiContext = {
|
||||
Link,
|
||||
Text: Text as any,
|
||||
Trigger: ContextMenuTrigger,
|
||||
emitAction: () => {},
|
||||
};
|
||||
|
||||
/**
|
||||
* This component provides all of the application's context layers.
|
||||
* @param param0 Provided children
|
||||
@@ -35,21 +37,17 @@ export default function Context({ children }: { children: Children }) {
|
||||
|
||||
return (
|
||||
<Router basename={import.meta.env.BASE_URL}>
|
||||
<LinkProvider value={Link}>
|
||||
<TextProvider value={Text as any}>
|
||||
<TrigProvider value={ContextMenuTrigger}>
|
||||
<Locale>
|
||||
<Intermediate>
|
||||
<Client>
|
||||
{children}
|
||||
<SyncManager />
|
||||
</Client>
|
||||
</Intermediate>
|
||||
<ModalRenderer />
|
||||
</Locale>
|
||||
</TrigProvider>
|
||||
</TextProvider>
|
||||
</LinkProvider>
|
||||
<UIProvider value={uiContext}>
|
||||
<Locale>
|
||||
<Intermediate>
|
||||
<Client>
|
||||
{children}
|
||||
<SyncManager />
|
||||
</Client>
|
||||
</Intermediate>
|
||||
<ModalRenderer />
|
||||
</Locale>
|
||||
</UIProvider>
|
||||
<Theme />
|
||||
</Router>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,12 @@ import { Key, Keyboard } from "@styled-icons/boxicons-solid";
|
||||
import { API } from "revolt.js";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
import { useCallback, useEffect, useState } from "preact/hooks";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
} from "preact/hooks";
|
||||
|
||||
import {
|
||||
Category,
|
||||
@@ -15,8 +20,6 @@ import {
|
||||
|
||||
import { noopTrue } from "../../../lib/js";
|
||||
|
||||
import { useApplicationState } from "../../../mobx/State";
|
||||
|
||||
import { ModalProps } from "../types";
|
||||
|
||||
const ICONS: Record<API.MFAMethod, React.FC<any>> = {
|
||||
@@ -34,12 +37,13 @@ function ResponseEntry({
|
||||
value?: API.MFAResponse;
|
||||
onChange: (v: API.MFAResponse) => void;
|
||||
}) {
|
||||
if (type === "Password") {
|
||||
return (
|
||||
<>
|
||||
<Category compact>
|
||||
<Text id={`login.${type.toLowerCase()}`} />
|
||||
</Category>
|
||||
return (
|
||||
<>
|
||||
<Category compact>
|
||||
<Text id={`login.${type.toLowerCase()}`} />
|
||||
</Category>
|
||||
|
||||
{type === "Password" && (
|
||||
<InputBox
|
||||
type="password"
|
||||
value={(value as { password: string })?.password}
|
||||
@@ -47,56 +51,51 @@ function ResponseEntry({
|
||||
onChange({ password: e.currentTarget.value })
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA ticket creation flow
|
||||
*/
|
||||
export default function MFAFlow({
|
||||
callback,
|
||||
onClose,
|
||||
...props
|
||||
}: ModalProps<"mfa_flow">) {
|
||||
const state = useApplicationState();
|
||||
|
||||
export default function MFAFlow({ onClose, ...props }: ModalProps<"mfa_flow">) {
|
||||
const [methods, setMethods] = useState<API.MFAMethod[] | undefined>(
|
||||
props.state === "unknown" ? props.available_methods : undefined,
|
||||
);
|
||||
|
||||
// Current state of the modal
|
||||
const [selectedMethod, setSelected] = useState<API.MFAMethod>();
|
||||
const [response, setResponse] = useState<API.MFAResponse>();
|
||||
|
||||
// Fetch available methods if they have not been provided.
|
||||
useEffect(() => {
|
||||
if (!methods && props.state === "known") {
|
||||
props.client.api.get("/auth/mfa/methods").then(setMethods);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Always select first available method if only one available.
|
||||
useLayoutEffect(() => {
|
||||
if (methods && methods.length === 1) {
|
||||
setSelected(methods[0]);
|
||||
}
|
||||
}, [methods]);
|
||||
|
||||
// Callback to generate a new ticket or send response back up the chain.
|
||||
const generateTicket = useCallback(async () => {
|
||||
if (response) {
|
||||
let ticket;
|
||||
|
||||
if (props.state === "known") {
|
||||
ticket = await props.client.api.put(
|
||||
const ticket = await props.client.api.put(
|
||||
"/auth/mfa/ticket",
|
||||
response,
|
||||
);
|
||||
|
||||
props.callback(ticket);
|
||||
} else {
|
||||
ticket = await state.config
|
||||
.createClient()
|
||||
.api.put("/auth/mfa/ticket", response, {
|
||||
headers: {
|
||||
"X-MFA-Ticket": props.ticket.token,
|
||||
},
|
||||
});
|
||||
props.callback(response);
|
||||
}
|
||||
|
||||
callback(ticket);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -122,8 +121,12 @@ export default function MFAFlow({
|
||||
},
|
||||
{
|
||||
palette: "plain",
|
||||
children: "Back",
|
||||
onClick: () => setSelected(undefined),
|
||||
children:
|
||||
methods!.length === 1 ? "Cancel" : "Back",
|
||||
onClick: () =>
|
||||
methods!.length === 1
|
||||
? true
|
||||
: void setSelected(undefined),
|
||||
},
|
||||
]
|
||||
: [
|
||||
|
||||
@@ -5,16 +5,16 @@ export type Modal = {
|
||||
} & (
|
||||
| ({
|
||||
type: "mfa_flow";
|
||||
callback: (ticket: API.MFATicket) => void;
|
||||
} & (
|
||||
| {
|
||||
state: "known";
|
||||
client: Client;
|
||||
callback: (ticket: API.MFATicket) => void;
|
||||
}
|
||||
| {
|
||||
state: "unknown";
|
||||
available_methods: API.MFAMethod[];
|
||||
ticket: API.MFATicket & { validated: false };
|
||||
callback: (response: API.MFAResponse) => void;
|
||||
}
|
||||
))
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user