mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2026-08-07 07:14:49 +00:00
fix(renderer): printing properly from iframe and host
React hooks may not be called inside other react hooks due to the "rule of hooks". Furthermore, with the recent iframe-communicator changes, the hook for printing from outside the iframe failed - no matter whether on normal documents or slides. This change therefore uses two distinct hooks that represent the event listeners for each side, instead of a shared one. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
committed by
Philip Molares
parent
9c00a7021a
commit
b6825bc703
@@ -18,7 +18,7 @@ import { PrintWarning } from './print-warning/print-warning'
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import './print.scss'
|
||||
import { usePrintKeyboardShortcut } from './hooks/use-print-keyboard-shortcut'
|
||||
import { usePrintIframeKeyboardShortcut } from './hooks/use-print-keyboard-shortcut'
|
||||
import { NoteType } from '@hedgedoc/commons'
|
||||
import { useApplicationState } from '../../hooks/common/use-application-state'
|
||||
import { buildCursorLineScrollState } from './synced-scroll/cursor-line-scroll-state'
|
||||
@@ -33,7 +33,7 @@ export enum ScrollSource {
|
||||
*/
|
||||
export const EditorPageContent: React.FC = () => {
|
||||
useTranslation()
|
||||
usePrintKeyboardShortcut()
|
||||
usePrintIframeKeyboardShortcut()
|
||||
|
||||
const scrollSource = useRef<ScrollSource>(ScrollSource.EDITOR)
|
||||
const [editorScrollState, onMarkdownRendererScroll] = useScrollState(scrollSource, ScrollSource.EDITOR)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { fireEvent, renderHook } from '@testing-library/react'
|
||||
import { usePrintIframeKeyboardShortcut, usePrintSelfKeyboardShortcut } from './use-print-keyboard-shortcut'
|
||||
|
||||
const printIframe = jest.fn()
|
||||
const printSelf = jest.fn()
|
||||
|
||||
jest.mock('../utils/print-iframe', () => ({
|
||||
usePrintIframe: () => printIframe,
|
||||
usePrintSelf: () => printSelf
|
||||
}))
|
||||
|
||||
describe('usePrintKeyboardShortcut', () => {
|
||||
beforeEach(() => {
|
||||
printIframe.mockClear()
|
||||
printSelf.mockClear()
|
||||
})
|
||||
|
||||
it('prints the renderer iframe when the print shortcut is pressed', () => {
|
||||
renderHook(() => usePrintIframeKeyboardShortcut())
|
||||
|
||||
fireEvent.keyDown(window, { ctrlKey: true, key: 'p' })
|
||||
|
||||
expect(printIframe).toHaveBeenCalledTimes(1)
|
||||
expect(printSelf).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('prints the current window when the print shortcut is pressed in the renderer iframe', () => {
|
||||
renderHook(() => usePrintSelfKeyboardShortcut())
|
||||
|
||||
fireEvent.keyDown(window, { ctrlKey: true, key: 'p' })
|
||||
|
||||
expect(printSelf).toHaveBeenCalledTimes(1)
|
||||
expect(printIframe).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -4,26 +4,33 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { usePrintIframe, usePrintSelf } from '../utils/print-iframe'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
|
||||
/**
|
||||
* Hook to listen for the print keyboard shortcut and print the content of the renderer iframe.
|
||||
*/
|
||||
export const usePrintKeyboardShortcut = (): void => {
|
||||
const isIframe = useMemo(() => window.top !== window.self, [])
|
||||
export const usePrintIframeKeyboardShortcut = (): void => {
|
||||
const printIframe = usePrintIframe()
|
||||
usePrintShortcut(printIframe)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to listen for the print keyboard shortcut and print the renderer content from within the iframe.
|
||||
*/
|
||||
export const usePrintSelfKeyboardShortcut = (): void => {
|
||||
const printSelf = usePrintSelf()
|
||||
usePrintShortcut(printSelf)
|
||||
}
|
||||
|
||||
const usePrintShortcut = (print: () => void): void => {
|
||||
const handlePrint = useCallback(
|
||||
(event: KeyboardEvent): void => {
|
||||
if (event.key === 'p' && (event.ctrlKey || event.metaKey)) {
|
||||
event.preventDefault()
|
||||
if (isIframe) {
|
||||
usePrintSelf()()
|
||||
} else {
|
||||
usePrintIframe()()
|
||||
}
|
||||
print()
|
||||
}
|
||||
},
|
||||
[isIframe]
|
||||
[print]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { RevealOptions } from 'reveal.js'
|
||||
import { EventEmitter2 } from 'eventemitter2'
|
||||
import React, { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { setPrintMode } from '../../redux/print-mode/methods'
|
||||
import { usePrintKeyboardShortcut } from '../editor-page/hooks/use-print-keyboard-shortcut'
|
||||
import { usePrintSelfKeyboardShortcut } from '../editor-page/hooks/use-print-keyboard-shortcut'
|
||||
|
||||
/**
|
||||
* Wraps the markdown rendering in an iframe.
|
||||
@@ -127,7 +127,7 @@ export const RenderPageContent: React.FC = () => {
|
||||
)
|
||||
)
|
||||
|
||||
usePrintKeyboardShortcut()
|
||||
usePrintSelfKeyboardShortcut()
|
||||
|
||||
const onMakeScrollSource = useCallback(() => {
|
||||
sendScrolling.current = true
|
||||
|
||||
@@ -11,9 +11,7 @@ const printModeSlice = createSlice({
|
||||
name: 'printMode',
|
||||
initialState,
|
||||
reducers: {
|
||||
setPrintMode: (state, action: PayloadAction<boolean>) => {
|
||||
state = action.payload
|
||||
}
|
||||
setPrintMode: (_state, action: PayloadAction<boolean>) => action.payload
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user