chore: fix note options menu visibility in plain editor on mobile [skip e2e]
This commit is contained in:
@@ -29,7 +29,7 @@ import {
|
|||||||
VaultUserServiceEvent,
|
VaultUserServiceEvent,
|
||||||
} from '@standardnotes/snjs'
|
} from '@standardnotes/snjs'
|
||||||
import { confirmDialog, DELETE_NOTE_KEYBOARD_COMMAND, KeyboardKey } from '@standardnotes/ui-services'
|
import { confirmDialog, DELETE_NOTE_KEYBOARD_COMMAND, KeyboardKey } from '@standardnotes/ui-services'
|
||||||
import { ChangeEventHandler, createRef, CSSProperties, KeyboardEventHandler, RefObject } from 'react'
|
import { ChangeEventHandler, createRef, CSSProperties, FocusEvent, KeyboardEventHandler, RefObject } from 'react'
|
||||||
import { SuperEditor } from '../SuperEditor/SuperEditor'
|
import { SuperEditor } from '../SuperEditor/SuperEditor'
|
||||||
import IndicatorCircle from '../IndicatorCircle/IndicatorCircle'
|
import IndicatorCircle from '../IndicatorCircle/IndicatorCircle'
|
||||||
import LinkedItemBubblesContainer from '../LinkedItems/LinkedItemBubblesContainer'
|
import LinkedItemBubblesContainer from '../LinkedItems/LinkedItemBubblesContainer'
|
||||||
@@ -826,7 +826,10 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
|||||||
this.setState({ plainEditorFocused: true })
|
this.setState({ plainEditorFocused: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlainBlur = () => {
|
onPlainBlur = (event: FocusEvent) => {
|
||||||
|
if (event.relatedTarget?.id === ElementIds.NoteOptionsButton) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.setState({ plainEditorFocused: false })
|
this.setState({ plainEditorFocused: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,30 +940,33 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
|||||||
{pluralize(this.state.conflictedNotes.length, 'conflict', 'conflicts')}
|
{pluralize(this.state.conflictedNotes.length, 'conflict', 'conflicts')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{renderHeaderOptions && (
|
<div className="note-view-options-buttons flex items-center gap-3">
|
||||||
<div className="note-view-options-buttons flex items-center gap-3">
|
{!this.state.readonly && renderHeaderOptions && (
|
||||||
{!this.state.readonly && (
|
<>
|
||||||
<>
|
<LinkedItemsButton
|
||||||
<LinkedItemsButton
|
linkingController={this.application.linkingController}
|
||||||
linkingController={this.application.linkingController}
|
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
/>
|
||||||
/>
|
<ChangeEditorButton
|
||||||
<ChangeEditorButton
|
noteViewController={this.controller}
|
||||||
noteViewController={this.controller}
|
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
/>
|
||||||
/>
|
<PinNoteButton
|
||||||
<PinNoteButton
|
notesController={this.application.notesController}
|
||||||
notesController={this.application.notesController}
|
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
/>
|
||||||
/>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
<NotesOptionsPanel
|
||||||
<NotesOptionsPanel
|
notesController={this.application.notesController}
|
||||||
notesController={this.application.notesController}
|
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
onButtonBlur={() => {
|
||||||
/>
|
this.setState({
|
||||||
</div>
|
plainEditorFocused: false,
|
||||||
)}
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-1 mt-2.5 md:hidden">
|
<div className="mb-1 mt-2.5 md:hidden">
|
||||||
<CollaborationInfoHUD item={this.note} />
|
<CollaborationInfoHUD item={this.note} />
|
||||||
|
|||||||
@@ -16,7 +16,16 @@ import {
|
|||||||
PrefDefaults,
|
PrefDefaults,
|
||||||
} from '@standardnotes/snjs'
|
} from '@standardnotes/snjs'
|
||||||
import { TAB_COMMAND } from '@standardnotes/ui-services'
|
import { TAB_COMMAND } from '@standardnotes/ui-services'
|
||||||
import { ChangeEventHandler, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
import {
|
||||||
|
ChangeEventHandler,
|
||||||
|
forwardRef,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useImperativeHandle,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
FocusEvent,
|
||||||
|
} from 'react'
|
||||||
import { NoteViewController } from '../Controller/NoteViewController'
|
import { NoteViewController } from '../Controller/NoteViewController'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -25,7 +34,7 @@ type Props = {
|
|||||||
controller: NoteViewController
|
controller: NoteViewController
|
||||||
locked: boolean
|
locked: boolean
|
||||||
onFocus: () => void
|
onFocus: () => void
|
||||||
onBlur: () => void
|
onBlur: (event: FocusEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlainEditorInterface = {
|
export type PlainEditorInterface = {
|
||||||
@@ -106,13 +115,16 @@ export const PlainEditor = forwardRef<PlainEditorInterface, Props>(
|
|||||||
onFocus()
|
onFocus()
|
||||||
}, [application, isAdjustingMobileCursor, lastEditorFocusEventSource, onFocus])
|
}, [application, isAdjustingMobileCursor, lastEditorFocusEventSource, onFocus])
|
||||||
|
|
||||||
const onContentBlur = useCallback(() => {
|
const onContentBlur = useCallback(
|
||||||
if (lastEditorFocusEventSource.current) {
|
(event: FocusEvent) => {
|
||||||
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
|
if (lastEditorFocusEventSource.current) {
|
||||||
}
|
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
|
||||||
lastEditorFocusEventSource.current = undefined
|
}
|
||||||
onBlur()
|
lastEditorFocusEventSource.current = undefined
|
||||||
}, [application, lastEditorFocusEventSource, onBlur])
|
onBlur(event)
|
||||||
|
},
|
||||||
|
[application, lastEditorFocusEventSource, onBlur],
|
||||||
|
)
|
||||||
|
|
||||||
const scrollMobileCursorIntoViewAfterWebviewResize = useCallback(() => {
|
const scrollMobileCursorIntoViewAfterWebviewResize = useCallback(() => {
|
||||||
if (needsAdjustMobileCursor.current) {
|
if (needsAdjustMobileCursor.current) {
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { useCallback, useRef, useState } from 'react'
|
import { FocusEvent, useCallback, useRef, useState } from 'react'
|
||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import NotesOptions from './NotesOptions'
|
import NotesOptions from './NotesOptions'
|
||||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||||
import Popover from '../Popover/Popover'
|
import Popover from '../Popover/Popover'
|
||||||
import RoundIconButton from '../Button/RoundIconButton'
|
import RoundIconButton from '../Button/RoundIconButton'
|
||||||
import Menu from '../Menu/Menu'
|
import Menu from '../Menu/Menu'
|
||||||
|
import { ElementIds } from '@/Constants/ElementIDs'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
notesController: NotesController
|
notesController: NotesController
|
||||||
onClickPreprocessing?: () => Promise<void>
|
onClickPreprocessing?: () => Promise<void>
|
||||||
|
onButtonBlur?: (event: FocusEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) => {
|
const NotesOptionsPanel = ({ notesController, onClickPreprocessing, onButtonBlur }: Props) => {
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const buttonRef = useRef<HTMLButtonElement>(null)
|
const buttonRef = useRef<HTMLButtonElement>(null)
|
||||||
|
|
||||||
@@ -30,7 +32,14 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) =>
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RoundIconButton label="Note options menu" onClick={toggleMenu} ref={buttonRef} icon="more" />
|
<RoundIconButton
|
||||||
|
id={ElementIds.NoteOptionsButton}
|
||||||
|
label="Note options menu"
|
||||||
|
onClick={toggleMenu}
|
||||||
|
onBlur={onButtonBlur}
|
||||||
|
ref={buttonRef}
|
||||||
|
icon="more"
|
||||||
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
title="Note options"
|
title="Note options"
|
||||||
disableClickOutside={disableClickOutside}
|
disableClickOutside={disableClickOutside}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const ElementIds = {
|
|||||||
NavigationColumn: 'navigation',
|
NavigationColumn: 'navigation',
|
||||||
NoteTextEditor: 'note-text-editor',
|
NoteTextEditor: 'note-text-editor',
|
||||||
NoteTitleEditor: 'note-title-editor',
|
NoteTitleEditor: 'note-title-editor',
|
||||||
|
NoteOptionsButton: 'note-options-button',
|
||||||
RootId: 'app-group-root',
|
RootId: 'app-group-root',
|
||||||
NoteStatusTooltip: 'note-status-tooltip',
|
NoteStatusTooltip: 'note-status-tooltip',
|
||||||
ItemLinkAutocompleteInput: 'item-link-autocomplete-input',
|
ItemLinkAutocompleteInput: 'item-link-autocomplete-input',
|
||||||
|
|||||||
Reference in New Issue
Block a user