Add backgrounded stream+messages title notifier. Closes #2208
This commit is contained in:
73
web/components/TitleNotifier/TitleNotifier.tsx
Normal file
73
web/components/TitleNotifier/TitleNotifier.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* This component is responsible for updating the title of the page when
|
||||||
|
* different state changes occur.
|
||||||
|
* If the stream live state changes, or chat messages come in while the
|
||||||
|
* page is backgrounded, this component will update the title to reflect it. *
|
||||||
|
* @component
|
||||||
|
*/
|
||||||
|
import { FC, useEffect } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { serverStatusState, chatMessagesAtom } from '../stores/ClientConfigStore';
|
||||||
|
|
||||||
|
export const TitleNotifier: FC = () => {
|
||||||
|
const chatMessages = useRecoilValue(chatMessagesAtom);
|
||||||
|
const serverStatus = useRecoilValue(serverStatusState);
|
||||||
|
|
||||||
|
let backgrounded = false;
|
||||||
|
let defaultTitle = '';
|
||||||
|
|
||||||
|
const onBlur = () => {
|
||||||
|
console.log('onBlur');
|
||||||
|
backgrounded = true;
|
||||||
|
defaultTitle = document.title;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
console.log('onFocus');
|
||||||
|
backgrounded = false;
|
||||||
|
window.document.title = defaultTitle;
|
||||||
|
};
|
||||||
|
|
||||||
|
const listenForEvents = () => {
|
||||||
|
// Listen for events that should update the title
|
||||||
|
console.log('listenForEvents');
|
||||||
|
window.addEventListener('blur', onBlur);
|
||||||
|
window.addEventListener('focus', onFocus);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
defaultTitle = window.document.title;
|
||||||
|
listenForEvents();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('focus', onFocus);
|
||||||
|
window.removeEventListener('blur', onBlur);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { online } = serverStatus;
|
||||||
|
|
||||||
|
if (!backgrounded || !online) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.document.title = `💬 :: ${defaultTitle}`;
|
||||||
|
}, [chatMessages]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!backgrounded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { online } = serverStatus;
|
||||||
|
|
||||||
|
if (online) {
|
||||||
|
window.document.title = ` 🟢 :: ${defaultTitle}`;
|
||||||
|
} else if (!online) {
|
||||||
|
window.document.title = ` 🔴 :: ${defaultTitle}`;
|
||||||
|
}
|
||||||
|
}, [serverStatusState]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
@@ -18,6 +18,7 @@ import { FatalErrorStateModal } from '../modals/FatalErrorStateModal/FatalErrorS
|
|||||||
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
||||||
import { ServerRenderedMetadata } from '../ServerRendered/ServerRenderedMetadata';
|
import { ServerRenderedMetadata } from '../ServerRendered/ServerRenderedMetadata';
|
||||||
import { ServerRenderedHydration } from '../ServerRendered/ServerRenderedHydration';
|
import { ServerRenderedHydration } from '../ServerRendered/ServerRenderedHydration';
|
||||||
|
import { TitleNotifier } from '../TitleNotifier/TitleNotifier';
|
||||||
|
|
||||||
export const Main: FC = () => {
|
export const Main: FC = () => {
|
||||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
@@ -77,6 +78,7 @@ export const Main: FC = () => {
|
|||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<ClientConfigStore />
|
<ClientConfigStore />
|
||||||
|
<TitleNotifier />
|
||||||
<Layout ref={layoutRef} style={{ minHeight: '100vh' }}>
|
<Layout ref={layoutRef} style={{ minHeight: '100vh' }}>
|
||||||
<Header name={title || name} chatAvailable={isChatAvailable} chatDisabled={chatDisabled} />
|
<Header name={title || name} chatAvailable={isChatAvailable} chatDisabled={chatDisabled} />
|
||||||
<Content />
|
<Content />
|
||||||
|
|||||||
@@ -329,6 +329,8 @@ export const ClientConfigStore: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChatNotification = () => {};
|
||||||
|
|
||||||
// Read the config and status on initial load from a JSON string that lives
|
// Read the config and status on initial load from a JSON string that lives
|
||||||
// in window. This is placed there server-side and allows for fast initial
|
// in window. This is placed there server-side and allows for fast initial
|
||||||
// load times because we don't have to wait for the API calls to complete.
|
// load times because we don't have to wait for the API calls to complete.
|
||||||
@@ -339,7 +341,7 @@ export const ClientConfigStore: FC = () => {
|
|||||||
setClientConfig(config);
|
setClientConfig(config);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.error('Error parsing config hydration', e);
|
console.error('Error parsing config hydration', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -348,7 +350,7 @@ export const ClientConfigStore: FC = () => {
|
|||||||
setServerStatus(status);
|
setServerStatus(status);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.error('error parsing status hydration', e);
|
console.error('error parsing status hydration', e);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -364,6 +366,11 @@ export const ClientConfigStore: FC = () => {
|
|||||||
}
|
}
|
||||||
}, [hasLoadedConfig, accessToken]);
|
}, [hasLoadedConfig, accessToken]);
|
||||||
|
|
||||||
|
// Notify about chat activity when backgrounded.
|
||||||
|
useEffect(() => {
|
||||||
|
handleChatNotification();
|
||||||
|
}, [chatMessages]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateClientConfig();
|
updateClientConfig();
|
||||||
handleUserRegistration();
|
handleUserRegistration();
|
||||||
|
|||||||
Reference in New Issue
Block a user