Better handle multiline formatting

This commit is contained in:
Scott Nonnenberg 2023-05-12 13:48:14 -07:00 committed by GitHub
parent bd0e08d6fd
commit 1c4213465b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 30 deletions

View file

@ -836,6 +836,12 @@ export function CompositionInput(props: Props): React.ReactElement {
return; return;
} }
setIsMouseDown(true); setIsMouseDown(true);
const onMouseUp = () => {
setIsMouseDown(false);
window.removeEventListener('mouseup', onMouseUp);
};
window.addEventListener('mouseup', onMouseUp);
} catch (error) { } catch (error) {
log.error( log.error(
'CompositionInput.onMouseDown: Failed to check event target', 'CompositionInput.onMouseDown: Failed to check event target',
@ -846,32 +852,6 @@ export function CompositionInput(props: Props): React.ReactElement {
}, },
[setIsMouseDown] [setIsMouseDown]
); );
const onMouseUp = React.useCallback(
() => setIsMouseDown(false),
[setIsMouseDown]
);
const onMouseOut = React.useCallback(
event => {
const target = event.target as HTMLElement;
try {
// We get mouseout events for child objects of this one; filter 'em out!
if (!target.classList.contains(getClassName('__input'))) {
return;
}
setIsMouseDown(false);
} catch (error) {
log.error(
'CompositionInput.onMouseOut: Failed to check class list',
Errors.toLogFormat(error)
);
}
},
[getClassName, setIsMouseDown]
);
const onBlur = React.useCallback(
() => setIsMouseDown(false),
[setIsMouseDown]
);
return ( return (
<Manager> <Manager>
@ -884,9 +864,6 @@ export function CompositionInput(props: Props): React.ReactElement {
data-testid="CompositionInput" data-testid="CompositionInput"
data-enabled={disabled ? 'false' : 'true'} data-enabled={disabled ? 'false' : 'true'}
onMouseDown={onMouseDown} onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onMouseOut={onMouseOut}
onBlur={onBlur}
> >
{draftEditMessage && ( {draftEditMessage && (
<div className={getClassName('__editing-message')}> <div className={getClassName('__editing-message')}>

View file

@ -249,7 +249,11 @@ export class FormattingMenu {
return; return;
} }
const contents = this.quill.getContents(selection.index, selection.length); const contents = this.quill.getContents(selection.index, selection.length);
return contents.ops.every(op => op.attributes?.[style]);
// Note: we special-case single \n ops because Quill doesn't apply formatting to them
return contents.ops.every(
op => op.attributes?.[style] || op.insert === '\n'
);
} }
toggleForStyle(style: QuillFormattingStyle, context?: KeyboardContext): void { toggleForStyle(style: QuillFormattingStyle, context?: KeyboardContext): void {

View file

@ -165,6 +165,11 @@ export const getTextAndRangesFromOps = (
}; };
const preTrimText = ops.reduce((acc, op) => { const preTrimText = ops.reduce((acc, op) => {
// We special-case single-newline ops because Quill doesn't apply styles to them
if (op.insert === '\n') {
return acc + op.insert;
}
// Start or finish format sections as needed // Start or finish format sections as needed
formats = extractAllFormats(startingBodyRanges, formats, acc.length, op); formats = extractAllFormats(startingBodyRanges, formats, acc.length, op);