+
+ {name}
-
- { !contentOnly && (
-
-
- {name}
-
-
- {time}
-
-
- )}
-
- { reply !== null && (
-
-
-
- {reply.to}
- <>{` ${reply.content}`}>
-
-
- )}
-
- { markdown ? genMarkdown(content) : linkifyContent(content) }
-
- { edited &&
(edited)}
- { reactions && (
-
- {
- reactions.map((reaction) => (
-
- ))
- }
-
- )}
-
+
+ {time}
);
}
+MessageHeader.propTypes = {
+ userId: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
+ color: PropTypes.string.isRequired,
+ time: PropTypes.string.isRequired,
+};
+function MessageReply({
+ userId, name, color, content,
+}) {
+ return (
+
+
+
+ {name}
+ <>{` ${content}`}>
+
+
+ );
+}
+
+MessageReply.propTypes = {
+ userId: PropTypes.string.isRequired,
+ name: PropTypes.string.isRequired,
+ color: PropTypes.string.isRequired,
+ content: PropTypes.string.isRequired,
+};
+
+function MessageContent({ content, isMarkdown, isEdited }) {
+ return (
+
+
+ { isMarkdown ? genMarkdown(content) : linkifyContent(content) }
+
+ { isEdited &&
(edited)}
+
+ );
+}
+MessageContent.defaultProps = {
+ isMarkdown: false,
+ isEdited: false,
+};
+MessageContent.propTypes = {
+ content: PropTypes.node.isRequired,
+ isMarkdown: PropTypes.bool,
+ isEdited: PropTypes.bool,
+};
+
+function MessageReactionGroup({ children }) {
+ return (
+
+ { children }
+
+ );
+}
+MessageReactionGroup.propTypes = {
+ children: PropTypes.node.isRequired,
+};
+
+function genReactionMsg(userIds, reaction) {
+ let msg = '';
+ userIds.forEach((userId, index) => {
+ if (index === 0) msg += getUsername(userId);
+ else if (index === userIds.length - 1) msg += ` and ${getUsername(userId)}`;
+ else msg += `, ${getUsername(userId)}`;
+ });
+ return (
+ <>
+ {`${msg} reacted with`}
+ {parse(twemoji.parse(reaction))}
+ >
+ );
+}
+
+function MessageReaction({
+ reaction, users, isActive, onClick,
+}) {
+ return (
+
{genReactionMsg(users, reaction)}}
+ >
+
+
+ );
+}
+MessageReaction.propTypes = {
+ reaction: PropTypes.node.isRequired,
+ users: PropTypes.arrayOf(PropTypes.string).isRequired,
+ isActive: PropTypes.bool.isRequired,
+ onClick: PropTypes.func.isRequired,
+};
+
+function Message({
+ avatar, header, reply, content, reactions,
+}) {
+ const msgClass = header === null ? ' message--content-only' : ' message--full';
+ return (
+
+
+ {avatar !== null && avatar}
+
+
+ {header !== null && header}
+ {reply !== null && reply}
+ {content}
+ {reactions !== null && reactions}
+
+
+ );
+}
Message.defaultProps = {
- color: 'var(--tc-surface-high)',
- avatarSrc: null,
- markdown: false,
- contentOnly: false,
+ avatar: null,
+ header: null,
reply: null,
- edited: false,
reactions: null,
};
-
Message.propTypes = {
- color: PropTypes.string,
- avatarSrc: PropTypes.string,
- name: PropTypes.string.isRequired,
+ avatar: PropTypes.node,
+ header: PropTypes.node,
+ reply: PropTypes.node,
content: PropTypes.node.isRequired,
- time: PropTypes.string.isRequired,
- markdown: PropTypes.bool,
- contentOnly: PropTypes.bool,
- reply: PropTypes.shape({
- color: PropTypes.string.isRequired,
- to: PropTypes.string.isRequired,
- content: PropTypes.string.isRequired,
- }),
- edited: PropTypes.bool,
- reactions: PropTypes.arrayOf(PropTypes.exact({
- id: PropTypes.string,
- key: PropTypes.string,
- count: PropTypes.number,
- active: PropTypes.bool,
- })),
+ reactions: PropTypes.node,
};
-export { Message as default, PlaceholderMessage };
+export {
+ Message,
+ MessageHeader,
+ MessageReply,
+ MessageContent,
+ MessageReactionGroup,
+ MessageReaction,
+ PlaceholderMessage,
+};
diff --git a/src/app/molecules/message/Message.scss b/src/app/molecules/message/Message.scss
index a1c7bbc5..f8a4108d 100644
--- a/src/app/molecules/message/Message.scss
+++ b/src/app/molecules/message/Message.scss
@@ -49,24 +49,9 @@
&__avatar-container {
width: var(--av-small);
}
- &__reply-content {
- .text {
- color: var(--tc-surface-low);
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- .ic-raw {
- width: 16px;
- height: 14px;
- }
- }
&__edited {
color: var(--tc-surface-low);
}
- &__reactions {
- margin-top: var(--sp-ultra-tight);
- }
}
.ph-msg {
@@ -106,6 +91,13 @@
}
}
+.message__reply,
+.message__content,
+.message__reactions {
+ max-width: 640px;
+}
+
+
.message__header {
display: flex;
align-items: baseline;
@@ -130,8 +122,19 @@
}
}
}
+.message__reply {
+ .text {
+ color: var(--tc-surface-low);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .ic-raw {
+ width: 16px;
+ height: 14px;
+ }
+}
.message__content {
- max-width: 640px;
word-break: break-word;
& > .text > * {
@@ -142,20 +145,36 @@
word-break: break-all;
}
}
+.message__reactions {
+ display: flex;
+}
.msg__reaction {
- --reaction-height: 24px;
- --reaction-padding: 6px;
- --reaction-radius: calc(var(--bo-radius) / 2);
+ margin: var(--sp-extra-tight) var(--sp-extra-tight) 0 0;
+ padding: 0 var(--sp-ultra-tight);
+ min-height: 26px;
display: inline-flex;
align-items: center;
color: var(--tc-surface-normal);
+ background-color: var(--bg-surface-low);
border: 1px solid var(--bg-surface-border);
- padding: 0 var(--reaction-padding);
- border-radius: var(--reaction-radius);
+ border-radius: 4px;
cursor: pointer;
- height: var(--reaction-height);
- margin-right: var(--sp-extra-tight);
+ & .emoji {
+ width: 14px;
+ height: 14px;
+ margin: 2px;
+ }
+ &-count {
+ margin: 0 var(--sp-ultra-tight);
+ color: var(--tc-surface-normal)
+ }
+ &-tooltip .emoji {
+ width: 14px;
+ height: 14px;
+ margin: 0 var(--sp-ultra-tight);
+ margin-bottom: -2px;
+ }
[dir=rtl] & {
margin: {
@@ -188,7 +207,7 @@
}
// markdown formating
-.message {
+.message__content {
& h1,
& h2 {
color: var(--tc-surface-high);
diff --git a/src/app/organisms/channel/ChannelViewContent.jsx b/src/app/organisms/channel/ChannelViewContent.jsx
index 2fdf1e24..4476b43f 100644
--- a/src/app/organisms/channel/ChannelViewContent.jsx
+++ b/src/app/organisms/channel/ChannelViewContent.jsx
@@ -12,7 +12,16 @@ import colorMXID from '../../../util/colorMXID';
import { diffMinutes, isNotInSameDay } from '../../../util/common';
import Divider from '../../atoms/divider/Divider';
-import Message, { PlaceholderMessage } from '../../molecules/message/Message';
+import Avatar from '../../atoms/avatar/Avatar';
+import {
+ Message,
+ MessageHeader,
+ MessageReply,
+ MessageContent,
+ MessageReactionGroup,
+ MessageReaction,
+ PlaceholderMessage,
+} from '../../molecules/message/Message';
import * as Media from '../../molecules/media/Media';
import ChannelIntro from '../../molecules/channel-intro/ChannelIntro';
import TimelineChange from '../../molecules/message/TimelineChange';
@@ -224,6 +233,7 @@ function ChannelViewContent({
if (parsedContent !== null) {
const username = getUsername(parsedContent.userId);
reply = {
+ userId: parsedContent.userId,
color: colorMXID(parsedContent.userId),
to: username,
content: parsedContent.replyContent,
@@ -259,9 +269,10 @@ function ChannelViewContent({
if (alreadyHaveThisReaction(rEvent)) {
for (let i = 0; i < reactions.length; i += 1) {
if (reactions[i].key === rEvent.getRelation().key) {
- reactions[i].count += 1;
- if (reactions[i].active !== true) {
- reactions[i].active = rEvent.getSender() === initMatrix.matrixClient.getUserId();
+ reactions[i].users.push(rEvent.getSender());
+ if (reactions[i].isActive !== true) {
+ const myUserId = initMatrix.matrixClient.getUserId();
+ reactions[i].isActive = rEvent.getSender() === myUserId;
}
break;
}
@@ -270,46 +281,70 @@ function ChannelViewContent({
reactions.push({
id: rEvent.getId(),
key: rEvent.getRelation().key,
- count: 1,
- active: (rEvent.getSender() === initMatrix.matrixClient.getUserId()),
+ users: [rEvent.getSender()],
+ isActive: (rEvent.getSender() === initMatrix.matrixClient.getUserId()),
});
}
});
}
+ const userMXIDColor = colorMXID(mEvent.sender.userId);
+ const userAvatar = isContentOnly ? null : (
+
+ );
+ const userHeader = isContentOnly ? null : (
+
+ );
+ const userReply = reply === null ? null : (
+
+ );
+ const userContent = (
+
+ );
+ const userReactions = reactions === null ? null : (
+
+ {
+ reactions.map((reaction) => (
+ alert('Sending reactions is yet to be implemented.')}
+ />
+ ))
+ }
+
+ );
+
const myMessageEl = (
-
- {divider}
- { isMedia(mEvent) ? (
-
- ) : (
-
- )}
-
+
);
prevMEvent = mEvent;