import * as React from 'react'; import { _ } from '@joplin/lib/locale'; import CommandService from '@joplin/lib/services/CommandService'; import { ChangeEvent, useCallback, useContext, useRef } from 'react'; import NoteToolbar from '../../NoteToolbar/NoteToolbar'; import { buildStyle } from '@joplin/lib/theme'; import time from '@joplin/lib/time'; import { WindowIdContext } from '../../NewWindowOrIFrame'; interface Props { themeId: number; noteUserUpdatedTime: number; noteTitle: string; noteIsTodo: number; isProvisional: boolean; titleInputRef: React.RefObject; onTitleChange(event: ChangeEvent): void; disabled: boolean; } function styles_(props: Props) { return buildStyle(['NoteEditorTitleBar'], props.themeId, theme => { return { titleInput: { flex: 1, display: 'inline-block', paddingTop: 5, minHeight: 38, boxSizing: 'border-box', fontWeight: 'bold', paddingBottom: 5, paddingLeft: 0, paddingRight: 8, color: theme.textStyle.color, fontSize: Math.round(theme.textStyle.fontSize * 1.5), backgroundColor: theme.backgroundColor, border: 'none', width: '100%', }, titleDate: { ...theme.textStyle, color: theme.colorFaded, paddingLeft: 8, whiteSpace: 'nowrap', }, toolbarStyle: { marginBottom: 0, minWidth: 0, }, }; }); } const useReselectHandlers = () => { const lastTitleFocus = useRef([0, 0]); const lastTitleValue = useRef(''); const onTitleBlur: React.FocusEventHandler = useCallback((event) => { const titleElement = event.currentTarget; lastTitleFocus.current = [titleElement.selectionStart, titleElement.selectionEnd]; lastTitleValue.current = titleElement.value; }, []); const onTitleFocus: React.FocusEventHandler = useCallback((event) => { const titleElement = event.currentTarget; // By default, focusing the note title bar can cause its content to become selected. We override // this with a more reasonable default: if (titleElement.selectionStart === 0 && titleElement.selectionEnd === titleElement.value.length) { if (lastTitleValue.current !== titleElement.value) { titleElement.selectionStart = titleElement.value.length; } else { titleElement.selectionStart = lastTitleFocus.current[0]; titleElement.selectionEnd = lastTitleFocus.current[1]; } } }, []); return { onTitleBlur, onTitleFocus }; }; export default function NoteTitleBar(props: Props) { const styles = styles_(props); const onTitleKeydown: React.KeyboardEventHandler = useCallback((event) => { const titleElement = event.currentTarget; const selectionAtEnd = titleElement.selectionEnd === titleElement.value.length; const isNavigationShortcut = (event.key === 'ArrowDown' && selectionAtEnd) || (event.key === 'Enter' && !event.shiftKey); const composing = event.nativeEvent.isComposing; // Don't change focus if the navigation shortcut is fired during composition. See // https://github.com/laurent22/joplin/issues/11485. if (!composing && isNavigationShortcut) { event.preventDefault(); const moveCursorToStart = event.key === 'ArrowDown'; void CommandService.instance().execute('focusElement', 'noteBody', { moveCursorToStart }); } }, []); const { onTitleFocus, onTitleBlur } = useReselectHandlers(); function renderTitleBarDate() { return {time.formatMsToLocal(props.noteUserUpdatedTime)}; } const windowId = useContext(WindowIdContext); function renderNoteToolbar() { return ; } return (
{renderTitleBarDate()} {renderNoteToolbar()}
); }