diff options
author | Vitaly Takmazov | 2019-06-19 20:11:45 +0300 |
---|---|---|
committer | Vitaly Takmazov | 2023-01-13 10:37:55 +0300 |
commit | 6d5e8905d6a676ca966fa32f6823ebc1409caabe (patch) | |
tree | 7979b4da9b639fc885c5f4c76616a188ca0f32cb | |
parent | 0c6b3b009f51fc5fa092176886069b4bece808eb (diff) |
Post: user tags
-rw-r--r-- | vnext/src/ui/MessageInput.js | 39 | ||||
-rw-r--r-- | vnext/src/ui/Post.js | 30 |
2 files changed, 50 insertions, 19 deletions
diff --git a/vnext/src/ui/MessageInput.js b/vnext/src/ui/MessageInput.js index a746ba08..63c2ee79 100644 --- a/vnext/src/ui/MessageInput.js +++ b/vnext/src/ui/MessageInput.js @@ -1,8 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; -import { useFormState } from 'react-use-form-state'; - import { MessageType } from './Types'; import Icon from './Icon'; @@ -10,6 +8,19 @@ import Button from './Button'; import UploadButton from './UploadButton'; + +// StackOverflow-driven development: https://stackoverflow.com/a/10158364/1097384 +function moveCaretToEnd(el) { + if (typeof el.selectionStart == 'number') { + el.selectionStart = el.selectionEnd = el.value.length; + } else if (typeof el.createTextRange != 'undefined') { + el.focus(); + var range = el.createTextRange(); + range.collapse(false); + range.select(); + } +} + export default function MessageInput({ text, data, rows, children, onSend }) { let textareaRef = useRef(); let fileinput = useRef(); @@ -18,28 +29,33 @@ export default function MessageInput({ text, data, rows, children, onSend }) { const isDesktop = window.matchMedia('(min-width: 62.5rem)'); if (isDesktop.matches) { textareaRef.current.focus(); + moveCaretToEnd(textareaRef.current); } }; useEffect(() => { - textChanged(); + textChanged({ + target: { + value: text + } + }); updateFocus(); - }, []); + }, [text]); + + let [body, setBody] = useState(text); let handleCtrlEnter = (event) => { if (event.ctrlKey && (event.charCode == 10 || event.charCode == 13)) { onSubmit({}); } }; - let textChanged = (event) => { + const textChanged = (event) => { + setBody(event.target.value); const el = textareaRef.current; const offset = el.offsetHeight - el.clientHeight; const height = el.scrollHeight + offset; el.style.height = `${height + offset}px`; }; const [attach, setAttach] = useState(''); - const [formState, { textarea }] = useFormState({ - body: text - }); let uploadValueChanged = (attach) => { setAttach(attach); }; @@ -51,12 +67,12 @@ export default function MessageInput({ text, data, rows, children, onSend }) { onSend({ mid: data.mid, rid: data.rid || 0, - body: formState.values.body, + body: body, attach: attach ? input.files[0] : '', to: data.to || {} }); setAttach(''); - formState.clearField('body'); + setBody(''); textareaRef.current.style.height = ''; updateFocus(); }; @@ -65,7 +81,7 @@ export default function MessageInput({ text, data, rows, children, onSend }) { <div style={commentStyle}> <textarea onChange={textChanged} onKeyPress={handleCtrlEnter} ref={textareaRef} style={textInputStyle} - rows={rows || '1'} placeholder={children} {...textarea('body')} /> + rows={rows || '1'} placeholder={children} value={body} /> <div style={inputBarStyle}> <UploadButton inputRef={fileinput} value={attach} onChange={uploadValueChanged} /> <Button onClick={onSubmit}><Icon name="ei-envelope" size="s" />Send</Button> @@ -78,7 +94,6 @@ export default function MessageInput({ text, data, rows, children, onSend }) { const commentStyle = { display: 'flex', flexDirection: 'column', - borderTop: '1px #eee solid', width: '100%', marginTop: '10px' }; diff --git a/vnext/src/ui/Post.js b/vnext/src/ui/Post.js index dc1c7a9d..662f9f78 100644 --- a/vnext/src/ui/Post.js +++ b/vnext/src/ui/Post.js @@ -1,16 +1,18 @@ -import React, { memo } from 'react'; +import React, { useState } from 'react'; import ReactRouterPropTypes from 'react-router-prop-types'; import { UserType } from './Types'; import qs from 'qs'; +import Button from './Button'; import MessageInput from './MessageInput'; import { post, update } from '../api'; -function PostComponent({ location, visitor, history }) { +export default function Post({ location, visitor, history }) { let draftMessage = (location.state || {}).draft || {}; + let [draft, setDraft] = useState(draftMessage.body); let params = qs.parse(window.location.search.substring(1)); let postMessage = (template) => { const { attach, body } = template; @@ -23,18 +25,32 @@ function PostComponent({ location, visitor, history }) { } }).catch(console.log); }; + let appendTag = (tag) => { + setDraft(prevDraft => { + return `${prevDraft || ''} *${tag} `; + }); + }; return ( <div className="msg-cont"> - <MessageInput rows="7" text={params.body || draftMessage.body || ''} data={{ mid: 0, timestamp: '0' }} onSend={postMessage}> + <MessageInput rows="7" text={params.body || draft || ''} data={{ mid: 0, timestamp: '0' }} onSend={postMessage}> *weather It is very cold today! - </MessageInput> + </MessageInput> + { + visitor.tagStats && + <div style={{ padding: '6px' }}> + <p>Tags:</p> + { + visitor.tagStats.map(t => { + return (<Button key={t.tag} onClick={() => { appendTag(t.tag); }}>{t.tag}</Button>); + }) + } + </div> + } </div> ); } -export default memo(PostComponent); - -PostComponent.propTypes = { +Post.propTypes = { location: ReactRouterPropTypes.location, history: ReactRouterPropTypes.history.isRequired, visitor: UserType |