fix(web): set page title on chat embed pages (#4820)
Set a translated page title on the readonly and readwrite chat embed pages so popout/embedded chat windows display a meaningful title based on the configured stream name, addressing #4794. Uses next-export-i18n with a new chatEmbedTitle key for proper localization. Also fixes the readonly embed error boundary componentName from ReadWriteChatEmbed to ReadOnlyChatEmbed.
This commit is contained in:
@@ -221,7 +221,8 @@
|
|||||||
"offlineBasic": "This stream is offline. Check back soon!",
|
"offlineBasic": "This stream is offline. Check back soon!",
|
||||||
"offlineFediverseOnly": "This stream is offline. <span class='follow-link'>Follow</span> {{fediverseAccount}} on the Fediverse to see the next time {{streamer}} goes live.",
|
"offlineFediverseOnly": "This stream is offline. <span class='follow-link'>Follow</span> {{fediverseAccount}} on the Fediverse to see the next time {{streamer}} goes live.",
|
||||||
"offlineNotifyAndFediverse": "This stream is offline. You can <span class='notify-link'>be notified</span> the next time {{streamer}} goes live or <span class='follow-link'>follow</span> {{fediverseAccount}} on the Fediverse.",
|
"offlineNotifyAndFediverse": "This stream is offline. You can <span class='notify-link'>be notified</span> the next time {{streamer}} goes live or <span class='follow-link'>follow</span> {{fediverseAccount}} on the Fediverse.",
|
||||||
"offlineNotifyOnly": "This stream is offline. <span class='notify-link'>Be notified</span> the next time {{streamer}} goes live."
|
"offlineNotifyOnly": "This stream is offline. <span class='notify-link'>Be notified</span> the next time {{streamer}} goes live.",
|
||||||
|
"chatEmbedTitle": "{{name}} Chat"
|
||||||
},
|
},
|
||||||
"Testing": {
|
"Testing": {
|
||||||
"itemCount": "You have {{count}} items",
|
"itemCount": "You have {{count}} items",
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import { useTranslation } from 'next-export-i18n';
|
||||||
import { ErrorBoundary } from 'react-error-boundary';
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
import { ChatMessage } from '../../../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../../../interfaces/chat-message.model';
|
||||||
import { ChatContainer } from '../../../../components/chat/ChatContainer/ChatContainer';
|
import { ChatContainer } from '../../../../components/chat/ChatContainer/ChatContainer';
|
||||||
@@ -6,22 +8,34 @@ import {
|
|||||||
ClientConfigStore,
|
ClientConfigStore,
|
||||||
currentUserAtom,
|
currentUserAtom,
|
||||||
visibleChatMessagesSelector,
|
visibleChatMessagesSelector,
|
||||||
|
clientConfigStateAtom,
|
||||||
isChatAvailableSelector,
|
isChatAvailableSelector,
|
||||||
} from '../../../../components/stores/ClientConfigStore';
|
} from '../../../../components/stores/ClientConfigStore';
|
||||||
|
import { ClientConfig } from '../../../../interfaces/client-config.model';
|
||||||
import { Theme } from '../../../../components/theme/Theme';
|
import { Theme } from '../../../../components/theme/Theme';
|
||||||
import { ComponentError } from '../../../../components/ui/ComponentError/ComponentError';
|
import { ComponentError } from '../../../../components/ui/ComponentError/ComponentError';
|
||||||
|
import { Localization } from '../../../../types/localization';
|
||||||
|
|
||||||
export default function ReadOnlyChatEmbed() {
|
export default function ReadOnlyChatEmbed() {
|
||||||
const currentUser = useRecoilValue(currentUserAtom);
|
const currentUser = useRecoilValue(currentUserAtom);
|
||||||
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
|
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
|
||||||
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
const isChatAvailable = useRecoilValue(isChatAvailableSelector);
|
const isChatAvailable = useRecoilValue(isChatAvailableSelector);
|
||||||
|
|
||||||
|
const { name } = clientConfig;
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const pageTitle = name ? t(Localization.Frontend.chatEmbedTitle, { name }) : 'Chat';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Head>
|
||||||
|
<title>{pageTitle}</title>
|
||||||
|
</Head>
|
||||||
<ErrorBoundary
|
<ErrorBoundary
|
||||||
// eslint-disable-next-line react/no-unstable-nested-components
|
// eslint-disable-next-line react/no-unstable-nested-components
|
||||||
fallbackRender={({ error }) => (
|
fallbackRender={({ error }) => (
|
||||||
<ComponentError componentName="ReadWriteChatEmbed" message={error.message} />
|
<ComponentError componentName="ReadOnlyChatEmbed" message={error.message} />
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ClientConfigStore />
|
<ClientConfigStore />
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/* eslint-disable react/no-unknown-property */
|
/* eslint-disable react/no-unknown-property */
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { ErrorBoundary } from 'react-error-boundary';
|
import Head from 'next/head';
|
||||||
import { useTranslation } from 'next-export-i18n';
|
import { useTranslation } from 'next-export-i18n';
|
||||||
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
import { ChatMessage } from '../../../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../../../interfaces/chat-message.model';
|
||||||
import { ChatContainer } from '../../../../components/chat/ChatContainer/ChatContainer';
|
import { ChatContainer } from '../../../../components/chat/ChatContainer/ChatContainer';
|
||||||
import {
|
import {
|
||||||
@@ -50,6 +51,8 @@ export default function ReadWriteChatEmbed() {
|
|||||||
|
|
||||||
const headerText = online ? streamTitle || name : name;
|
const headerText = online ? streamTitle || name : name;
|
||||||
|
|
||||||
|
const pageTitle = name ? t(Localization.Frontend.chatEmbedTitle, { name }) : 'Chat';
|
||||||
|
|
||||||
// This is a hack to force a specific body background color for just this page.
|
// This is a hack to force a specific body background color for just this page.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.classList.add('body-background');
|
document.body.classList.add('body-background');
|
||||||
@@ -57,6 +60,9 @@ export default function ReadWriteChatEmbed() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Head>
|
||||||
|
<title>{pageTitle}</title>
|
||||||
|
</Head>
|
||||||
<style jsx global>
|
<style jsx global>
|
||||||
{`
|
{`
|
||||||
.body-background {
|
.body-background {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export const Localization = {
|
|||||||
*/
|
*/
|
||||||
Frontend: {
|
Frontend: {
|
||||||
// Chat interface
|
// Chat interface
|
||||||
|
chatEmbedTitle: 'Frontend.chatEmbedTitle',
|
||||||
chatOffline: 'Chat is offline',
|
chatOffline: 'Chat is offline',
|
||||||
chatDisabled: 'Chat is disabled',
|
chatDisabled: 'Chat is disabled',
|
||||||
chatWillBeAvailable: 'Chat will be available when the stream is live',
|
chatWillBeAvailable: 'Chat will be available when the stream is live',
|
||||||
|
|||||||
Reference in New Issue
Block a user