Wire up notify popup to hide/show at correct times. Closes #1911

This commit is contained in:
Gabe Kangas
2022-06-26 23:01:52 -07:00
parent 8fc922588b
commit 577ce5718d
4 changed files with 65 additions and 34 deletions

View File

@ -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>
</>
); );
} }

View File

@ -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" />

View File

@ -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}

View File

@ -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) {