Newer
Older
navi-1 / webclient / src / components / messages / UserMessage.vue
<template>
  <div class="msg-user">
    <div class="msg-user-wrap">
      <div class="msg-user-bubble">
        <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>
        <button class="btn-icon msg-copy-btn" :title="copied ? 'Copied!' : 'Copy'" @click="copy(msg.text)">
          <i :class="copied ? 'ph ph-check' : 'ph ph-copy'"></i>
        </button>
      </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 } })

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>