feat(modals): port SignedOut and SignOutSessions

This commit is contained in:
Paul Makles 2022-06-18 11:56:05 +01:00
parent 0ee7b73d61
commit 374be319c4
9 changed files with 60 additions and 56 deletions

View file

@ -8,8 +8,6 @@ import { ExternalLinkModal } from "./modals/ExternalLinkPrompt";
import { InputModal } from "./modals/Input"; import { InputModal } from "./modals/Input";
import { OnboardingModal } from "./modals/Onboarding"; import { OnboardingModal } from "./modals/Onboarding";
import { PromptModal } from "./modals/Prompt"; import { PromptModal } from "./modals/Prompt";
import { SessionsModal } from "./modals/SessionsPrompt";
import { SignedOutModal } from "./modals/SignedOut";
import { TokenRevealModal } from "./modals/TokenReveal"; import { TokenRevealModal } from "./modals/TokenReveal";
export interface Props { export interface Props {
@ -30,8 +28,6 @@ export default function Modals({ screen, openScreen }: Props) {
return <InputModal onClose={onClose} {...screen} />; return <InputModal onClose={onClose} {...screen} />;
case "error": case "error":
return <ErrorModal onClose={onClose} {...screen} />; return <ErrorModal onClose={onClose} {...screen} />;
case "signed_out":
return <SignedOutModal onClose={onClose} {...screen} />;
case "clipboard": case "clipboard":
return <ClipboardModal onClose={onClose} {...screen} />; return <ClipboardModal onClose={onClose} {...screen} />;
case "token_reveal": case "token_reveal":
@ -40,8 +36,6 @@ export default function Modals({ screen, openScreen }: Props) {
return <OnboardingModal onClose={onClose} {...screen} />; return <OnboardingModal onClose={onClose} {...screen} />;
case "external_link_prompt": case "external_link_prompt":
return <ExternalLinkModal onClose={onClose} {...screen} />; return <ExternalLinkModal onClose={onClose} {...screen} />;
case "sessions":
return <SessionsModal onClose={onClose} {...screen} />;
} }
return null; return null;

View file

@ -35,7 +35,7 @@ function RenderLog({ post }: { post: ChangelogPost }) {
} }
/** /**
* Changelog rendering modal * Changelog modal
*/ */
export default function Changelog({ export default function Changelog({
initial, initial,

View file

@ -7,6 +7,10 @@ import { noop, noopTrue } from "../../../lib/js";
import { APP_VERSION } from "../../../version"; import { APP_VERSION } from "../../../version";
import { ModalProps } from "../types"; import { ModalProps } from "../types";
/**
* Out-of-date indicator which instructs users
* that their client needs to be updated
*/
export default function OutOfDate({ export default function OutOfDate({
onClose, onClose,
version, version,

View file

@ -1,31 +1,35 @@
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import { useCallback } from "preact/hooks";
import { Modal } from "@revoltchat/ui"; import { Modal } from "@revoltchat/ui";
interface Props { import { noopTrue } from "../../../lib/js";
onClose: () => void;
confirm: () => void; import { ModalProps } from "../types";
}
/**
* Confirm whether a user wants to sign out of all other sessions
*/
export function SignOutSessions(props: ModalProps<"sign_out_sessions">) {
const onClick = useCallback(() => {
props.onDeleting();
props.client.api.delete("/auth/session/all").then(props.onDelete);
return true;
}, []);
export function SessionsModal({ onClose, confirm }: Props) {
return ( return (
<Modal <Modal
onClose={onClose} {...props}
title={<Text id={"app.special.modals.sessions.title"} />} title={<Text id={"app.special.modals.sessions.title"} />}
actions={[ actions={[
{ {
onClick: () => { onClick: noopTrue,
onClose();
},
confirmation: true,
palette: "accent", palette: "accent",
confirmation: true,
children: <Text id="app.special.modals.actions.back" />, children: <Text id="app.special.modals.actions.back" />,
}, },
{ {
onClick: () => { onClick,
confirm();
onClose();
},
confirmation: true, confirmation: true,
children: <Text id="app.special.modals.sessions.accept" />, children: <Text id="app.special.modals.sessions.accept" />,
}, },

View file

@ -2,18 +2,21 @@ import { Text } from "preact-i18n";
import { Modal } from "@revoltchat/ui"; import { Modal } from "@revoltchat/ui";
interface Props { import { noopTrue } from "../../../lib/js";
onClose: () => void;
}
export function SignedOutModal({ onClose }: Props) { import { ModalProps } from "../types";
/**
* Indicate that the user has been signed out of their account
*/
export function SignedOut(props: ModalProps<"signed_out">) {
return ( return (
<Modal <Modal
onClose={onClose} {...props}
title={<Text id="app.special.modals.signed_out" />} title={<Text id="app.special.modals.signed_out" />}
actions={[ actions={[
{ {
onClick: onClose, onClick: noopTrue,
confirmation: true, confirmation: true,
children: <Text id="app.special.modals.actions.ok" />, children: <Text id="app.special.modals.actions.ok" />,
}, },

View file

@ -13,6 +13,8 @@ import MFAEnableTOTP from "./components/MFAEnableTOTP";
import MFAFlow from "./components/MFAFlow"; import MFAFlow from "./components/MFAFlow";
import MFARecovery from "./components/MFARecovery"; import MFARecovery from "./components/MFARecovery";
import OutOfDate from "./components/OutOfDate"; import OutOfDate from "./components/OutOfDate";
import { SignOutSessions } from "./components/SignOutSessions";
import { SignedOut } from "./components/SignedOut";
import Test from "./components/Test"; import Test from "./components/Test";
import { Modal } from "./types"; import { Modal } from "./types";
@ -142,5 +144,7 @@ export const modalController = new ModalControllerExtended({
mfa_recovery: MFARecovery, mfa_recovery: MFARecovery,
mfa_enable_totp: MFAEnableTOTP, mfa_enable_totp: MFAEnableTOTP,
out_of_date: OutOfDate, out_of_date: OutOfDate,
signed_out: SignedOut,
sign_out_sessions: SignOutSessions,
test: Test, test: Test,
}); });

View file

@ -33,7 +33,13 @@ export type Modal = {
initial?: number; initial?: number;
} }
| { | {
type: "test"; client: Client;
onDelete: () => void;
onDeleting: () => void;
type: "sign_out_sessions";
}
| {
type: "test" | "signed_out";
} }
); );

View file

@ -10,6 +10,7 @@ import { Preloader } from "@revoltchat/ui";
import { useApplicationState } from "../../mobx/State"; import { useApplicationState } from "../../mobx/State";
import { useIntermediate } from "../intermediate/Intermediate"; import { useIntermediate } from "../intermediate/Intermediate";
import { modalController } from "../modals";
import { registerEvents } from "./events"; import { registerEvents } from "./events";
import { takeError } from "./util"; import { takeError } from "./util";
@ -68,7 +69,7 @@ export default observer(({ children }: Props) => {
const error = takeError(err); const error = takeError(err);
if (error === "Forbidden" || error === "Unauthorized") { if (error === "Forbidden" || error === "Unauthorized") {
client.logout(true); client.logout(true);
openScreen({ id: "signed_out" }); modalController.push({ type: "signed_out" });
} else { } else {
setStatus(ClientStatus.DISCONNECTED); setStatus(ClientStatus.DISCONNECTED);
openScreen({ id: "error", error }); openScreen({ id: "error", error });

View file

@ -27,7 +27,7 @@ import {
} from "@revoltchat/ui"; } from "@revoltchat/ui";
import { dayjs } from "../../../context/Locale"; import { dayjs } from "../../../context/Locale";
import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { modalController } from "../../../context/modals";
import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { AppContext } from "../../../context/revoltjs/RevoltClient";
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
@ -43,8 +43,6 @@ export function Sessions() {
const [attemptingDelete, setDelete] = useState<string[]>([]); const [attemptingDelete, setDelete] = useState<string[]>([]);
const history = useHistory(); const history = useHistory();
const { openScreen } = useIntermediate();
function switchPage(to: string) { function switchPage(to: string) {
history.replace(`/settings/${to}`); history.replace(`/settings/${to}`);
} }
@ -217,32 +215,22 @@ export function Sessions() {
})} })}
<hr /> <hr />
<CategoryButton <CategoryButton
onClick={async () => { onClick={async () =>
openScreen({ modalController.push({
id: "sessions", type: "sign_out_sessions",
confirm: async () => { client,
// ! FIXME: add to rAuth onDeleting: () =>
const del: string[] = []; setDelete(
render.forEach((session) => { render
if (deviceId !== session._id) { .filter((x) => x._id !== deviceId)
del.push(session._id); .map((x) => x._id),
} ),
}); onDelete: () =>
setDelete(del);
for (const id of del) {
await client.api.delete(
`/auth/session/${id as ""}`,
);
}
setSessions( setSessions(
sessions.filter((x) => x._id === deviceId), sessions.filter((x) => x._id === deviceId),
); ),
}, })
}); }
}}
icon={<LogOut size={24} color={"var(--error)"} />} icon={<LogOut size={24} color={"var(--error)"} />}
action={"chevron"} action={"chevron"}
description={ description={