mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-24 18:56:32 -05:00
feat(frontend): show indicator in document title for background changes
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
336e621bc4
commit
9497726a7c
5 changed files with 142 additions and 2 deletions
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import * as UseIsDocumentVisibleModule from '../../../../hooks/common/use-is-document-visible'
|
||||
import * as UseNoteMarkdownContent from '../../../../hooks/common/use-note-markdown-content'
|
||||
import { useHasMarkdownContentBeenChangedInBackground } from './use-has-markdown-content-been-changed-in-background'
|
||||
import { render } from '@testing-library/react'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
jest.mock('../../../../hooks/common/use-is-document-visible')
|
||||
jest.mock('../../../../hooks/common/use-note-markdown-content')
|
||||
|
||||
describe('use has markdown content been changed in background', () => {
|
||||
const TestComponent: React.FC = () => {
|
||||
const visible = useHasMarkdownContentBeenChangedInBackground()
|
||||
return <Fragment>{String(visible)}</Fragment>
|
||||
}
|
||||
|
||||
let documentVisible = true
|
||||
let noteContent = 'content'
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(UseIsDocumentVisibleModule, 'useIsDocumentVisible').mockImplementation(() => documentVisible)
|
||||
jest.spyOn(UseNoteMarkdownContent, 'useNoteMarkdownContent').mockImplementation(() => noteContent)
|
||||
})
|
||||
|
||||
it('returns the correct value', () => {
|
||||
documentVisible = true
|
||||
noteContent = 'content1'
|
||||
const view = render(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('false')
|
||||
expect(view.container.textContent).toBe('false') //intentionally no change
|
||||
|
||||
noteContent = 'content2'
|
||||
view.rerender(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('false')
|
||||
|
||||
documentVisible = false
|
||||
view.rerender(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('false')
|
||||
|
||||
noteContent = 'content3'
|
||||
view.rerender(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('true')
|
||||
|
||||
noteContent = 'content2'
|
||||
view.rerender(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('true')
|
||||
|
||||
documentVisible = true
|
||||
view.rerender(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('false')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useIsDocumentVisible } from '../../../../hooks/common/use-is-document-visible'
|
||||
import { useNoteMarkdownContent } from '../../../../hooks/common/use-note-markdown-content'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Determines if the markdown content has been changed while the browser tab hasn't been active.
|
||||
*/
|
||||
export const useHasMarkdownContentBeenChangedInBackground = (): boolean => {
|
||||
const [backgroundChangesHappened, setBackgroundChangesHappened] = useState(false)
|
||||
const documentVisible = useIsDocumentVisible()
|
||||
const currentContent = useNoteMarkdownContent()
|
||||
const lastContent = useRef<string>('')
|
||||
|
||||
useEffect(() => {
|
||||
if (lastContent.current === currentContent || documentVisible) {
|
||||
lastContent.current = currentContent
|
||||
setBackgroundChangesHappened(false)
|
||||
return
|
||||
}
|
||||
lastContent.current = currentContent
|
||||
setBackgroundChangesHappened(true)
|
||||
}, [currentContent, documentVisible])
|
||||
|
||||
return backgroundChangesHappened
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
import { useAppTitle } from '../../../hooks/common/use-app-title'
|
||||
import { useNoteTitle } from '../../../hooks/common/use-note-title'
|
||||
import { useHasMarkdownContentBeenChangedInBackground } from './hooks/use-has-markdown-content-been-changed-in-background'
|
||||
import Head from 'next/head'
|
||||
import React, { useMemo } from 'react'
|
||||
|
||||
|
@ -14,10 +15,11 @@ import React, { useMemo } from 'react'
|
|||
export const NoteAndAppTitleHead: React.FC = () => {
|
||||
const noteTitle = useNoteTitle()
|
||||
const appTitle = useAppTitle()
|
||||
const showDot = useHasMarkdownContentBeenChangedInBackground()
|
||||
|
||||
const noteAndAppTitle = useMemo(() => {
|
||||
return noteTitle + ' - ' + appTitle
|
||||
}, [appTitle, noteTitle])
|
||||
return (showDot ? '(•) ' : '') + noteTitle + ' - ' + appTitle
|
||||
}, [appTitle, noteTitle, showDot])
|
||||
|
||||
return (
|
||||
<Head>
|
||||
|
|
24
frontend/src/hooks/common/use-is-document-visible.spec.tsx
Normal file
24
frontend/src/hooks/common/use-is-document-visible.spec.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useIsDocumentVisible } from './use-is-document-visible'
|
||||
import { fireEvent, render } from '@testing-library/react'
|
||||
import React, { Fragment } from 'react'
|
||||
|
||||
describe('use is document visible', () => {
|
||||
const TestComponent: React.FC = () => {
|
||||
const visible = useIsDocumentVisible()
|
||||
return <Fragment>{String(visible)}</Fragment>
|
||||
}
|
||||
|
||||
it('returns the correct value', () => {
|
||||
const view = render(<TestComponent />)
|
||||
expect(view.container.textContent).toBe('true')
|
||||
fireEvent(window, new Event('blur'))
|
||||
expect(view.container.textContent).toBe('false')
|
||||
fireEvent(window, new Event('focus'))
|
||||
expect(view.container.textContent).toBe('true')
|
||||
})
|
||||
})
|
28
frontend/src/hooks/common/use-is-document-visible.ts
Normal file
28
frontend/src/hooks/common/use-is-document-visible.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Uses the browsers visiblity API to determine if the tab is active or now.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
*/
|
||||
export const useIsDocumentVisible = (): boolean => {
|
||||
const [documentVisible, setDocumentVisible] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
const onFocus = () => setDocumentVisible(true)
|
||||
const onBlur = () => setDocumentVisible(false)
|
||||
window.addEventListener('focus', onFocus)
|
||||
window.addEventListener('blur', onBlur)
|
||||
return () => {
|
||||
document.removeEventListener('focus', onFocus)
|
||||
document.removeEventListener('blur', onBlur)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return documentVisible
|
||||
}
|
Loading…
Reference in a new issue