Skip to content

Commit

Permalink
feat(chat): message replies
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonwoodland committed Aug 2, 2022
1 parent a5a41a1 commit fdd80f4
Show file tree
Hide file tree
Showing 24 changed files with 210 additions and 280 deletions.
9 changes: 3 additions & 6 deletions components/views/chat/chatbar/Chatbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const Chatbar = Vue.extend({
isSharpCorners(): boolean {
return (
Boolean(this.files.length) ||
Boolean(this.ui.replyChatbarContent.id) ||
Boolean(this.ui.replyChatbarMessage) ||
this.commandPreview ||
this.chat.countError
)
Expand Down Expand Up @@ -133,11 +133,7 @@ const Chatbar = Vue.extend({
handler(value) {
const message = this.chat.draftMessages[this.conversationId]
this.$refs.editable?.resetHistory()
this.$store.commit('ui/setReplyChatbarContent', {
id: '',
payload: '',
from: '',
})
this.$store.commit('ui/clearReplyChatbarMessage')
this.$store.dispatch('ui/setChatbarContent', { content: message })
// in desktop, stay chatbar focused when switching recipient
if (this.$device.isDesktop) {
Expand Down Expand Up @@ -228,6 +224,7 @@ const Chatbar = Vue.extend({
body: value,
at: Date.now(),
attachments: [],
replyToId: this.ui.replyChatbarMessage.id,
})
// if (
// this.ui.replyChatbarContent.from &&
Expand Down
6 changes: 3 additions & 3 deletions components/views/chat/chatbar/reply/Reply.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div v-if="ui.replyChatbarContent.id" class="is-chatbar-reply">
<div v-if="ui.replyChatbarMessage" class="is-chatbar-reply">
<div class="markdown">
{{ $t('conversation.reply_to') }}
<strong>{{ ui.replyChatbarContent.from }}</strong>
<strong>{{ ui.replyChatbarMessage.from }}</strong>
</div>
<div class="reply-close" @click="setReplyChatbarContent">
<div class="reply-close" @click="clearReplyChatbarMessage">
<x-icon size="1x" />
</div>
</div>
13 changes: 2 additions & 11 deletions components/views/chat/chatbar/reply/Reply.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,8 @@ export default Vue.extend({
...mapState(['ui']),
},
methods: {
/**
* @method setReplyChatbarContent
* @description Adds message reply by committing chatbar content to setReplyChatbarContent in state
* @example @click="setReplyChatbarContent"
*/
setReplyChatbarContent() {
this.$store.commit('ui/setReplyChatbarContent', {
id: '',
payload: '',
from: '',
})
clearReplyChatbarMessage() {
this.$store.commit('ui/clearReplyChatbarMessage')
},
},
})
Expand Down
3 changes: 2 additions & 1 deletion components/views/chat/conversation/Conversation.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
/>
<UiCaretDivider v-if="item.isFirstUnreadMessage" text="New Messages" />
<Message
:message="item.message"
:key="item.message.id"
:message="item.message"
:showHeader="!item.isSameAuthor"
:replies="item.replies"
/>
</template>
</div>
Expand Down
51 changes: 30 additions & 21 deletions components/views/chat/conversation/Conversation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface ChatItem {
timeDiff: number
isNextDay: boolean
isFirstUnreadMessage: boolean
replies: (ConversationMessage & { id: string })[]
}
export default Vue.extend({
Expand All @@ -29,28 +30,36 @@ export default Vue.extend({
return iridium.connector?.id ?? ''
},
chatItems(): ChatItem[] {
return this.messages.map((message, index) => {
const prevMessage = index >= 0 ? this.messages[index - 1] : undefined
const isSameAuthor = prevMessage
? message.from === prevMessage.from
: false
const timeDiff = prevMessage ? message.at - prevMessage.at : 0
const isNextDay = prevMessage
? !this.$dayjs(prevMessage.at).isSame(message.at, 'day')
: false
const lastReadAt = this.conversation.lastReadAt
const isFirstUnreadMessage =
message.at > lastReadAt &&
(prevMessage ? prevMessage.at <= lastReadAt : true)
return this.messages
.filter((message) => message.replyToId)
.map((message, index) => {
const prevMessage = index >= 0 ? this.messages[index - 1] : undefined
const isSameAuthor = prevMessage
? message.from === prevMessage.from
: false
const timeDiff = prevMessage ? message.at - prevMessage.at : 0
const isNextDay = prevMessage
? !this.$dayjs(prevMessage.at).isSame(message.at, 'day')
: false
const lastReadAt = this.conversation.lastReadAt
const isFirstUnreadMessage =
message.at > lastReadAt &&
(prevMessage ? prevMessage.at <= lastReadAt : true)
const replies = this.messages.filter(
(replyMessage) => replyMessage.replyToId === message.id,
)
return {
message,
isSameAuthor,
timeDiff,
isNextDay,
isFirstUnreadMessage,
}
})
console.log('replies', replies)
return {
message,
isSameAuthor,
timeDiff,
isNextDay,
isFirstUnreadMessage,
replies,
}
})
},
},
methods: {},
Expand Down
92 changes: 45 additions & 47 deletions components/views/chat/message/Message.html
Original file line number Diff line number Diff line change
@@ -1,52 +1,50 @@
<UiContextMenu
class="chat-message"
:class="{ 'show-header': showHeader }"
:items="contextMenuValues"
>
<template v-if="showHeader">
<div class="avatar">
<UiCircle
:type="author.src ? 'image' :'random'"
:seed="author.id"
:source="author.src"
<UiContextMenu class="chat-message-container" :items="contextMenuValues">
<div
class="chat-message"
:class="{ 'show-header': showHeader, 'is-replying-to': isReplyingTo }"
>
<template v-if="showHeader">
<div class="avatar">
<UiCircle
:type="author.src ? 'image' :'random'"
:seed="author.id"
:source="author.src"
/>
</div>
<div class="header">
<span :click="showQuickProfile">
<UiUserName :username="author.name" />
</span>
</div>
</template>
<div class="timestamp">{{ timestamp }}</div>
<div class="body">
<MessageMarkdown
:text="wrapEmoji(markdownToHtml(message.body))"
class="markdown"
:class="{ bigmoji: containsOnlyEmoji(message.body) }"
data-cy="chat-message"
/>
</div>
<div class="header">
<span :click="showQuickProfile">
<UiUserName :username="author.name" />
<span class="status editing" v-if="message.editingAt">
<UiLoadersSpinner spinning />
</span>
<span
class="status edited"
data-cy="message-edited"
v-else-if="message.editedAt"
>
({{$t('ui.edited')}})
</span>
<MessageActions
:setReplyChatbarMessage="setReplyChatbarMessage"
:emojiReaction="emojiReaction"
:editMessage="editMessage"
:message="message"
/>
</div>
<div class="footer">
<MessageReactions :message="message" :emojiReaction="emojiReaction" />
<MessageReply :replies="replies" />
</div>
</template>
<div class="timestamp">{{ timestamp }}</div>
<div class="body">
<MessageMarkdown
v-if="message.body"
:text="wrapEmoji(markdownToHtml(message.body))"
class="markdown"
:class="{ bigmoji: containsOnlyEmoji(message.body) }"
data-cy="chat-message"
/>
<span class="status editing" v-if="message.editingAt">
<UiLoadersSpinner spinning />
</span>
<span
class="status edited"
data-cy="message-edited"
v-else-if="message.editedAt"
>
({{$t('ui.edited')}})
</span>
<MessageGlyph
v-if="message.glyph"
:source="message.glyph.src"
:pack="message.glyph.pack"
/>
<MessageActions
:setReplyChatbarContent="setReplyChatbarContent"
:emojiReaction="emojiReaction"
:editMessage="editMessage"
:message="message"
/>
<MessageReactions :message="message" :emojiReaction="emojiReaction" />
</div>
</UiContextMenu>
24 changes: 20 additions & 4 deletions components/views/chat/message/Message.less
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,18 @@
.chat-message {
display: grid;
text-align: left;
// border-left: 3px solid transparent;
padding-left: @xlight-spacing;

&.is-replying-to {
background-color: fade(@satellite-color, 10%);
// border-left-color: @satellite-color;
}

&:not(.show-header) {
grid-template-areas: 'timestamp body';
grid-template-areas:
'timestamp body'
'timestamp footer';
grid-template-columns: 52px;

.timestamp {
Expand All @@ -35,7 +44,8 @@
&.show-header {
grid-template-areas:
'avatar header timestamp'
'avatar body body';
'avatar body body'
'avatar footer footer';
grid-template-columns: 52px auto 1fr;
margin-top: @normal-spacing;

Expand Down Expand Up @@ -77,8 +87,14 @@
}
}

&:hover {
.body {
.footer {
grid-area: footer;
background: none;
padding: 0;
}

&:not(.is-replying-to):hover {
> .body > .markdown {
&:extend(.background-semitransparent-light);
}

Expand Down
41 changes: 11 additions & 30 deletions components/views/chat/message/Message.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
<script lang="ts">
import Vue, { PropType } from 'vue'
import { mapState, mapGetters } from 'vuex'
import { ArchiveIcon } from 'satellite-lucide-icons'
import { UIMessage, Group } from '~/types/messaging'
import { toHTML } from '~/libraries/ui/Markdown'
import { ContextMenuItem, EmojiUsage, ModalWindows } from '~/store/ui/types'
import { isMimeEmbeddableImage } from '~/utilities/FileType'
Expand All @@ -23,7 +20,11 @@ export default Vue.extend({
},
props: {
message: {
type: Object as PropType<ConversationMessage>,
type: Object as PropType<ConversationMessage & { id: string }>,
required: true,
},
replies: {
type: Array as PropType<(ConversationMessage & { id: string })[]>,
required: true,
},
showHeader: {
Expand Down Expand Up @@ -67,6 +68,9 @@ export default Vue.extend({
// }
// return this.groups[this.conversation.id]
},
isReplyingTo(): boolean {
return this.ui.replyChatbarMessage?.id === this.message.id
},
timestamp(): string {
return this.getTimestamp({ time: this.message.at })
},
Expand All @@ -80,7 +84,7 @@ export default Vue.extend({
const mainList = [
{ text: 'quickReaction', func: this.quickReaction },
{ text: this.$t('context.reaction'), func: this.emojiReaction },
{ text: this.$t('context.reply'), func: this.setReplyChatbarContent },
{ text: this.$t('context.reply'), func: this.setReplyChatbarMessage },
// AP-1120 copy link functionality
// { text: this.$t('context.copy_link'), func: (this as any).testFunc },
]
Expand Down Expand Up @@ -239,31 +243,8 @@ export default Vue.extend({
}
})
},
/**
* @method setReplyChatbarContent DocsTODO
* @description
* @example
*/
setReplyChatbarContent() {
if (this.isGroup) {
this.toggleModal(ModalWindows.CALL_TO_ACTION)
return
}
const myTextilePublicKey = this.$TextileManager.getIdentityPublicKey()
const { id, type, payload, to, from } = this.message
let finalPayload = payload
if (['image', 'video', 'audio', 'file'].includes(type)) {
finalPayload = `*${this.$t('conversation.multimedia')}*`
} else if (type === 'glyph') {
finalPayload = `<img src=${payload} width='16px' height='16px' />`
}
this.$store.commit('ui/setReplyChatbarContent', {
id,
payload: finalPayload,
from: this.from,
messageID: this.message.id,
to: to === myTextilePublicKey ? from : to,
})
setReplyChatbarMessage() {
this.$store.commit('ui/setReplyChatbarMessage', this.message)
this.$nextTick(() => this.$store.dispatch('ui/setChatbarFocus'))
},
/**
Expand Down
2 changes: 1 addition & 1 deletion components/views/chat/message/actions/Actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class="reply-command"
:class="{'coming-soon': isGroup}"
v-tooltip.top="$t(isGroup ? 'ui.coming_soon' : 'messaging.reply')"
@click="setReplyChatbarContent"
@click="setReplyChatbarMessage"
>
<corner-down-right-icon size="1x" :class="'control-icon'" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/views/chat/message/actions/Actions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default Vue.extend({
MoreVerticalIcon,
},
props: {
setReplyChatbarContent: {
setReplyChatbarMessage: {
type: Function,
default: () => () => {},
},
Expand Down
Loading

0 comments on commit fdd80f4

Please sign in to comment.