mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
Add browser meta tags for favicon and title (#1746)
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
0a4ab9fb0a
commit
194183a7eb
11 changed files with 111 additions and 48 deletions
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>HedgeDoc</title>
|
||||
<link href="%PUBLIC_URL%/icons/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180">
|
||||
<link href="%PUBLIC_URL%/icons/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
|
||||
<link href="%PUBLIC_URL%/icons/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
|
||||
<link href="%PUBLIC_URL%/icons/site.webmanifest" rel="manifest">
|
||||
<link color="#b51f08" href="%PUBLIC_URL%/icons/safari-pinned-tab.svg" rel="mask-icon">
|
||||
<link href="%PUBLIC_URL%/icons/favicon.ico" rel="shortcut icon">
|
||||
<meta name="apple-mobile-web-app-title" content="HedgeDoc">
|
||||
<meta name="application-name" content="HedgeDoc">
|
||||
<meta name="msapplication-TileColor" content="#b51f08">
|
||||
<meta content="%PUBLIC_URL%/icons/browserconfig.xml" name="msapplication-config">
|
||||
<meta name="theme-color" content="#b51f08">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<meta content="HedgeDoc - Collaborative markdown notes" name="description"/>
|
||||
<base href="%PUBLIC_URL%/"/>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root" dir="auto"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -6,15 +6,12 @@
|
|||
|
||||
import React, { Fragment } from 'react'
|
||||
import { Container } from 'react-bootstrap'
|
||||
import { useDocumentTitle } from '../../hooks/common/use-document-title'
|
||||
import { MotdModal } from '../common/motd-modal/motd-modal'
|
||||
import { Footer } from './footer/footer'
|
||||
import { HeaderBar } from './navigation/header-bar/header-bar'
|
||||
import { UiNotifications } from '../notifications/ui-notifications'
|
||||
|
||||
export const LandingLayout: React.FC = ({ children }) => {
|
||||
useDocumentTitle()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<UiNotifications />
|
||||
|
|
25
src/components/layout/base-head.tsx
Normal file
25
src/components/layout/base-head.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import Head from 'next/head'
|
||||
import { useAppTitle } from '../../hooks/common/use-app-title'
|
||||
import { FavIcon } from './fav-icon'
|
||||
|
||||
/**
|
||||
* Sets basic browser meta tags.
|
||||
*/
|
||||
export const BaseHead: React.FC = () => {
|
||||
const appTitle = useAppTitle()
|
||||
|
||||
return (
|
||||
<Head>
|
||||
<title>{appTitle}</title>
|
||||
<FavIcon />
|
||||
<meta content='width=device-width, initial-scale=1' name='viewport' />
|
||||
</Head>
|
||||
)
|
||||
}
|
29
src/components/layout/fav-icon.tsx
Normal file
29
src/components/layout/fav-icon.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
/**
|
||||
* Sets meta tags for the favicon.
|
||||
*/
|
||||
export const FavIcon: React.FC = () => {
|
||||
return (
|
||||
<Fragment>
|
||||
<link href='/icons/apple-touch-icon.png' rel='apple-touch-icon' sizes='180x180' />
|
||||
<link href='/icons/favicon-32x32.png' rel='icon' sizes='32x32' type='image/png' />
|
||||
<link href='/icons/favicon-16x16.png' rel='icon' sizes='16x16' type='image/png' />
|
||||
<link href='/icons/site.webmanifest' rel='manifest' />
|
||||
<link href='/icons/favicon.ico' rel='shortcut icon' />
|
||||
<link color='#b51f08' href='/icons/safari-pinned-tab.svg' rel='mask-icon' />
|
||||
<meta name='apple-mobile-web-app-title' content='HedgeDoc' />
|
||||
<meta name='application-name' content='HedgeDoc' />
|
||||
<meta name='msapplication-TileColor' content='#b51f08' />
|
||||
<meta name='theme-color' content='#b51f08' />
|
||||
<meta content='/icons/browserconfig.xml' name='msapplication-config' />
|
||||
<meta content='HedgeDoc - Collaborative markdown notes' name='description' />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
28
src/components/layout/note-and-app-title-head.tsx
Normal file
28
src/components/layout/note-and-app-title-head.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import Head from 'next/head'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useNoteTitle } from '../../hooks/common/use-note-title'
|
||||
import { useAppTitle } from '../../hooks/common/use-app-title'
|
||||
|
||||
/**
|
||||
* Sets the note and app title for the browser window
|
||||
*/
|
||||
export const NoteAndAppTitleHead: React.FC = () => {
|
||||
const noteTitle = useNoteTitle()
|
||||
const appTitle = useAppTitle()
|
||||
|
||||
const noteAndAppTitle = useMemo(() => {
|
||||
return noteTitle + ' - ' + appTitle
|
||||
}, [appTitle, noteTitle])
|
||||
|
||||
return (
|
||||
<Head>
|
||||
<title>{noteAndAppTitle}</title>
|
||||
</Head>
|
||||
)
|
||||
}
|
|
@ -4,13 +4,16 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import { useMemo } from 'react'
|
||||
import { useApplicationState } from './use-application-state'
|
||||
|
||||
export const useDocumentTitle = (title?: string): void => {
|
||||
/**
|
||||
* Returns the app title with branding if set.
|
||||
*/
|
||||
export const useAppTitle = (): string => {
|
||||
const brandingName = useApplicationState((state) => state.config.branding.name)
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${title ? title + ' - ' : ''}HedgeDoc ${brandingName ? ` @ ${brandingName}` : ''}`
|
||||
}, [brandingName, title])
|
||||
return useMemo(() => {
|
||||
return 'HedgeDoc' + (brandingName ? ` @ ${brandingName}` : '')
|
||||
}, [brandingName])
|
||||
}
|
|
@ -6,13 +6,15 @@
|
|||
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useApplicationState } from './use-application-state'
|
||||
import { useDocumentTitle } from './use-document-title'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
export const useDocumentTitleWithNoteTitle = (): void => {
|
||||
/**
|
||||
* Returns the title of the note or a placeholder text.
|
||||
*/
|
||||
export const useNoteTitle = (): string => {
|
||||
const { t } = useTranslation()
|
||||
const untitledNote = useMemo(() => t('editor.untitledNote'), [t])
|
||||
const noteTitle = useApplicationState((state) => state.noteDetails.noteTitle)
|
||||
|
||||
useDocumentTitle(noteTitle === '' ? untitledNote : noteTitle)
|
||||
return useMemo(() => (noteTitle === '' ? untitledNote : noteTitle), [noteTitle, untitledNote])
|
||||
}
|
|
@ -11,6 +11,7 @@ import { ApplicationLoader } from '../components/application-loader/application-
|
|||
import '../../global-styles/dark.scss'
|
||||
import '../../global-styles/index.scss'
|
||||
import type { NextPage } from 'next'
|
||||
import { BaseHead } from '../components/layout/base-head'
|
||||
|
||||
/**
|
||||
* The actual hedgedoc next js app.
|
||||
|
@ -19,6 +20,7 @@ import type { NextPage } from 'next'
|
|||
const HedgeDocApp: NextPage<AppProps> = ({ Component, pageProps }: AppProps) => {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<BaseHead />
|
||||
<ApplicationLoader>
|
||||
<ErrorBoundary>
|
||||
<Component {...pageProps} />
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import React, { Suspense, useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
|
||||
import { useDocumentTitleWithNoteTitle } from '../../hooks/common/use-document-title-with-note-title'
|
||||
import { setCheckboxInMarkdownContent, updateNoteTitleByFirstHeading } from '../../redux/note-details/methods'
|
||||
import { MotdModal } from '../../components/common/motd-modal/motd-modal'
|
||||
import { ShowIf } from '../../components/common/show-if/show-if'
|
||||
|
@ -32,6 +31,7 @@ import { NoteType } from '../../redux/note-details/types/note-details'
|
|||
import type { NextPage } from 'next'
|
||||
import { isClientSideRendering } from '../../utils/is-client-side-rendering'
|
||||
import { LoadingScreen } from '../../components/application-loader/loading-screen'
|
||||
import { NoteAndAppTitleHead } from '../../components/layout/note-and-app-title-head'
|
||||
|
||||
const EditorPane = React.lazy(() => import('../../components/editor-page/editor-pane/editor-pane'))
|
||||
|
||||
|
@ -88,7 +88,6 @@ export const EditorPage: NextPage = () => {
|
|||
|
||||
useViewModeShortcuts()
|
||||
useApplyDarkMode()
|
||||
useDocumentTitleWithNoteTitle()
|
||||
useEditorModeFromUrl()
|
||||
|
||||
const [error, loading] = useLoadNoteFromServer()
|
||||
|
@ -137,6 +136,7 @@ export const EditorPage: NextPage = () => {
|
|||
|
||||
return (
|
||||
<EditorToRendererCommunicatorContextProvider>
|
||||
<NoteAndAppTitleHead />
|
||||
<UiNotifications />
|
||||
<MotdModal />
|
||||
<div className={'d-flex flex-column vh-100'}>
|
||||
|
|
|
@ -4,23 +4,25 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import React, { Fragment } from 'react'
|
||||
import { useLoadNoteFromServer } from '../../components/editor-page/hooks/useLoadNoteFromServer'
|
||||
import { ShowIf } from '../../components/common/show-if/show-if'
|
||||
import { EditorToRendererCommunicatorContextProvider } from '../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||
import { SlideShowPageContent } from '../../components/slide-show-page/slide-show-page-content'
|
||||
import { useDocumentTitleWithNoteTitle } from '../../hooks/common/use-document-title-with-note-title'
|
||||
import { NoteAndAppTitleHead } from '../../components/layout/note-and-app-title-head'
|
||||
|
||||
export const SlideShowPage: React.FC = () => {
|
||||
const [error, loading] = useLoadNoteFromServer()
|
||||
useDocumentTitleWithNoteTitle()
|
||||
|
||||
return (
|
||||
<EditorToRendererCommunicatorContextProvider>
|
||||
<ShowIf condition={!error && !loading}>
|
||||
<SlideShowPageContent />
|
||||
</ShowIf>
|
||||
</EditorToRendererCommunicatorContextProvider>
|
||||
<Fragment>
|
||||
<NoteAndAppTitleHead />
|
||||
<EditorToRendererCommunicatorContextProvider>
|
||||
<ShowIf condition={!error && !loading}>
|
||||
<SlideShowPageContent />
|
||||
</ShowIf>
|
||||
</EditorToRendererCommunicatorContextProvider>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import React from 'react'
|
||||
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
|
||||
import { useDocumentTitleWithNoteTitle } from '../../hooks/common/use-document-title-with-note-title'
|
||||
import { MotdModal } from '../../components/common/motd-modal/motd-modal'
|
||||
import { ShowIf } from '../../components/common/show-if/show-if'
|
||||
import { AppBar, AppBarMode } from '../../components/editor-page/app-bar/app-bar'
|
||||
|
@ -16,16 +15,17 @@ import { LoadingNoteAlert } from '../../components/document-read-only-page/Loadi
|
|||
import { EditorToRendererCommunicatorContextProvider } from '../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||
import { UiNotifications } from '../../components/notifications/ui-notifications'
|
||||
import { DocumentReadOnlyPageContent } from '../../components/document-read-only-page/document-read-only-page-content'
|
||||
import { NoteAndAppTitleHead } from '../../components/layout/note-and-app-title-head'
|
||||
|
||||
/**
|
||||
* Renders a page that contains only the rendered document without an editor or realtime updates.
|
||||
*/
|
||||
export const DocumentReadOnlyPage: React.FC = () => {
|
||||
useApplyDarkMode()
|
||||
useDocumentTitleWithNoteTitle()
|
||||
const [error, loading] = useLoadNoteFromServer()
|
||||
return (
|
||||
<EditorToRendererCommunicatorContextProvider>
|
||||
<NoteAndAppTitleHead />
|
||||
<UiNotifications />
|
||||
<MotdModal />
|
||||
<div className={'d-flex flex-column mvh-100 bg-light'}>
|
||||
|
|
Loading…
Reference in a new issue