aboutsummaryrefslogtreecommitdiff
path: root/vnext
diff options
context:
space:
mode:
Diffstat (limited to 'vnext')
-rw-r--r--vnext/src/ui/Message.js42
-rw-r--r--vnext/src/ui/Thread.js24
2 files changed, 54 insertions, 12 deletions
diff --git a/vnext/src/ui/Message.js b/vnext/src/ui/Message.js
index d45395bb..3bb59a4a 100644
--- a/vnext/src/ui/Message.js
+++ b/vnext/src/ui/Message.js
@@ -15,8 +15,15 @@ import { format, embedUrls } from '../utils/embed';
import { useVisitor } from './VisitorContext';
/**
+ * @callback ToggleSubscriptionCallback
+ * @param { import('../client').Message } message
+ */
+
+/**
* @typedef {object} MessageProps
* @property { import('../client').Message } data data
+ * @property {boolean} isThread
+ * @property {ToggleSubscriptionCallback} onToggleSubscription
*/
/**
@@ -24,7 +31,7 @@ import { useVisitor } from './VisitorContext';
*
* @param {React.PropsWithChildren<{}> & MessageProps} props props
*/
-export default function Message({ data, children }) {
+export default function Message({ data, isThread = false, onToggleSubscription, children }) {
const [visitor] = useVisitor();
const isCode = (data.tags || []).indexOf('code') >= 0;
const likesSummary = data.likes ? `${data.likes}` : 'Recommend';
@@ -68,7 +75,7 @@ export default function Message({ data, children }) {
<span>&nbsp;&middot;&nbsp;</span>
<Link to={{
pathname: '/post',
- }} state={{data: data}}>Edit</Link>
+ }} state={{ data: data }}>Edit</Link>
</>
}
</div>
@@ -109,16 +116,31 @@ export default function Message({ data, children }) {
<span>{likesSummary}</span>
</Link>
)}
- {data.user && canComment && (
- <Link to={`/${data.user.uname}/${data.mid}`} className="a-comment msg-button"
- state={{ data: data }}>
- <Icon name="ei-comment" size="s" />
- <span>{commentsSummary}</span>
- </Link>
- )}
+ {
+ data.user && canComment && ((
+ isThread ? (
+ <Link className="msg-button" onClick={() => { onToggleSubscription(data); }}>
+ {
+ data.subscribed ? (<>
+ <Icon name="ei-check" size="s" />
+ <span>Subscribed</span>
+ </>) : (<>
+ <Icon name="ei-eye" size="s" />
+ <span>Subscribe</span>
+ </>)}
+ </Link>
+ ) : (
+ <Link to={`/${data.user.uname}/${data.mid}`} className="a-comment msg-button"
+ state={{ data: data }}>
+ <Icon name="ei-comment" size="s" />
+ <span>{commentsSummary}</span>
+ </Link>
+ )
+ ))
+ }
</nav>
{children}
- </div>
+ </div >
);
}
diff --git a/vnext/src/ui/Thread.js b/vnext/src/ui/Thread.js
index de1d74b2..2919e830 100644
--- a/vnext/src/ui/Thread.js
+++ b/vnext/src/ui/Thread.js
@@ -6,7 +6,7 @@ import Message from './Message';
import MessageInput from './MessageInput';
import Spinner from './Spinner';
-import { getMessages, comment, update } from '../api';
+import { getMessages, comment, update, post } from '../api';
import { useVisitor } from './VisitorContext';
import { Helmet } from 'react-helmet';
/**
@@ -104,6 +104,26 @@ export default function Thread(props) {
const loaders = Math.min(message.replies || 0, 10);
const pageTitle = `${params.user} ${message && message.tags || 'thread'}`;
+ /** @type { import('./Message').ToggleSubscriptionCallback } */
+ const handleSubsciptionToggle = (message) => {
+ if (message.subscribed) {
+ if (confirm('Unsubscribe?')) {
+ post(`U #${message.mid}`).then((response) => {
+ if (response.status === 200) {
+ setMessage({...message, subscribed: false});
+ }
+ }).catch(console.error);
+ }
+ } else {
+ if (confirm('Subscribe?')) {
+ post(`S #${message.mid}`).then((response) => {
+ if (response.status === 200) {
+ setMessage({...message, subscribed: true});
+ }
+ }).catch(console.error);
+ }
+ }
+ };
return (
<>
<Helmet>
@@ -111,7 +131,7 @@ export default function Thread(props) {
</Helmet>
{
message.mid ? (
- <Message data={message}>
+ <Message key={message.mid} data={message} isThread={true} onToggleSubscription={handleSubsciptionToggle}>
{active === (message.rid || 0) && <MessageInput data={message} text={editing.body || ''} onSend={postComment}>Write a comment...</MessageInput>}
</Message>
) : (