aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2019-06-19 20:11:45 +0300
committerGravatar Vitaly Takmazov2023-01-13 10:37:55 +0300
commit6d5e8905d6a676ca966fa32f6823ebc1409caabe (patch)
tree7979b4da9b639fc885c5f4c76616a188ca0f32cb
parent0c6b3b009f51fc5fa092176886069b4bece808eb (diff)
Post: user tags
-rw-r--r--vnext/src/ui/MessageInput.js39
-rw-r--r--vnext/src/ui/Post.js30
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