Browse Source

Add remote fediverse follow modal. Closes #1862

pull/2057/head
Gabe Kangas 3 years ago
parent
commit
1a9b9f53fc
No known key found for this signature in database
GPG Key ID: 9A56337728BC81EA
  1. 13
      web/components/action-buttons/FollowButton.tsx
  2. 1
      web/components/chat/ChatUserMessage/ChatUserMessage.module.scss
  3. 44
      web/components/modals/Follow/FollowModal.module.scss
  4. 77
      web/components/modals/Follow/FollowModal.tsx
  5. 11
      web/components/ui/Modal/Modal.tsx

13
web/components/action-buttons/FollowButton.tsx

@ -11,7 +11,8 @@ import { ClientConfig } from '../../interfaces/client-config.model'; @@ -11,7 +11,8 @@ import { ClientConfig } from '../../interfaces/client-config.model';
export default function FollowButton(props: any) {
const [showModal, setShowModal] = useState(false);
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
const { name } = clientConfig;
const { name, federation } = clientConfig;
const { account } = federation;
const buttonClicked = () => {
setShowModal(true);
@ -28,8 +29,14 @@ export default function FollowButton(props: any) { @@ -28,8 +29,14 @@ export default function FollowButton(props: any) {
>
Follow
</Button>
<Modal title={`Follow ${name}`} visible={showModal} handleCancel={() => setShowModal(false)}>
<FollowModal handleClose={() => setShowModal(false)} />
<Modal
title={`Follow ${name}`}
visible={showModal}
handleCancel={() => setShowModal(false)}
width="550px"
height="200px"
>
<FollowModal account={account} name={name} handleClose={() => setShowModal(false)} />
</Modal>
</>
);

1
web/components/chat/ChatUserMessage/ChatUserMessage.module.scss

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
padding-left: 0.35em;
padding-right: 0.35em;
color: var(--theme-text-highlight);
background-color: var(--color-bg-highlight);
}
}

44
web/components/modals/Follow/FollowModal.module.scss

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
.header {
font-family: var(--theme-text-display-font-family);
font-size: 0.8rem;
}
.buttons {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.instructions {
font-family: var(--theme-text-display-font-family);
font-size: 0.7rem;
font-weight: 600;
}
.footer {
font-size: 0.5rem;
}
.account {
display: flex;
flex-direction: row;
margin-top: 5px;
margin-bottom: 10px;
font-size: 0.8rem;
.logo {
border-radius: 50%;
width: 4em;
height: 4em;
}
.username {
display: flex;
flex-direction: column;
margin-left: 10px;
margin-top: 5px;
.name {
font-weight: 600;
}
}
}

77
web/components/modals/Follow/FollowModal.tsx

@ -1,10 +1,13 @@ @@ -1,10 +1,13 @@
import { Input, Button, Alert, Spin } from 'antd';
import { Input, Button, Alert, Spin, Space } from 'antd';
import { useState } from 'react';
import s from './FollowModal.module.scss';
const ENDPOINT = '/api/remotefollow';
interface Props {
handleClose: () => void;
account: string;
name: string;
}
function validateAccount(a) {
@ -15,14 +18,14 @@ function validateAccount(a) { @@ -15,14 +18,14 @@ function validateAccount(a) {
}
export default function FollowModal(props: Props) {
const { handleClose } = props;
const [account, setAccount] = useState(null);
const { handleClose, account, name } = props;
const [remoteAccount, setRemoteAccount] = useState(null);
const [valid, setValid] = useState(false);
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const handleAccountChange = a => {
setAccount(a);
setRemoteAccount(a);
if (validateAccount(a)) {
setValid(true);
} else {
@ -30,6 +33,10 @@ export default function FollowModal(props: Props) { @@ -30,6 +33,10 @@ export default function FollowModal(props: Props) {
}
};
const joinButtonPressed = () => {
window.open('https://owncast.online/join-fediverse', '_blank');
};
const remoteFollowButtonPressed = async () => {
if (!valid) {
return;
@ -38,7 +45,7 @@ export default function FollowModal(props: Props) { @@ -38,7 +45,7 @@ export default function FollowModal(props: Props) {
setLoading(true);
try {
const sanitizedAccount = account.replace(/^@+/, '');
const sanitizedAccount = remoteAccount.replace(/^@+/, '');
const request = { account: sanitizedAccount };
const rawResponse = await fetch(ENDPOINT, {
method: 'POST',
@ -67,24 +74,48 @@ export default function FollowModal(props: Props) { @@ -67,24 +74,48 @@ export default function FollowModal(props: Props) {
};
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.
<Space direction="vertical">
<div className={s.header}>
By following this stream you'll get notified on the Fediverse when it goes live. Now is a
great time to{' '}
<a href="https://owncast.online/join-fediverse" target="_blank" rel="noreferrer">
learn about the Fediverse
</a>{' '}
if it's new to you.
</div>
</Spin>
<Spin spinning={loading}>
{errorMessage && (
<Alert message="Follow Error" description={errorMessage} type="error" showIcon />
)}
<div className={s.account}>
<img src="/logo" alt="logo" className={s.logo} />
<div className={s.username}>
<div className={s.name}>{name}</div>
<div>{account}</div>
</div>
</div>
<div>
<div className={s.instructions}>Enter your username @server to follow</div>
<Input
value={account}
size="large"
onChange={e => handleAccountChange(e.target.value)}
placeholder="Your fediverse account @account@server"
defaultValue={account}
/>
<div className={s.footer}>
You'll be redirected to your Fediverse server and asked to confirm the action.
</div>
</div>
<Space className={s.buttons}>
<Button disabled={!valid} onClick={remoteFollowButtonPressed}>
Follow
</Button>
<Button onClick={joinButtonPressed}>Join the Fediverse</Button>
</Space>
</Spin>
</Space>
);
}

11
web/components/ui/Modal/Modal.tsx

@ -11,15 +11,17 @@ interface Props { @@ -11,15 +11,17 @@ interface Props {
afterClose?: () => void;
children?: ReactNode;
height?: string;
width?: string;
}
export default function Modal(props: Props) {
const { title, url, visible, handleOk, handleCancel, afterClose, height, children } = props;
const { title, url, visible, handleOk, handleCancel, afterClose, height, width, children } =
props;
const [loading, setLoading] = useState(!!url);
const modalStyle = {
padding: '0px',
minHeight: height || '40vh',
minHeight: height,
};
const iframe = url && (
@ -45,7 +47,7 @@ export default function Modal(props: Props) { @@ -45,7 +47,7 @@ export default function Modal(props: Props) {
onCancel={handleCancel}
afterClose={afterClose}
bodyStyle={modalStyle}
width="70%"
width={width}
zIndex={9999}
footer={null}
centered
@ -70,5 +72,6 @@ Modal.defaultProps = { @@ -70,5 +72,6 @@ Modal.defaultProps = {
handleOk: undefined,
handleCancel: undefined,
afterClose: undefined,
height: undefined,
height: '40vh',
width: '70%',
};

Loading…
Cancel
Save