From 596bcd8d8b0aff25f504050053c912dba94d929c Mon Sep 17 00:00:00 2001 From: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com> Date: Wed, 31 Jul 2024 06:10:58 -0700 Subject: [PATCH] Desktop: Accessibility: Improve focus handling for plugin and prompt dialogs (#10801) --- .eslintignore | 3 + .gitignore | 3 + packages/app-desktop/gui/Dialog.tsx | 29 +++++--- .../gui/EditFolderDialog/Dialog.tsx | 2 +- .../gui/MasterPasswordDialog/Dialog.tsx | 2 +- .../gui/NoteContentPropertiesDialog.tsx | 34 +++++----- .../app-desktop/gui/NotePropertiesDialog.tsx | 18 +++-- packages/app-desktop/gui/PromptDialog.tsx | 45 ++++--------- packages/app-desktop/gui/Root.tsx | 2 +- .../ShareFolderDialog/ShareFolderDialog.tsx | 2 +- packages/app-desktop/gui/ShareNoteDialog.tsx | 2 +- .../app-desktop/gui/SyncWizard/Dialog.tsx | 2 +- .../gui/styles/dialog-modal-layer.scss | 3 +- packages/app-desktop/gui/styles/index.scss | 4 +- .../app-desktop/gui/styles/prompt-dialog.scss | 7 ++ .../gui/styles/user-webview-dialog.scss | 25 +++++++ .../integration-tests/goToAnything.spec.ts | 52 +++++++++++++++ .../integration-tests/models/GoToAnything.ts | 36 ++++++++++ .../integration-tests/models/MainScreen.ts | 3 + packages/app-desktop/plugins/GotoAnything.tsx | 55 +++++----------- .../services/plugins/UserWebviewDialog.tsx | 66 ++++++------------- 21 files changed, 230 insertions(+), 165 deletions(-) create mode 100644 packages/app-desktop/gui/styles/prompt-dialog.scss create mode 100644 packages/app-desktop/gui/styles/user-webview-dialog.scss create mode 100644 packages/app-desktop/integration-tests/goToAnything.spec.ts create mode 100644 packages/app-desktop/integration-tests/models/GoToAnything.ts diff --git a/.eslintignore b/.eslintignore index 4a8bd854c..10672a2d3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -451,7 +451,9 @@ packages/app-desktop/gui/utils/convertToScreenCoordinates.js packages/app-desktop/gui/utils/dragAndDrop.js packages/app-desktop/gui/utils/loadScript.js packages/app-desktop/gulpfile.js +packages/app-desktop/integration-tests/goToAnything.spec.js packages/app-desktop/integration-tests/main.spec.js +packages/app-desktop/integration-tests/models/GoToAnything.js packages/app-desktop/integration-tests/models/MainScreen.js packages/app-desktop/integration-tests/models/NoteEditorScreen.js packages/app-desktop/integration-tests/models/SettingsScreen.js @@ -469,6 +471,7 @@ packages/app-desktop/integration-tests/util/test.js packages/app-desktop/integration-tests/util/waitForNextOpenPath.js packages/app-desktop/playwright.config.js packages/app-desktop/plugins/GotoAnything.js +packages/app-desktop/services/autoUpdater/AutoUpdaterService.js packages/app-desktop/services/bridge.js packages/app-desktop/services/commands/stateToWhenClauseContext.js packages/app-desktop/services/commands/types.js diff --git a/.gitignore b/.gitignore index a3e3c787d..710590954 100644 --- a/.gitignore +++ b/.gitignore @@ -430,7 +430,9 @@ packages/app-desktop/gui/utils/convertToScreenCoordinates.js packages/app-desktop/gui/utils/dragAndDrop.js packages/app-desktop/gui/utils/loadScript.js packages/app-desktop/gulpfile.js +packages/app-desktop/integration-tests/goToAnything.spec.js packages/app-desktop/integration-tests/main.spec.js +packages/app-desktop/integration-tests/models/GoToAnything.js packages/app-desktop/integration-tests/models/MainScreen.js packages/app-desktop/integration-tests/models/NoteEditorScreen.js packages/app-desktop/integration-tests/models/SettingsScreen.js @@ -448,6 +450,7 @@ packages/app-desktop/integration-tests/util/test.js packages/app-desktop/integration-tests/util/waitForNextOpenPath.js packages/app-desktop/playwright.config.js packages/app-desktop/plugins/GotoAnything.js +packages/app-desktop/services/autoUpdater/AutoUpdaterService.js packages/app-desktop/services/bridge.js packages/app-desktop/services/commands/stateToWhenClauseContext.js packages/app-desktop/services/commands/types.js diff --git a/packages/app-desktop/gui/Dialog.tsx b/packages/app-desktop/gui/Dialog.tsx index e8cb3bda5..299210b97 100644 --- a/packages/app-desktop/gui/Dialog.tsx +++ b/packages/app-desktop/gui/Dialog.tsx @@ -1,10 +1,11 @@ import * as React from 'react'; -import { ReactElement, ReactEventHandler, useCallback, useEffect, useRef, useState } from 'react'; +import { MouseEventHandler, ReactEventHandler, ReactNode, useCallback, useEffect, useRef, useState } from 'react'; interface Props { - renderContent: ()=> ReactElement; className?: string; - onClose?: ()=> void; + onCancel?: ()=> void; + contentStyle?: React.CSSProperties; + children: ReactNode; } export default function Dialog(props: Props) { @@ -18,12 +19,12 @@ export default function Dialog(props: Props) { dialogElement.showModal(); }, [dialogElement]); - const onCloseRef = useRef(props.onClose); - onCloseRef.current = props.onClose; + const onCancelRef = useRef(props.onCancel); + onCancelRef.current = props.onCancel; const onCancel: ReactEventHandler = useCallback((event) => { - const canCancel = !!onCloseRef.current; - if (canCancel) { + const canCancel = !!onCancelRef.current; + if (!canCancel) { // Prevents [Escape] from closing the dialog. In many places, this is handled // elsewhere. // See https://stackoverflow.com/a/61021326 @@ -31,15 +32,23 @@ export default function Dialog(props: Props) { } }, []); + const onContainerClick: MouseEventHandler = useCallback((event) => { + const onCancel = onCancelRef.current; + if (event.target === dialogElement && onCancel) { + onCancel(); + } + }, [dialogElement]); + return ( -
- {props.renderContent()} +
+ {props.children}
); diff --git a/packages/app-desktop/gui/EditFolderDialog/Dialog.tsx b/packages/app-desktop/gui/EditFolderDialog/Dialog.tsx index eb57f53b4..467c2dc64 100644 --- a/packages/app-desktop/gui/EditFolderDialog/Dialog.tsx +++ b/packages/app-desktop/gui/EditFolderDialog/Dialog.tsx @@ -179,6 +179,6 @@ export default function(props: Props) { } return ( - + {renderDialogWrapper()} ); } diff --git a/packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx b/packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx index e3fc31bcc..e23f9bf42 100644 --- a/packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx +++ b/packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx @@ -240,6 +240,6 @@ export default function(props: Props) { } return ( - + {renderDialogWrapper()} ); } diff --git a/packages/app-desktop/gui/NoteContentPropertiesDialog.tsx b/packages/app-desktop/gui/NoteContentPropertiesDialog.tsx index 624ceb85c..db2c9b0fc 100644 --- a/packages/app-desktop/gui/NoteContentPropertiesDialog.tsx +++ b/packages/app-desktop/gui/NoteContentPropertiesDialog.tsx @@ -5,13 +5,13 @@ import DialogButtonRow from './DialogButtonRow'; const { themeStyle } = require('@joplin/lib/theme'); const Countable = require('@joplin/lib/countable/Countable'); import markupLanguageUtils from '../utils/markupLanguageUtils'; +import Dialog from './Dialog'; interface NoteContentPropertiesDialogProps { themeId: number; text: string; markupLanguage: number; - // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied - onClose: Function; + onClose: ()=> void; } interface TextPropertiesMap { @@ -159,22 +159,20 @@ export default function NoteContentPropertiesDialog(props: NoteContentProperties const readTimeLabel = _('Read time: %s min', formatReadTime(strippedReadTime)); return ( -
-
-
{_('Statistics')}
- - - {tableHeader} - - - {tableBodyComps} - -
-
- {readTimeLabel} -
- + +
{_('Statistics')}
+ + + {tableHeader} + + + {tableBodyComps} + +
+
+ {readTimeLabel}
-
+ +
); } diff --git a/packages/app-desktop/gui/NotePropertiesDialog.tsx b/packages/app-desktop/gui/NotePropertiesDialog.tsx index 6bd8faa27..8c6af9131 100644 --- a/packages/app-desktop/gui/NotePropertiesDialog.tsx +++ b/packages/app-desktop/gui/NotePropertiesDialog.tsx @@ -8,14 +8,14 @@ import bridge from '../services/bridge'; import shim from '@joplin/lib/shim'; import { NoteEntity } from '@joplin/lib/services/database/types'; import { focus } from '@joplin/lib/utils/focusHandler'; +import Dialog from './Dialog'; const Datetime = require('react-datetime').default; const { clipboard } = require('electron'); const formatcoords = require('formatcoords'); interface Props { noteId: string; - // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied - onClose: Function; + onClose: ()=> void; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied onRevisionLinkClick: Function; themeId: number; @@ -447,15 +447,13 @@ class NotePropertiesDialog extends React.Component { } return ( -
-
-
{_('Note properties')}
-
- {noteComps} -
- + +
{_('Note properties')}
+
+ {noteComps}
-
+ +
); } } diff --git a/packages/app-desktop/gui/PromptDialog.tsx b/packages/app-desktop/gui/PromptDialog.tsx index c34d2e33c..1a3248b4a 100644 --- a/packages/app-desktop/gui/PromptDialog.tsx +++ b/packages/app-desktop/gui/PromptDialog.tsx @@ -7,6 +7,8 @@ import CreatableSelect from 'react-select/creatable'; import Select from 'react-select'; import makeAnimated from 'react-select/animated'; import { focus } from '@joplin/lib/utils/focusHandler'; +import Dialog from './Dialog'; + interface Props { themeId: number; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied @@ -90,31 +92,6 @@ export default class PromptDialog extends React.Component { this.styles_ = {}; - const paddingTop = 20; - - this.styles_.modalLayer = { - zIndex: 9999, - position: 'absolute', - top: 0, - left: 0, - width: width, - height: height, - boxSizing: 'border-box', - backgroundColor: 'rgba(0,0,0,0.6)', - display: visible ? 'flex' : 'none', - alignItems: 'flex-start', - justifyContent: 'center', - paddingTop: `${paddingTop}px`, - }; - - this.styles_.promptDialog = { - backgroundColor: theme.backgroundColor, - padding: 16, - display: 'inline-block', - maxWidth: width * 0.5, - boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', - }; - this.styles_.button = { minWidth: theme.buttonMinWidth, minHeight: theme.buttonMinHeight, @@ -218,6 +195,8 @@ export default class PromptDialog extends React.Component { } public render() { + if (!this.state.visible) return null; + const style = this.props.style; const theme = themeStyle(this.props.themeId); const buttonTypes = this.props.buttons ? this.props.buttons : ['ok', 'cancel']; @@ -325,16 +304,14 @@ export default class PromptDialog extends React.Component { } return ( -
-
- -
- {inputComp} - {descComp} -
-
{buttonComps}
+ + +
+ {inputComp} + {descComp}
-
+
{buttonComps}
+ ); } } diff --git a/packages/app-desktop/gui/Root.tsx b/packages/app-desktop/gui/Root.tsx index 8ca26d208..948b6783f 100644 --- a/packages/app-desktop/gui/Root.tsx +++ b/packages/app-desktop/gui/Root.tsx @@ -167,7 +167,7 @@ class RootComponent extends React.Component { ); }; - return ; + return {renderContent()}; } private modalDialogProps(): ModalDialogProps { diff --git a/packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx b/packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx index 555de9076..76895ef4e 100644 --- a/packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx +++ b/packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx @@ -407,7 +407,7 @@ function ShareFolderDialog(props: Props) { } return ( - + {renderContent()} ); } diff --git a/packages/app-desktop/gui/ShareNoteDialog.tsx b/packages/app-desktop/gui/ShareNoteDialog.tsx index b62b58f7a..e09427c5a 100644 --- a/packages/app-desktop/gui/ShareNoteDialog.tsx +++ b/packages/app-desktop/gui/ShareNoteDialog.tsx @@ -226,7 +226,7 @@ export function ShareNoteDialog(props: Props) { }; return ( - + {renderContent()} ); } diff --git a/packages/app-desktop/gui/SyncWizard/Dialog.tsx b/packages/app-desktop/gui/SyncWizard/Dialog.tsx index 30814a6ff..3eac5e7b2 100644 --- a/packages/app-desktop/gui/SyncWizard/Dialog.tsx +++ b/packages/app-desktop/gui/SyncWizard/Dialog.tsx @@ -277,6 +277,6 @@ export default function(props: Props) { } return ( - + {renderDialogWrapper()} ); } diff --git a/packages/app-desktop/gui/styles/dialog-modal-layer.scss b/packages/app-desktop/gui/styles/dialog-modal-layer.scss index 2576f7a14..67b7821d3 100644 --- a/packages/app-desktop/gui/styles/dialog-modal-layer.scss +++ b/packages/app-desktop/gui/styles/dialog-modal-layer.scss @@ -13,6 +13,7 @@ > .content { background-color: var(--joplin-background-color); + color: var(--joplin-color); padding: 16px; box-shadow: 6px 6px 20px rgba(0,0,0,0.5); margin: 20px; @@ -23,6 +24,6 @@ } &::backdrop { - background-color: rgba(0,0,0,0.6); + background-color: rgba(0,0,0,0.5); } } diff --git a/packages/app-desktop/gui/styles/index.scss b/packages/app-desktop/gui/styles/index.scss index 736f60da5..75455d811 100644 --- a/packages/app-desktop/gui/styles/index.scss +++ b/packages/app-desktop/gui/styles/index.scss @@ -1,2 +1,4 @@ -@use './dialog-modal-layer.scss'; \ No newline at end of file +@use './dialog-modal-layer.scss'; +@use './user-webview-dialog.scss'; +@use './prompt-dialog.scss'; \ No newline at end of file diff --git a/packages/app-desktop/gui/styles/prompt-dialog.scss b/packages/app-desktop/gui/styles/prompt-dialog.scss new file mode 100644 index 000000000..33fef2a9f --- /dev/null +++ b/packages/app-desktop/gui/styles/prompt-dialog.scss @@ -0,0 +1,7 @@ + +.prompt-dialog { + > .content { + display: inline-block; + max-width: 450px; + } +} \ No newline at end of file diff --git a/packages/app-desktop/gui/styles/user-webview-dialog.scss b/packages/app-desktop/gui/styles/user-webview-dialog.scss new file mode 100644 index 000000000..62b2c2bcb --- /dev/null +++ b/packages/app-desktop/gui/styles/user-webview-dialog.scss @@ -0,0 +1,25 @@ + +.user-webview-dialog { + // Overflow should be handled within WebView dialogs (rather than externally). + // Allowing external overflow can create space for a scrollbar in some cases. + overflow: unset; + align-items: center; + --content-width: 90vw; + --content-height: 90vh; + + &.-fit { + --content-width: auto; + --content-height: auto; + } + + > .content { + display: flex; + flex-direction: column; + background-color: var(--joplin-background-color); + padding: var(--joplin-main-padding); + border-radius: 4px; + box-shadow: 0 6px 10px #00000077; + width: var(--content-width); + height: var(--content-height); + } +} \ No newline at end of file diff --git a/packages/app-desktop/integration-tests/goToAnything.spec.ts b/packages/app-desktop/integration-tests/goToAnything.spec.ts new file mode 100644 index 000000000..b3dcc7c9c --- /dev/null +++ b/packages/app-desktop/integration-tests/goToAnything.spec.ts @@ -0,0 +1,52 @@ + +import { test, expect } from './util/test'; +import MainScreen from './models/MainScreen'; + +test.describe('goToAnything', () => { + test('clicking outside of go to anything should close it', async ({ electronApp, mainWindow }) => { + const mainScreen = new MainScreen(mainWindow); + await mainScreen.noteEditor.waitFor(); + const goToAnything = mainScreen.goToAnything; + await goToAnything.open(electronApp); + + await goToAnything.expectToBeOpen(); + + // Click outside of the dialog + await goToAnything.containerLocator.click({ position: { x: 0, y: 0 } }); + + await goToAnything.expectToBeClosed(); + }); + + test('pressing escape in go to anything should close it ', async ({ electronApp, mainWindow }) => { + const mainScreen = new MainScreen(mainWindow); + const goToAnything = mainScreen.goToAnything; + + // Pressing Escape to close the dialog should work even if opened multiple times in a row. + for (let i = 0; i < 3; i++) { + await goToAnything.open(electronApp); + + await goToAnything.expectToBeOpen(); + await goToAnything.inputLocator.press('Escape'); + await goToAnything.expectToBeClosed(); + } + }); + + test('should be possible to show the set tags dialog from goToAnything', async ({ electronApp, mainWindow }) => { + const mainScreen = new MainScreen(mainWindow); + await mainScreen.createNewNote('Test note'); + + const goToAnything = mainScreen.goToAnything; + await goToAnything.open(electronApp); + await goToAnything.inputLocator.fill(':setTags'); + + // Should show a matching command + await expect(goToAnything.containerLocator.getByText('Tags (setTags)')).toBeAttached(); + + await mainWindow.keyboard.press('Enter'); + await goToAnything.expectToBeClosed(); + + // Should show the "set tags" dialog + const setTagsLabel = mainWindow.getByText('Add or remove tags:'); + await expect(setTagsLabel).toBeVisible(); + }); +}); diff --git a/packages/app-desktop/integration-tests/models/GoToAnything.ts b/packages/app-desktop/integration-tests/models/GoToAnything.ts new file mode 100644 index 000000000..a8374636e --- /dev/null +++ b/packages/app-desktop/integration-tests/models/GoToAnything.ts @@ -0,0 +1,36 @@ + +import { ElectronApplication, expect, Locator, Page } from '@playwright/test'; +import MainScreen from './MainScreen'; +import activateMainMenuItem from '../util/activateMainMenuItem'; + +export default class GoToAnything { + public readonly containerLocator: Locator; + public readonly inputLocator: Locator; + + public constructor(page: Page, private readonly mainScreen: MainScreen) { + this.containerLocator = page.locator('.go-to-anything-dialog[open]'); + this.inputLocator = this.containerLocator.getByRole('textbox'); + } + + public async open(electronApp: ElectronApplication) { + await this.mainScreen.waitFor(); + + if (!await activateMainMenuItem(electronApp, 'Goto Anything...')) { + throw new Error('Menu item for opening Goto Anything not found'); + } + + return this.waitFor(); + } + + public async waitFor() { + await this.containerLocator.waitFor(); + } + + public async expectToBeClosed() { + await expect(this.containerLocator).not.toBeAttached(); + } + + public async expectToBeOpen() { + await expect(this.containerLocator).toBeAttached(); + } +} diff --git a/packages/app-desktop/integration-tests/models/MainScreen.ts b/packages/app-desktop/integration-tests/models/MainScreen.ts index 30ac7b1b5..085ed3dee 100644 --- a/packages/app-desktop/integration-tests/models/MainScreen.ts +++ b/packages/app-desktop/integration-tests/models/MainScreen.ts @@ -2,6 +2,7 @@ import { Page, Locator, ElectronApplication } from '@playwright/test'; import NoteEditorScreen from './NoteEditorScreen'; import activateMainMenuItem from '../util/activateMainMenuItem'; import Sidebar from './Sidebar'; +import GoToAnything from './GoToAnything'; export default class MainScreen { public readonly newNoteButton: Locator; @@ -9,6 +10,7 @@ export default class MainScreen { public readonly sidebar: Sidebar; public readonly dialog: Locator; public readonly noteEditor: NoteEditorScreen; + public readonly goToAnything: GoToAnything; public constructor(private page: Page) { this.newNoteButton = page.locator('.new-note-button'); @@ -16,6 +18,7 @@ export default class MainScreen { this.sidebar = new Sidebar(page, this); this.dialog = page.locator('.dialog-root'); this.noteEditor = new NoteEditorScreen(page); + this.goToAnything = new GoToAnything(page, this); } public async waitFor() { diff --git a/packages/app-desktop/plugins/GotoAnything.tsx b/packages/app-desktop/plugins/GotoAnything.tsx index 5424a1b88..94614411a 100644 --- a/packages/app-desktop/plugins/GotoAnything.tsx +++ b/packages/app-desktop/plugins/GotoAnything.tsx @@ -22,6 +22,7 @@ import Logger from '@joplin/utils/Logger'; import { MarkupLanguage, MarkupToHtml } from '@joplin/renderer'; import Resource from '@joplin/lib/models/Resource'; import { NoteEntity, ResourceEntity } from '@joplin/lib/services/database/types'; +import Dialog from '../gui/Dialog'; const logger = Logger.create('GotoAnything'); @@ -116,7 +117,7 @@ class GotoAnything { } -class Dialog extends React.PureComponent { +class DialogComponent extends React.PureComponent { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private styles_: any; @@ -153,10 +154,8 @@ class Dialog extends React.PureComponent { this.inputRef = React.createRef(); this.itemListRef = React.createRef(); - this.onKeyDown = this.onKeyDown.bind(this); this.input_onChange = this.input_onChange.bind(this); this.input_onKeyDown = this.input_onKeyDown.bind(this); - this.modalLayer_onClick = this.modalLayer_onClick.bind(this); this.renderItem = this.renderItem.bind(this); this.listItem_onClick = this.listItem_onClick.bind(this); this.helpButton_onClick = this.helpButton_onClick.bind(this); @@ -226,8 +225,6 @@ class Dialog extends React.PureComponent { } public componentDidMount() { - document.addEventListener('keydown', this.onKeyDown); - this.props.dispatch({ type: 'VISIBLE_DIALOGS_ADD', name: 'gotoAnything', @@ -236,7 +233,6 @@ class Dialog extends React.PureComponent { public componentWillUnmount() { if (this.listUpdateIID_) shim.clearTimeout(this.listUpdateIID_); - document.removeEventListener('keydown', this.onKeyDown); this.props.dispatch({ type: 'VISIBLE_DIALOGS_REMOVE', @@ -244,27 +240,13 @@ class Dialog extends React.PureComponent { }); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - public onKeyDown(event: any) { - if (event.keyCode === 27) { // ESCAPE - this.props.dispatch({ - pluginName: PLUGIN_NAME, - type: 'PLUGINLEGACY_DIALOG_SET', - open: false, - }); - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - private modalLayer_onClick(event: any) { - if (event.currentTarget === event.target) { - this.props.dispatch({ - pluginName: PLUGIN_NAME, - type: 'PLUGINLEGACY_DIALOG_SET', - open: false, - }); - } - } + private modalLayer_onDismiss = () => { + this.props.dispatch({ + pluginName: PLUGIN_NAME, + type: 'PLUGINLEGACY_DIALOG_SET', + open: false, + }); + }; private helpButton_onClick() { this.setState({ showHelp: !this.state.showHelp }); @@ -646,21 +628,18 @@ class Dialog extends React.PureComponent { } public render() { - const theme = themeStyle(this.props.themeId); const style = this.style(); const helpComp = !this.state.showHelp ? null :
{_('Type a note title or part of its content to jump to it. Or type # followed by a tag name, or @ followed by a notebook name. Or type : to search for commands.')}
; return ( -
-
- {helpComp} -
- - -
- {this.renderList()} + + {helpComp} +
+ +
-
+ {this.renderList()} +
); } @@ -675,7 +654,7 @@ const mapStateToProps = (state: AppState) => { }; }; -GotoAnything.Dialog = connect(mapStateToProps)(Dialog); +GotoAnything.Dialog = connect(mapStateToProps)(DialogComponent); GotoAnything.manifest = { diff --git a/packages/app-desktop/services/plugins/UserWebviewDialog.tsx b/packages/app-desktop/services/plugins/UserWebviewDialog.tsx index 9b3c4cb48..942d63da4 100644 --- a/packages/app-desktop/services/plugins/UserWebviewDialog.tsx +++ b/packages/app-desktop/services/plugins/UserWebviewDialog.tsx @@ -6,40 +6,14 @@ import WebviewController from '@joplin/lib/services/plugins/WebviewController'; import UserWebview, { Props as UserWebviewProps } from './UserWebview'; import UserWebviewDialogButtonBar from './UserWebviewDialogButtonBar'; import { focus } from '@joplin/lib/utils/focusHandler'; +import Dialog from '../../gui/Dialog'; const styled = require('styled-components').default; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -type StyleProps = any; - interface Props extends UserWebviewProps { buttons: ButtonSpec[]; fitToContent: boolean; } -const StyledRoot = styled.div` - display: flex; - flex: 1; - padding: 0; - margin: 0; - width: 100%; - height: 100%; - background-color: rgba(0,0,0,0.5); - box-sizing: border-box; - justify-content: center; - align-items: center; -`; - -const Dialog = styled.div` - display: flex; - flex-direction: column; - background-color: ${(props: StyleProps) => props.theme.backgroundColor}; - padding: ${(props: StyleProps) => `${props.theme.mainPadding}px`}; - border-radius: 4px; - box-shadow: 0 6px 10px #00000077; - width: ${(props: StyleProps) => props.fitToContent ? 'auto' : '90vw'}; - height: ${(props: StyleProps) => props.fitToContent ? 'auto' : '80vh'}; -`; - const UserWebViewWrapper = styled.div` display: flex; flex: 1; @@ -109,25 +83,23 @@ export default function UserWebviewDialog(props: Props) { }, []); return ( - - - - - - - - + + + + + + ); }