Newer
Older
navi-1 / webclient / src / components / messages / UserMessage.vue
<template>
  <div class="msg-user" :class="{ 'msg-user--recall': msg.isRecall }">
    <div class="msg-user-wrap">
      <div class="msg-user-bubble" :class="{ 'msg-flash': props.isFlashing }">
        <div v-if="msg.isRecall" class="msg-recall-badge">
          <i class="ph ph-clock"></i>
          <span>Scheduled recall</span>
        </div>
        <div class="msg-user-text" v-html="renderUserText(msg.text)"></div>
        <div v-if="msg.images?.length || msg.files?.length" class="msg-user-attachments">
          <img
            v-for="(src, i) in msg.images"
            :key="`img-${i}`"
            :src="src"
            class="msg-user-image"
            @click="openImage(src)"
          />
          <span
            v-for="(file, i) in msg.files"
            :key="`file-${i}`"
            class="msg-user-file-pill"
          >
            <i class="ph ph-file"></i>
            {{ file.name }}
          </span>
        </div>
      </div>
      <div class="msg-user-footer">
        <span v-if="msgTime" class="msg-time msg-time--user">{{ msgTime }}</span>
        <GnIconButton
          :icon="copied ? 'ph ph-check' : 'ph ph-copy'"
          :label="copied ? 'Copied!' : 'Copy'"
          class="msg-copy-btn"
          @click="copy(msg.text)"
        />
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { useTimeLabel } from '@/composables/useTime.js'
import { useLightbox } from '@/composables/useLightbox.js'
import { useCopy } from '@/composables/useCopy.js'

const props = defineProps({
  msg: { type: Object, required: true },
  isFlashing: { type: Boolean, default: false }
})

const tsRef = computed(() => props.msg.time)
const msgTime = useTimeLabel(tsRef)

const { open: openImage } = useLightbox()
const { copied, copy } = useCopy()

function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
}

function renderUserText(text) {
  if (!text) return ''
  const lines = text.split('\n')
  let quoteLines = []
  let textLines = []

  for (const line of lines) {
    if (line.startsWith('> ')) {
      quoteLines.push(escapeHtml(line.slice(2)))
    } else if (line.trim()) {
      textLines.push(escapeHtml(line))
    }
  }

  const quote = quoteLines.length
    ? `<blockquote class="msg-user-quote">${quoteLines.join('<br>')}</blockquote>`
    : ''
  const body = textLines.join(' ')
  return quote + body
}
</script>