mirror of
https://github.com/owncast/owncast.git
synced 2025-11-03 04:27:18 +08:00
Wire up notify popup to hide/show at correct times. Closes #1911
This commit is contained in:
@ -1,30 +1,20 @@
|
|||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { NotificationFilled } from '@ant-design/icons';
|
import { NotificationFilled } from '@ant-design/icons';
|
||||||
import { useState } from 'react';
|
|
||||||
import Modal from '../ui/Modal/Modal';
|
|
||||||
import s from './ActionButton.module.scss';
|
import s from './ActionButton.module.scss';
|
||||||
import BrowserNotifyModal from '../modals/BrowserNotify/BrowserNotifyModal';
|
|
||||||
|
|
||||||
export default function NotifyButton() {
|
interface Props {
|
||||||
const [showModal, setShowModal] = useState(false);
|
onClick: () => void;
|
||||||
|
}
|
||||||
const buttonClicked = () => {
|
|
||||||
setShowModal(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
export default function NotifyButton({ onClick }: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
className={`${s.button}`}
|
className={`${s.button}`}
|
||||||
icon={<NotificationFilled />}
|
icon={<NotificationFilled />}
|
||||||
onClick={buttonClicked}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
Notify
|
Notify
|
||||||
</Button>
|
</Button>
|
||||||
<Modal title="Notify" visible={showModal} handleCancel={() => setShowModal(false)}>
|
|
||||||
<BrowserNotifyModal />
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
/* eslint-disable react/no-danger */
|
/* eslint-disable react/no-danger */
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Layout, Tabs, Spin } from 'antd';
|
import { Layout, Tabs, Spin } from 'antd';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
clientConfigStateAtom,
|
clientConfigStateAtom,
|
||||||
chatMessagesAtom,
|
chatMessagesAtom,
|
||||||
@ -34,6 +37,8 @@ import OfflineBanner from '../OfflineBanner/OfflineBanner';
|
|||||||
import { AppStateOptions } from '../../stores/application-state';
|
import { AppStateOptions } from '../../stores/application-state';
|
||||||
import FollowButton from '../../action-buttons/FollowButton';
|
import FollowButton from '../../action-buttons/FollowButton';
|
||||||
import NotifyButton from '../../action-buttons/NotifyButton';
|
import NotifyButton from '../../action-buttons/NotifyButton';
|
||||||
|
import Modal from '../Modal/Modal';
|
||||||
|
import BrowserNotifyModal from '../../modals/BrowserNotify/BrowserNotifyModal';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
@ -50,6 +55,8 @@ export default function ContentComponent() {
|
|||||||
|
|
||||||
const { extraPageContent, version, socialHandles, name, title, tags, summary } = clientConfig;
|
const { extraPageContent, version, socialHandles, name, title, tags, summary } = clientConfig;
|
||||||
const { viewerCount, lastConnectTime, lastDisconnectTime } = status;
|
const { viewerCount, lastConnectTime, lastDisconnectTime } = status;
|
||||||
|
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
||||||
|
const [showNotifyPopup, setShowNotifyPopup] = useState(false);
|
||||||
|
|
||||||
const followers: Follower[] = [];
|
const followers: Follower[] = [];
|
||||||
|
|
||||||
@ -71,6 +78,29 @@ export default function ContentComponent() {
|
|||||||
<ActionButton key={action.url} action={action} />
|
<ActionButton key={action.url} action={action} />
|
||||||
));
|
));
|
||||||
|
|
||||||
|
const incrementVisitCounter = () => {
|
||||||
|
let visits = parseInt(getLocalStorage(LOCAL_STORAGE_KEYS.userVisitCount), 10);
|
||||||
|
if (Number.isNaN(visits)) {
|
||||||
|
visits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLocalStorage(LOCAL_STORAGE_KEYS.userVisitCount, visits + 1);
|
||||||
|
|
||||||
|
if (visits > 2 && !getLocalStorage(LOCAL_STORAGE_KEYS.hasDisplayedNotificationModal)) {
|
||||||
|
setShowNotifyReminder(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const disableNotifyReminderPopup = () => {
|
||||||
|
setShowNotifyPopup(false);
|
||||||
|
setShowNotifyReminder(false);
|
||||||
|
setLocalStorage(LOCAL_STORAGE_KEYS.hasDisplayedNotificationModal, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
incrementVisitCounter();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Content className={`${s.root}`}>
|
<Content className={`${s.root}`}>
|
||||||
<Spin className={s.loadingSpinner} size="large" spinning={appState.appLoading} />
|
<Spin className={s.loadingSpinner} size="large" spinning={appState.appLoading} />
|
||||||
@ -95,14 +125,23 @@ export default function ContentComponent() {
|
|||||||
{externalActionButtons}
|
{externalActionButtons}
|
||||||
<FollowButton />
|
<FollowButton />
|
||||||
<NotifyReminderPopup
|
<NotifyReminderPopup
|
||||||
visible
|
visible={showNotifyReminder}
|
||||||
notificationClicked={() => {}}
|
notificationClicked={() => setShowNotifyPopup(true)}
|
||||||
notificationClosed={() => {}}
|
notificationClosed={() => disableNotifyReminderPopup()}
|
||||||
>
|
>
|
||||||
<NotifyButton />
|
<NotifyButton onClick={() => setShowNotifyPopup(true)} />
|
||||||
</NotifyReminderPopup>
|
</NotifyReminderPopup>
|
||||||
</ActionButtonRow>
|
</ActionButtonRow>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="Notify"
|
||||||
|
visible={showNotifyPopup}
|
||||||
|
afterClose={() => disableNotifyReminderPopup()}
|
||||||
|
handleCancel={() => disableNotifyReminderPopup()}
|
||||||
|
>
|
||||||
|
<BrowserNotifyModal />
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<div className={`${s.lowerRow}`}>
|
<div className={`${s.lowerRow}`}>
|
||||||
<div className={s.logoTitleSection}>
|
<div className={s.logoTitleSection}>
|
||||||
<ServerLogo src="/logo" />
|
<ServerLogo src="/logo" />
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Popover } from 'antd';
|
import { Popover } from 'antd';
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { LOCAL_STORAGE_KEYS, getLocalStorage } from '../../../utils/localStorage';
|
|
||||||
import s from './NotifyReminderPopup.module.scss';
|
import s from './NotifyReminderPopup.module.scss';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -15,11 +14,13 @@ export default function NotifyReminderPopup(props: Props) {
|
|||||||
const { children, visible, notificationClicked, notificationClosed } = props;
|
const { children, visible, notificationClicked, notificationClosed } = props;
|
||||||
const [visiblePopup, setVisiblePopup] = useState(visible);
|
const [visiblePopup, setVisiblePopup] = useState(visible);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [shouldShowPopup, setShouldShowPopup] = useState(false);
|
|
||||||
|
useEffect(() => {
|
||||||
|
setVisiblePopup(visible);
|
||||||
|
}, [visible]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMounted(true);
|
setMounted(true);
|
||||||
setShouldShowPopup(!getLocalStorage(LOCAL_STORAGE_KEYS.hasDisplayedNotificationModal));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const title = <div className={s.title}>Stay updated!</div>;
|
const title = <div className={s.title}>Stay updated!</div>;
|
||||||
@ -43,20 +44,20 @@ export default function NotifyReminderPopup(props: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<div>
|
<div onClick={popupClicked} onKeyDown={popupClicked} role="menuitem" tabIndex={0}>
|
||||||
<button type="button" className={s.closebutton} onClick={popupClosed}>
|
<button type="button" className={s.closebutton} onClick={popupClosed}>
|
||||||
<CloseOutlined />
|
<CloseOutlined />
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onClick={popupClicked} className={s.contentbutton}>
|
<div className={s.contentbutton}>
|
||||||
Click and never miss
|
Click and never miss
|
||||||
<br />
|
<br />
|
||||||
future streams!
|
future streams!
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
mounted &&
|
mounted && (
|
||||||
shouldShowPopup && (
|
|
||||||
<Popover
|
<Popover
|
||||||
placement="topLeft"
|
placement="topLeft"
|
||||||
defaultVisible={visiblePopup}
|
defaultVisible={visiblePopup}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export const LOCAL_STORAGE_KEYS = {
|
export const LOCAL_STORAGE_KEYS = {
|
||||||
username: 'username',
|
username: 'username',
|
||||||
hasDisplayedNotificationModal: 'HAS_DISPLAYED_NOTIFICATION_MODAL',
|
hasDisplayedNotificationModal: 'HAS_DISPLAYED_NOTIFICATION_MODAL',
|
||||||
|
userVisitCount: 'USER_VISIT_COUNT',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getLocalStorage(key) {
|
export function getLocalStorage(key) {
|
||||||
|
|||||||
Reference in New Issue
Block a user