mirror of
https://github.com/owncast/owncast.git
synced 2024-10-24 13:35:57 +03:00
Refactor action buttons callback
This commit is contained in:
parent
fadc529a4a
commit
3fbbecc0e8
4 changed files with 147 additions and 113 deletions
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
import { ActionButton } from './ActionButton';
|
import { ActionButton } from './ActionButton';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -14,8 +15,14 @@ export default {
|
||||||
},
|
},
|
||||||
} as ComponentMeta<typeof ActionButton>;
|
} as ComponentMeta<typeof ActionButton>;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
const itemSelected = a => {
|
||||||
const Template: ComponentStory<typeof ActionButton> = args => <ActionButton {...args} />;
|
console.log('itemSelected', a);
|
||||||
|
action(a.title);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Template: ComponentStory<typeof ActionButton> = args => (
|
||||||
|
<ActionButton externalActionSelected={itemSelected} {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export const Example1 = Template.bind({});
|
export const Example1 = Template.bind({});
|
||||||
|
|
|
@ -1,46 +1,30 @@
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { FC, useState } from 'react';
|
import { FC } from 'react';
|
||||||
import { Modal } from '../../ui/Modal/Modal';
|
|
||||||
import { ExternalAction } from '../../../interfaces/external-action';
|
import { ExternalAction } from '../../../interfaces/external-action';
|
||||||
import styles from './ActionButton.module.scss';
|
import styles from './ActionButton.module.scss';
|
||||||
|
|
||||||
export type ActionButtonProps = {
|
export type ActionButtonProps = {
|
||||||
action: ExternalAction;
|
action: ExternalAction;
|
||||||
primary?: boolean;
|
primary?: boolean;
|
||||||
|
externalActionSelected: (action: ExternalAction) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActionButton: FC<ActionButtonProps> = ({
|
export const ActionButton: FC<ActionButtonProps> = ({
|
||||||
action: { url, title, description, icon, color, openExternally },
|
action,
|
||||||
primary = true,
|
primary = true,
|
||||||
|
externalActionSelected,
|
||||||
}) => {
|
}) => {
|
||||||
const [showModal, setShowModal] = useState(false);
|
const { title, description, icon, color } = action;
|
||||||
|
|
||||||
const onButtonClicked = () => {
|
|
||||||
if (openExternally) {
|
|
||||||
window.open(url, '_blank');
|
|
||||||
} else {
|
|
||||||
setShowModal(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Button
|
||||||
<Button
|
type={primary ? 'primary' : 'default'}
|
||||||
type={primary ? 'primary' : 'default'}
|
className={`${styles.button}`}
|
||||||
className={`${styles.button}`}
|
onClick={() => externalActionSelected(action)}
|
||||||
onClick={onButtonClicked}
|
style={{ backgroundColor: color }}
|
||||||
style={{ backgroundColor: color }}
|
>
|
||||||
>
|
{icon && <img src={icon} className={`${styles.icon}`} alt={description} />}
|
||||||
{icon && <img src={icon} className={`${styles.icon}`} alt={description} />}
|
{title}
|
||||||
{title}
|
</Button>
|
||||||
</Button>
|
|
||||||
<Modal
|
|
||||||
title={description || title}
|
|
||||||
url={url}
|
|
||||||
open={showModal}
|
|
||||||
height="80vh"
|
|
||||||
handleCancel={() => setShowModal(false)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
|
import { action } from '@storybook/addon-actions';
|
||||||
import { ActionButtonRow } from './ActionButtonRow';
|
import { ActionButtonRow } from './ActionButtonRow';
|
||||||
import { ActionButton } from '../ActionButton/ActionButton';
|
import { ActionButton } from '../ActionButton/ActionButton';
|
||||||
|
|
||||||
|
@ -42,7 +43,12 @@ const actions = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const buttons = actions.map(action => <ActionButton action={action} />);
|
const itemSelected = a => {
|
||||||
|
console.log('itemSelected', a);
|
||||||
|
action(a.title);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttons = actions.map(a => <ActionButton externalActionSelected={itemSelected} action={a} />);
|
||||||
export const Example1 = Template.bind({});
|
export const Example1 = Template.bind({});
|
||||||
Example1.args = {
|
Example1.args = {
|
||||||
buttons,
|
buttons,
|
||||||
|
|
|
@ -34,13 +34,11 @@ import { ServerStatus } from '../../../interfaces/server-status.model';
|
||||||
import { Statusbar } from '../Statusbar/Statusbar';
|
import { Statusbar } from '../Statusbar/Statusbar';
|
||||||
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
||||||
import { FollowerCollection } from '../followers/FollowerCollection/FollowerCollection';
|
import { FollowerCollection } from '../followers/FollowerCollection/FollowerCollection';
|
||||||
|
import { ExternalAction } from '../../../interfaces/external-action';
|
||||||
|
import { Modal } from '../Modal/Modal';
|
||||||
|
|
||||||
const { Content: AntContent } = Layout;
|
const { Content: AntContent } = Layout;
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Modal = dynamic(() => import('../Modal/Modal').then(mod => mod.Modal));
|
|
||||||
|
|
||||||
const BrowserNotifyModal = dynamic(() =>
|
const BrowserNotifyModal = dynamic(() =>
|
||||||
import('../../modals/BrowserNotifyModal/BrowserNotifyModal').then(mod => mod.BrowserNotifyModal),
|
import('../../modals/BrowserNotifyModal/BrowserNotifyModal').then(mod => mod.BrowserNotifyModal),
|
||||||
);
|
);
|
||||||
|
@ -163,6 +161,19 @@ const MobileContent = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ExternalModal = ({ externalActionToDisplay, setExternalActionToDisplay }) => {
|
||||||
|
const { title, description, url } = externalActionToDisplay;
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={description || title}
|
||||||
|
url={url}
|
||||||
|
open={!!externalActionToDisplay}
|
||||||
|
height="80vh"
|
||||||
|
handleCancel={() => setExternalActionToDisplay(null)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Content: FC = () => {
|
export const Content: FC = () => {
|
||||||
const appState = useRecoilValue<AppStateOptions>(appStateAtom);
|
const appState = useRecoilValue<AppStateOptions>(appStateAtom);
|
||||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
|
@ -194,9 +205,23 @@ export const Content: FC = () => {
|
||||||
const { account: fediverseAccount } = federation;
|
const { account: fediverseAccount } = federation;
|
||||||
const { browser: browserNotifications } = notifications;
|
const { browser: browserNotifications } = notifications;
|
||||||
const { enabled: browserNotificationsEnabled } = browserNotifications;
|
const { enabled: browserNotificationsEnabled } = browserNotifications;
|
||||||
|
const [externalActionToDisplay, setExternalActionToDisplay] = useState<ExternalAction>(null);
|
||||||
|
|
||||||
|
const externalActionSelected = (action: ExternalAction) => {
|
||||||
|
const { openExternally, url } = action;
|
||||||
|
if (openExternally) {
|
||||||
|
window.open(url, '_blank');
|
||||||
|
} else {
|
||||||
|
setExternalActionToDisplay(action);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const externalActionButtons = externalActions.map(action => (
|
const externalActionButtons = externalActions.map(action => (
|
||||||
<ActionButton key={action.url} action={action} />
|
<ActionButton
|
||||||
|
key={action.url}
|
||||||
|
action={action}
|
||||||
|
externalActionSelected={externalActionSelected}
|
||||||
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
const incrementVisitCounter = () => {
|
const incrementVisitCounter = () => {
|
||||||
|
@ -232,88 +257,100 @@ export const Content: FC = () => {
|
||||||
incrementVisitCounter();
|
incrementVisitCounter();
|
||||||
checkIfMobile();
|
checkIfMobile();
|
||||||
window.addEventListener('resize', checkIfMobile);
|
window.addEventListener('resize', checkIfMobile);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', checkIfMobile);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const showChat = !chatDisabled && isChatAvailable && isChatVisible;
|
const showChat = !chatDisabled && isChatAvailable && isChatVisible;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.main}>
|
<>
|
||||||
<Spin wrapperClassName={styles.loadingSpinner} size="large" spinning={appState.appLoading}>
|
<div className={styles.main}>
|
||||||
<AntContent className={styles.root}>
|
<Spin wrapperClassName={styles.loadingSpinner} size="large" spinning={appState.appLoading}>
|
||||||
<div className={styles.mainSection}>
|
<AntContent className={styles.root}>
|
||||||
<div className={styles.topSection}>
|
<div className={styles.mainSection}>
|
||||||
{online && <OwncastPlayer source="/hls/stream.m3u8" online={online} />}
|
<div className={styles.topSection}>
|
||||||
{!online && !appState.appLoading && (
|
{online && <OwncastPlayer source="/hls/stream.m3u8" online={online} />}
|
||||||
<OfflineBanner
|
{!online && !appState.appLoading && (
|
||||||
streamName={name}
|
<OfflineBanner
|
||||||
customText={offlineMessage}
|
streamName={name}
|
||||||
notificationsEnabled={browserNotificationsEnabled}
|
customText={offlineMessage}
|
||||||
fediverseAccount={fediverseAccount}
|
notificationsEnabled={browserNotificationsEnabled}
|
||||||
lastLive={lastDisconnectTime}
|
fediverseAccount={fediverseAccount}
|
||||||
onNotifyClick={() => setShowNotifyPopup(true)}
|
lastLive={lastDisconnectTime}
|
||||||
/>
|
onNotifyClick={() => setShowNotifyPopup(true)}
|
||||||
)}
|
/>
|
||||||
{online && (
|
)}
|
||||||
<Statusbar
|
{online && (
|
||||||
online={online}
|
<Statusbar
|
||||||
lastConnectTime={lastConnectTime}
|
online={online}
|
||||||
lastDisconnectTime={lastDisconnectTime}
|
lastConnectTime={lastConnectTime}
|
||||||
viewerCount={viewerCount}
|
lastDisconnectTime={lastDisconnectTime}
|
||||||
/>
|
viewerCount={viewerCount}
|
||||||
)}
|
/>
|
||||||
</div>
|
)}
|
||||||
<div className={styles.midSection}>
|
|
||||||
<div className={styles.buttonsLogoTitleSection}>
|
|
||||||
<ActionButtonRow>
|
|
||||||
{externalActionButtons}
|
|
||||||
<FollowButton size="small" />
|
|
||||||
<NotifyReminderPopup
|
|
||||||
open={showNotifyReminder}
|
|
||||||
notificationClicked={() => setShowNotifyPopup(true)}
|
|
||||||
notificationClosed={() => disableNotifyReminderPopup()}
|
|
||||||
>
|
|
||||||
<NotifyButton onClick={() => setShowNotifyPopup(true)} />
|
|
||||||
</NotifyReminderPopup>
|
|
||||||
</ActionButtonRow>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
title="Notify"
|
|
||||||
open={showNotifyPopup}
|
|
||||||
afterClose={() => disableNotifyReminderPopup()}
|
|
||||||
handleCancel={() => disableNotifyReminderPopup()}
|
|
||||||
>
|
|
||||||
<BrowserNotifyModal />
|
|
||||||
</Modal>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className={styles.midSection}>
|
||||||
|
<div className={styles.buttonsLogoTitleSection}>
|
||||||
|
<ActionButtonRow>
|
||||||
|
{externalActionButtons}
|
||||||
|
<FollowButton size="small" />
|
||||||
|
<NotifyReminderPopup
|
||||||
|
open={showNotifyReminder}
|
||||||
|
notificationClicked={() => setShowNotifyPopup(true)}
|
||||||
|
notificationClosed={() => disableNotifyReminderPopup()}
|
||||||
|
>
|
||||||
|
<NotifyButton onClick={() => setShowNotifyPopup(true)} />
|
||||||
|
</NotifyReminderPopup>
|
||||||
|
</ActionButtonRow>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="Notify"
|
||||||
|
open={showNotifyPopup}
|
||||||
|
afterClose={() => disableNotifyReminderPopup()}
|
||||||
|
handleCancel={() => disableNotifyReminderPopup()}
|
||||||
|
>
|
||||||
|
<BrowserNotifyModal />
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{isMobile && isChatVisible ? (
|
||||||
|
<MobileContent
|
||||||
|
name={name}
|
||||||
|
streamTitle={streamTitle}
|
||||||
|
summary={summary}
|
||||||
|
tags={tags}
|
||||||
|
socialHandles={socialHandles}
|
||||||
|
extraPageContent={extraPageContent}
|
||||||
|
messages={messages}
|
||||||
|
currentUser={currentUser}
|
||||||
|
showChat={showChat}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<DesktopContent
|
||||||
|
name={name}
|
||||||
|
streamTitle={streamTitle}
|
||||||
|
summary={summary}
|
||||||
|
tags={tags}
|
||||||
|
socialHandles={socialHandles}
|
||||||
|
extraPageContent={extraPageContent}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isMobile && isChatVisible ? (
|
{showChat && !isMobile && <Sidebar />}
|
||||||
<MobileContent
|
</AntContent>
|
||||||
name={name}
|
</Spin>
|
||||||
streamTitle={streamTitle}
|
{!isMobile && <Footer version={version} />}
|
||||||
summary={summary}
|
</div>
|
||||||
tags={tags}
|
|
||||||
socialHandles={socialHandles}
|
{externalActionToDisplay && (
|
||||||
extraPageContent={extraPageContent}
|
<ExternalModal
|
||||||
messages={messages}
|
externalActionToDisplay={externalActionToDisplay}
|
||||||
currentUser={currentUser}
|
setExternalActionToDisplay={setExternalActionToDisplay}
|
||||||
showChat={showChat}
|
/>
|
||||||
/>
|
)}
|
||||||
) : (
|
</>
|
||||||
<DesktopContent
|
|
||||||
name={name}
|
|
||||||
streamTitle={streamTitle}
|
|
||||||
summary={summary}
|
|
||||||
tags={tags}
|
|
||||||
socialHandles={socialHandles}
|
|
||||||
extraPageContent={extraPageContent}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{showChat && !isMobile && <Sidebar />}
|
|
||||||
</AntContent>
|
|
||||||
</Spin>
|
|
||||||
{!isMobile && <Footer version={version} />}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default Content;
|
export default Content;
|
||||||
|
|
Loading…
Reference in a new issue