Quoted message
This commit is contained in:
parent
f53513f37f
commit
072213fcc0
|
@ -40,6 +40,9 @@ const Message = (props: Props) => {
|
||||||
<div innerHTML={md.render(props.content.body)} />
|
<div innerHTML={md.render(props.content.body)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Show when={props.content.replyTo}>
|
||||||
|
<small>Repl to {props.content.replyTo}</small>
|
||||||
|
</Show>
|
||||||
<div class={styles.time}>{formattedTime(props.content.createdAt)}</div>
|
<div class={styles.time}>{formattedTime(props.content.createdAt)}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
33
src/components/Inbox/QuotedMessage.module.scss
Normal file
33
src/components/Inbox/QuotedMessage.module.scss
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
.QuotedMessage {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
border-top: 2px solid #ccc;
|
||||||
|
padding: 12px 0;
|
||||||
|
gap: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
&.cancel {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.author {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/components/Inbox/QuotedMessage.tsx
Normal file
33
src/components/Inbox/QuotedMessage.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Show } from 'solid-js'
|
||||||
|
import styles from './QuotedMessage.module.scss'
|
||||||
|
import { Icon } from '../_shared/Icon'
|
||||||
|
import { clsx } from 'clsx'
|
||||||
|
|
||||||
|
type QuotedMessage = {
|
||||||
|
body: string
|
||||||
|
cancel?: () => void
|
||||||
|
author?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const QuotedMessage = (props: QuotedMessage) => {
|
||||||
|
return (
|
||||||
|
<div class={styles.QuotedMessage}>
|
||||||
|
<div class={styles.icon}>
|
||||||
|
<Icon name="chat-reply" />
|
||||||
|
</div>
|
||||||
|
<div class={styles.body}>
|
||||||
|
<Show when={props.author}>
|
||||||
|
<div class={styles.author}>{props.author}</div>
|
||||||
|
</Show>
|
||||||
|
<div class={styles.quote}>{props.body}</div>
|
||||||
|
</div>
|
||||||
|
<Show when={props.cancel}>
|
||||||
|
<div class={clsx(styles.cancel, styles.icon)} onClick={props.cancel}>
|
||||||
|
<Icon name="close-gray" />
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default QuotedMessage
|
|
@ -17,6 +17,7 @@ import MessagesFallback from '../Inbox/MessagesFallback'
|
||||||
import { useRouter } from '../../stores/router'
|
import { useRouter } from '../../stores/router'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import styles from '../../styles/Inbox.module.scss'
|
import styles from '../../styles/Inbox.module.scss'
|
||||||
|
import QuotedMessage from '../Inbox/QuotedMessage'
|
||||||
|
|
||||||
const userSearch = (array: Author[], keyword: string) => {
|
const userSearch = (array: Author[], keyword: string) => {
|
||||||
const searchTerm = keyword.toLowerCase()
|
const searchTerm = keyword.toLowerCase()
|
||||||
|
@ -79,10 +80,12 @@ export const InboxView = () => {
|
||||||
try {
|
try {
|
||||||
const post = await apiClient.createMessage({
|
const post = await apiClient.createMessage({
|
||||||
body: postMessageText().toString(),
|
body: postMessageText().toString(),
|
||||||
chat: currentDialog().id.toString()
|
chat: currentDialog().id.toString(),
|
||||||
|
replyTo: messageToReply()?.id
|
||||||
})
|
})
|
||||||
setMessages((prev) => [...prev, post.message])
|
setMessages((prev) => [...prev, post.message])
|
||||||
setPostMessageText('')
|
setPostMessageText('')
|
||||||
|
setMessageToReply(null)
|
||||||
chatWindow.scrollTop = chatWindow.scrollHeight
|
chatWindow.scrollTop = chatWindow.scrollHeight
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[post message error]:', error)
|
console.error('[post message error]:', error)
|
||||||
|
@ -98,10 +101,10 @@ export const InboxView = () => {
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
const params = Object.fromEntries(urlParams)
|
const params = Object.fromEntries(urlParams)
|
||||||
createEffect(async () => {
|
createEffect(async () => {
|
||||||
console.log('!!! postMessageText:', postMessageText())
|
|
||||||
if (textareaParent) {
|
if (textareaParent) {
|
||||||
textareaParent.dataset.replicatedValue = postMessageText()
|
textareaParent.dataset.replicatedValue = postMessageText()
|
||||||
}
|
}
|
||||||
|
console.log('!!! messages:', messages())
|
||||||
if (params['initChat']) {
|
if (params['initChat']) {
|
||||||
try {
|
try {
|
||||||
const newChat = await actions.createChat([Number(params['initChat'])], '')
|
const newChat = await actions.createChat([Number(params['initChat'])], '')
|
||||||
|
@ -231,24 +234,14 @@ export const InboxView = () => {
|
||||||
|
|
||||||
<div class={styles.messageForm}>
|
<div class={styles.messageForm}>
|
||||||
<Show when={messageToReply()}>
|
<Show when={messageToReply()}>
|
||||||
<div class={styles.reply}>
|
<QuotedMessage
|
||||||
<div class={styles.icon}>
|
author={
|
||||||
<Icon name="chat-reply" />
|
currentDialog().members.find((member) => member.id === Number(messageToReply().author))
|
||||||
</div>
|
.name
|
||||||
<div class={styles.body}>
|
}
|
||||||
<div class={styles.author}>
|
body={messageToReply().body}
|
||||||
{
|
cancel={() => setMessageToReply(undefined)}
|
||||||
currentDialog().members.find(
|
/>
|
||||||
(member) => member.id === Number(messageToReply().author)
|
|
||||||
).name
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class={styles.quote}>{messageToReply().body}</div>
|
|
||||||
</div>
|
|
||||||
<div class={clsx(styles.cancel, styles.icon)} onClick={() => setMessageToReply(null)}>
|
|
||||||
<Icon name="close-gray" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Show>
|
</Show>
|
||||||
<div class={styles.wrapper}>
|
<div class={styles.wrapper}>
|
||||||
<div class={styles.growWrap} ref={textareaParent}>
|
<div class={styles.growWrap} ref={textareaParent}>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { gql } from '@urql/core'
|
import { gql } from '@urql/core'
|
||||||
|
|
||||||
export default gql`
|
export default gql`
|
||||||
mutation createMessage($chat: String!, $body: String!) {
|
mutation createMessage($chat: String!, $body: String!, $replyTo: Int) {
|
||||||
createMessage(chat: $chat, body: $body) {
|
createMessage(chat: $chat, body: $body, replyTo: $replyTo) {
|
||||||
error
|
error
|
||||||
message {
|
message {
|
||||||
id
|
id
|
||||||
|
|
|
@ -131,40 +131,6 @@ main {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 2px 0 12px;
|
padding: 2px 0 12px;
|
||||||
|
|
||||||
.reply {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
border-top: 2px solid #ccc;
|
|
||||||
padding: 12px 0;
|
|
||||||
gap: 12px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
|
|
||||||
&.cancel {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
flex-grow: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.author {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quote {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
border: 2px solid #ccc;
|
border: 2px solid #ccc;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user