feat: add Giphy support with embed component and power levels state management
This commit is contained in:
@@ -31,8 +31,11 @@ import {
|
||||
import { HTMLReactParserOptions } from 'html-react-parser';
|
||||
import { Opts as LinkifyOpts } from 'linkifyjs';
|
||||
import { ReactEditor } from 'slate-react';
|
||||
import { isKeyHotkey } from 'is-hotkey';
|
||||
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { useKeyDown } from '../../hooks/useKeyDown';
|
||||
import { editableActiveElement } from '../../utils/dom';
|
||||
import {
|
||||
useEditor,
|
||||
createMentionElement,
|
||||
@@ -100,6 +103,37 @@ type ThreadViewProps = {
|
||||
threadRootId: string;
|
||||
};
|
||||
|
||||
const FN_KEYS_REGEX = /^F\d+$/;
|
||||
const shouldFocusMessageField = (evt: KeyboardEvent): boolean => {
|
||||
const { code } = evt;
|
||||
if (evt.metaKey || evt.altKey || evt.ctrlKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FN_KEYS_REGEX.test(code)) return false;
|
||||
|
||||
if (
|
||||
code.startsWith('OS') ||
|
||||
code.startsWith('Meta') ||
|
||||
code.startsWith('Shift') ||
|
||||
code.startsWith('Alt') ||
|
||||
code.startsWith('Control') ||
|
||||
code.startsWith('Arrow') ||
|
||||
code.startsWith('Page') ||
|
||||
code.startsWith('End') ||
|
||||
code.startsWith('Home') ||
|
||||
code === 'Tab' ||
|
||||
code === 'Space' ||
|
||||
code === 'Enter' ||
|
||||
code === 'NumLock' ||
|
||||
code === 'ScrollLock'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a thread inline, replacing the main room timeline.
|
||||
* Structured as direct flex siblings of `Page` to match the RoomView layout contract.
|
||||
@@ -285,6 +319,29 @@ export function ThreadView({ room, threadRootId }: ThreadViewProps) {
|
||||
const inputRef = useRef<HTMLDivElement>(null);
|
||||
const editor = useEditor();
|
||||
|
||||
useKeyDown(
|
||||
window,
|
||||
useCallback(
|
||||
(evt) => {
|
||||
if (editableActiveElement()) return;
|
||||
const portalContainer = document.getElementById('portalContainer');
|
||||
if (portalContainer && portalContainer.children.length > 0) {
|
||||
return;
|
||||
}
|
||||
if (shouldFocusMessageField(evt)) {
|
||||
evt.preventDefault();
|
||||
ReactEditor.focus(editor);
|
||||
if (evt.key.length === 1) {
|
||||
editor.insertText(evt.key);
|
||||
}
|
||||
} else if (isKeyHotkey('mod+v', evt)) {
|
||||
ReactEditor.focus(editor);
|
||||
}
|
||||
},
|
||||
[editor]
|
||||
)
|
||||
);
|
||||
|
||||
// Subscribe to thread and room timeline events.
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
Reference in New Issue
Block a user