Add undesigned functionality of follow modal. For #1862

This commit is contained in:
Gabe Kangas 2022-06-24 15:55:53 -07:00
parent 78dc183c11
commit 5d65b4b3b1
No known key found for this signature in database
GPG key ID: 9A56337728BC81EA
4 changed files with 101 additions and 13 deletions

View file

@ -1,11 +1,17 @@
import { Button } from 'antd'; import { Button } from 'antd';
import { HeartFilled } from '@ant-design/icons'; import { HeartFilled } from '@ant-design/icons';
import { useState } from 'react'; import { useState } from 'react';
import { useRecoilValue } from 'recoil';
import Modal from '../ui/Modal/Modal'; import Modal from '../ui/Modal/Modal';
import FollowModal from '../modals/Follow/FollowModal';
import s from './ActionButton.module.scss'; import s from './ActionButton.module.scss';
import { clientConfigStateAtom } from '../stores/ClientConfigStore';
import { ClientConfig } from '../../interfaces/client-config.model';
export default function FollowButton() { export default function FollowButton() {
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
const { name } = clientConfig;
const buttonClicked = () => { const buttonClicked = () => {
setShowModal(true); setShowModal(true);
@ -21,11 +27,9 @@ export default function FollowButton() {
> >
Follow Follow
</Button> </Button>
<Modal <Modal title={`Follow ${name}`} visible={showModal} handleCancel={() => setShowModal(false)}>
title="Follow <servername>" <FollowModal handleClose={() => setShowModal(false)} />
visible={showModal} </Modal>
handleCancel={() => setShowModal(false)}
/>
</> </>
); );
} }

View file

@ -0,0 +1,90 @@
import { Input, Button, Alert, Spin } from 'antd';
import { useState } from 'react';
const ENDPOINT = '/api/remotefollow';
interface Props {
handleClose: () => void;
}
function validateAccount(a) {
const sanitized = a.replace(/^@+/, '');
const regex =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return regex.test(String(sanitized).toLowerCase());
}
export default function FollowModal(props: Props) {
const { handleClose } = props;
const [account, setAccount] = useState(null);
const [valid, setValid] = useState(false);
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const handleAccountChange = a => {
setAccount(a);
if (validateAccount(a)) {
setValid(true);
} else {
setValid(false);
}
};
const remoteFollowButtonPressed = async () => {
if (!valid) {
return;
}
setLoading(true);
try {
const sanitizedAccount = account.replace(/^@+/, '');
const request = { account: sanitizedAccount };
const rawResponse = await fetch(ENDPOINT, {
method: 'POST',
body: JSON.stringify(request),
});
const result = await rawResponse.json();
if (result.redirectUrl) {
window.open(result.redirectUrl, '_blank');
handleClose();
}
if (!result.success) {
setErrorMessage(result.message);
setLoading(false);
return;
}
if (!result.redirectUrl) {
setErrorMessage('Unable to follow.');
setLoading(false);
return;
}
} catch (e) {
setErrorMessage(e.message);
}
setLoading(false);
};
return (
<Spin spinning={loading}>
{errorMessage && (
<Alert message="Follow Error" description={errorMessage} type="error" showIcon />
)}
<Input
value={account}
size="large"
onChange={e => handleAccountChange(e.target.value)}
placeholder="Your fediverse account @account@server"
defaultValue={account}
/>
<Button disabled={!valid} onClick={remoteFollowButtonPressed}>
Follow
</Button>
<div>
Information about following a Fediverse account and next steps how to create a Fediverse
account goes here.
</div>
</Spin>
);
}

View file

@ -1,6 +0,0 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
interface Props {}
export default function FollowModal(props: Props) {
return <div>Component goes here</div>;
}

View file

@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react'; import { ComponentStory, ComponentMeta } from '@storybook/react';
import FollowModal from '../components/modals/FollowModal'; import FollowModal from '../components/modals/Follow/FollowModal';
import FollowModalMock from './assets/mocks/follow-modal.png'; import FollowModalMock from './assets/mocks/follow-modal.png';
const Example = () => ( const Example = () => (
<div> <div>
<FollowModal /> <FollowModal handleClose={null} />
</div> </div>
); );