• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Freegle / iznik-nuxt3 / ce5abe40-6f99-4088-a6e7-20c39d0d906f

28 Nov 2025 03:32PM UTC coverage: 43.578% (-2.3%) from 45.902%
ce5abe40-6f99-4088-a6e7-20c39d0d906f

push

circleci

edwh
Fix TestFlight version to be higher than production (99.0.x) and force update plugin

3135 of 7742 branches covered (40.49%)

Branch coverage included in aggregate %.

3417 of 7293 relevant lines covered (46.85%)

12.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/components/ChatMessageText.vue
1
<template>
2
  <div
3
    class="chatMessageWrapper"
4
    :class="{ myChatMessage: messageIsFromCurrentUser }"
5
  >
6
    <div class="chatMessage forcebreak chatMessage__owner">
7
      <div>
8
        <span v-if="!highlightEmails">
9
          <span v-if="messageIsNew" class="prewrap font-weight-bold">{{
×
10
            emessage
11
          }}</span>
12
          <span v-else class="preline forcebreak">{{ emessage }}</span>
×
13
          <b-img
14
            v-if="chatmessage?.image"
×
15
            fluid
16
            :src="chatmessage?.image.path"
17
            lazy
×
18
            rounded
19
          />
20
        </span>
21
        <span v-else>
×
22
          <span v-if="messageIsNew" class="font-weight-bold">
23
            <Highlighter
24
              :text-to-highlight="emessage"
25
              :search-words="[regexEmail]"
26
              highlight-class-name="highlight"
27
              class="prewrap"
×
28
            />
29
          </span>
30
          <span v-else>
31
            <Highlighter
32
              :text-to-highlight="emessage"
33
              :search-words="[regexEmail]"
34
              highlight-class-name="highlight"
35
              class="preline forcebreak"
36
            />
37
          </span>
38
          <b-img
39
            v-if="chatmessage?.image"
40
            fluid
41
            :src="chatmessage?.image.path"
×
42
            lazy
43
            rounded
44
          />
45
        </span>
46
      </div>
×
47
      <div v-if="lat || lng">
48
        <l-map
49
          ref="map"
50
          :zoom="16"
51
          :max-zoom="maxZoom"
52
          :center="[lat, lng]"
×
53
          :style="'width: 100%; height: 200px'"
54
        >
55
          <l-tile-layer :url="osmtile()" :attribution="attribution()" />
56
          <l-marker :lat-lng="[lat, lng]" :interactive="false" />
57
        </l-map>
58
        <div class="small text-muted">
59
          (Map shows approximate location of {{ postcode }})
60
        </div>
61
      </div>
62
    </div>
63
    <div class="chatMessageProfilePic">
64
      <ProfileImage
65
        :image="chatMessageProfileImage"
66
        class="ml-1 mb-1 mt-1 inline"
67
        is-thumbnail
68
        size="sm"
69
      />
70
    </div>
71
  </div>
72
</template>
73
<script setup>
74
import Highlighter from 'vue-highlight-words'
75
import { useChatMessageBase } from '~/composables/useChat'
76
import { ref, computed, onMounted } from '#imports'
77
import ProfileImage from '~/components/ProfileImage'
78
import { MAX_MAP_ZOOM, POSTCODE_REGEX } from '~/constants'
79
import { attribution, osmtile } from '~/composables/useMap'
80
import { useLocationStore } from '~/stores/location'
81

82
const props = defineProps({
83
  chatid: {
84
    type: Number,
85
    required: true,
86
  },
87
  id: {
88
    type: Number,
×
89
    required: true,
90
  },
91
  pov: {
92
    type: Number,
93
    required: false,
94
    default: null,
95
  },
96
  highlightEmails: {
97
    type: Boolean,
98
    required: false,
99
    default: false,
100
  },
101
})
102

103
// Use properties from ChatBase component via composable
104
const {
105
  chat,
106
  chatmessage,
107
  emessage,
108
  messageIsFromCurrentUser,
109
  chatMessageProfileImage,
110
  regexEmail,
×
111
} = useChatMessageBase(props.chatid, props.id, props.pov)
112

113
// Data properties
114
const lat = ref(null)
115
const lng = ref(null)
116

117
// Computed properties
118
const maxZoom = computed(() => MAX_MAP_ZOOM)
119

120
const messageIsNew = computed(() => {
×
121
  return (
×
122
    chatmessage.value?.secondsago < 60 ||
×
123
    chatmessage.value?.id > chat.value?.lastmsgseen
×
124
  )
125
})
126

×
127
const postcode = computed(() => {
×
128
  let ret = null
129

×
130
  const postcodeMatch = chatmessage.value?.message.match(POSTCODE_REGEX)
×
131

×
132
  if (postcodeMatch?.length) {
133
    if (!postcodeMatch[0].includes(' ')) {
134
      // Make sure we have a space in the right place, because this helps with autocomplete
135
      ret = postcodeMatch[0].replace(/^(.*)(\d)/, '$1 $2')
136
    } else {
137
      ret = postcodeMatch[0]
×
138
    }
×
139
  }
×
140

×
141
  return ret
×
142
})
×
143

×
144
// Lifecycle hooks
×
145
onMounted(async () => {
×
146
  if (postcode.value) {
×
147
    // Use typeahead to find the postcode location.
148
    const locationStore = useLocationStore()
×
149
    const locs = await locationStore.typeahead(postcode.value)
150

151
    if (locs?.length) {
×
152
      lat.value = locs[0].lat
153
      lng.value = locs[0].lng
×
154
    }
×
155
  }
×
156
})
×
157
</script>
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc