From a6c8587e70cede0a2930286c4548623d54c12be2 Mon Sep 17 00:00:00 2001 From: keyan Date: Tue, 3 Oct 2023 20:06:48 -0500 Subject: [PATCH] onPointerDown for mobile, quote+reply quotes text --- components/action-dropdown.js | 2 +- components/form.js | 100 ++++++++++++++++++---------------- components/item-info.js | 4 +- components/reply.js | 11 +++- 4 files changed, 65 insertions(+), 52 deletions(-) diff --git a/components/action-dropdown.js b/components/action-dropdown.js index 497f150d0..ea19ebaca 100644 --- a/components/action-dropdown.js +++ b/components/action-dropdown.js @@ -8,7 +8,7 @@ export default function ActionDropdown ({ children }) { } return ( - e.preventDefault()}> + e.preventDefault()}> diff --git a/components/form.js b/components/form.js index 8b947eb84..d135256c5 100644 --- a/components/form.js +++ b/components/form.js @@ -92,6 +92,7 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH const [, meta, helpers] = useField(props) const [selectionRange, setSelectionRange] = useState({ start: 0, end: 0 }) innerRef = innerRef || useRef(null) + const previousTab = useRef(tab) props.as ||= TextareaAutosize props.rows ||= props.minRows || 6 @@ -100,6 +101,14 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH !meta.value && setTab('write') }, [meta.value]) + useEffect(() => { + // focus on input when switching to write tab from preview tab + if (innerRef?.current && tab === 'write' && previousTab?.current !== 'write') { + innerRef.current.focus() + } + previousTab.current = tab + }, [tab]) + useEffect(() => { if (selectionRange.start <= selectionRange.end && innerRef?.current) { const { start, end } = selectionRange @@ -125,53 +134,49 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH - {tab === 'write' - ? ( -
- { - if (onChange) onChange(formik, e) - if (setHasImgLink) { - setHasImgLink(mdHas(e.target.value, ['link', 'image'])) - } - }} - innerRef={innerRef} - onKeyDown={(e) => { - const metaOrCtrl = e.metaKey || e.ctrlKey - if (metaOrCtrl) { - if (e.key === 'k') { - // some browsers use CTRL+K to focus search bar so we have to prevent that behavior - e.preventDefault() - insertMarkdownLinkFormatting(innerRef.current, helpers.setValue, setSelectionRange) - } - if (e.key === 'b') { - // some browsers use CTRL+B to open bookmarks so we have to prevent that behavior - e.preventDefault() - insertMarkdownBoldFormatting(innerRef.current, helpers.setValue, setSelectionRange) - } - if (e.key === 'i') { - // some browsers might use CTRL+I to do something else so prevent that behavior too - e.preventDefault() - insertMarkdownItalicFormatting(innerRef.current, helpers.setValue, setSelectionRange) - } - if (e.key === 'Tab' && e.altKey) { - e.preventDefault() - insertMarkdownTabFormatting(innerRef.current, helpers.setValue, setSelectionRange) - } - } - - if (onKeyDown) onKeyDown(e) - }} - /> -
) - : ( -
-
- {meta.value} -
-
- )} +
+ { + if (onChange) onChange(formik, e) + if (setHasImgLink) { + setHasImgLink(mdHas(e.target.value, ['link', 'image'])) + } + }} + innerRef={innerRef} + onKeyDown={(e) => { + const metaOrCtrl = e.metaKey || e.ctrlKey + if (metaOrCtrl) { + if (e.key === 'k') { + // some browsers use CTRL+K to focus search bar so we have to prevent that behavior + e.preventDefault() + insertMarkdownLinkFormatting(innerRef.current, helpers.setValue, setSelectionRange) + } + if (e.key === 'b') { + // some browsers use CTRL+B to open bookmarks so we have to prevent that behavior + e.preventDefault() + insertMarkdownBoldFormatting(innerRef.current, helpers.setValue, setSelectionRange) + } + if (e.key === 'i') { + // some browsers might use CTRL+I to do something else so prevent that behavior too + e.preventDefault() + insertMarkdownItalicFormatting(innerRef.current, helpers.setValue, setSelectionRange) + } + if (e.key === 'Tab' && e.altKey) { + e.preventDefault() + insertMarkdownTabFormatting(innerRef.current, helpers.setValue, setSelectionRange) + } + } + if (onKeyDown) onKeyDown(e) + }} + /> +
+ {tab !== 'write' && +
+
+ {meta.value} +
+
} ) @@ -225,7 +230,8 @@ function FormGroup ({ className, label, children }) { function InputInner ({ prepend, append, hint, showValid, onChange, onBlur, overrideValue, - innerRef, noForm, clear, onKeyDown, inputGroupClassName, debounce, maxLength, ...props + innerRef, noForm, clear, onKeyDown, inputGroupClassName, debounce, maxLength, + ...props }) { const [field, meta, helpers] = noForm ? [{}, {}, {}] : useField(props) const formik = noForm ? null : useFormikContext() diff --git a/components/item-info.js b/components/item-info.js index c75576c30..783d70536 100644 --- a/components/item-info.js +++ b/components/item-info.js @@ -133,6 +133,8 @@ export default function ItemInfo ({ } + {(item.parentId || item.text) && onQuoteReply && + quote reply} {me && } {me && !item.mine && } {item.otsHash && @@ -148,8 +150,6 @@ export default function ItemInfo ({
} - {(item.parentId || item.text) && onQuoteReply && - quote reply}
{extraInfo} diff --git a/components/reply.js b/components/reply.js index 66c02cd36..9bdd16bf2 100644 --- a/components/reply.js +++ b/components/reply.js @@ -41,13 +41,14 @@ export default forwardRef(function Reply ({ item, onSuccess, replyOpen, children const replyInput = useRef(null) const formInnerRef = useRef() useImperativeHandle(ref, () => ({ - quoteReply: () => { + quoteReply: ({ selectionOnly }) => { if (!reply) { setReply(true) } const selection = window.getSelection() const selectedText = selection.isCollapsed ? undefined : selection.toString() const isSelectedTextInTarget = contentContainerRef?.current?.contains(selection.anchorNode) + if ((selection.isCollapsed || !isSelectedTextInTarget) && selectionOnly) return const textToQuote = isSelectedTextInTarget ? selectedText : item.text let updatedValue if (formInnerRef.current && formInnerRef.current.values && !formInnerRef.current.values.text) { @@ -133,7 +134,13 @@ export default forwardRef(function Reply ({ item, onSuccess, replyOpen, children : (
setReply(!reply)} + onPointerDown={e => { + if (!reply) { + e.preventDefault() + ref?.current?.quoteReply({ selectionOnly: true }) + } + setReply(!reply) + }} > {reply ? 'cancel' : 'reply'}