// Copyright (c) 2020-2021 Drew Lemmy
// This file is part of KristWeb 2 under GPL-3.0.
// Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt
import React, { FC, useState } from "react";
import { TooltipPlacement } from "antd/lib/tooltip";
import { useSelector, shallowEqual } from "react-redux";
import { RootState } from "@store";
import { AuthMasterPasswordPopover } from "./AuthMasterPasswordPopover";
import { SetMasterPasswordModal } from "./SetMasterPasswordModal";
import "./AuthorisedAction.less";
import Debug from "debug";
const debug = Debug("kristweb:authorised-action");
interface Props {
encrypt?: boolean;
onAuthed?: () => void;
popoverPlacement?: TooltipPlacement;
children: React.ReactNode;
}
export const AuthorisedAction: FC<Props> = ({ encrypt, onAuthed, popoverPlacement, children }) => {
const { isAuthed, hasMasterPassword }
= useSelector((s: RootState) => s.masterPassword, shallowEqual);
// Don't render the modal and popover unless we absolutely have to
const [clicked, setClicked] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
// This is used to pass the 'onClick' prop down to the child. The child MUST
// support the onClick prop.
// NOTE: If the child is a custom component, make sure it passes `...props`
// down to its child.
// TODO: Support multiple children?
const child = React.Children.only(children) as React.ReactElement;
if (isAuthed) {
// The user is authed with their master password, just perform the action
// directly:
return React.cloneElement(child, { onClick: (e: MouseEvent) => {
e.preventDefault();
debug("authorised action occurred: was already authed");
if (onAuthed) onAuthed();
}});
} else if (!hasMasterPassword) {
// The user does not yet have a master password, prompt them to create one:
return <>
{React.cloneElement(child, { onClick: (e: MouseEvent) => {
e.preventDefault();
debug("authorised action postponed: no master password set");
if (!clicked) setClicked(true);
setModalVisible(true);
}})}
{clicked && <SetMasterPasswordModal
visible={modalVisible}
onCancel={() => setModalVisible(false)}
onSubmit={() => {
debug("authorised action occurred: master password now set, continuing with action");
setModalVisible(false);
if (onAuthed) onAuthed();
}}
/>}
</>;
} else {
// The user has a master password set but is not logged in, prompt them to
// enter it:
return <AuthMasterPasswordPopover
encrypt={encrypt}
onSubmit={() => {
debug("authorised action occurred: master password provided");
if (onAuthed) onAuthed();
}}
placement={popoverPlacement}
>
{children}
</AuthMasterPasswordPopover>;
}
};