import { computed, onMounted, onUnmounted, ref } from 'vue'
import { locale, t } from '@/i18n/index.js'
/**
* Format a timestamp as a relative/short label (same logic as old client).
* < 1 min → "just now"
* < 1 hour → "5 min ago"
* today → "14:32"
* older → "12.04.2024"
*/
export function formatTimeLabel(ts) {
if (!ts) return ''
const d = new Date(ts)
if (isNaN(d)) return ''
const diff = Date.now() - d
if (diff < 60_000) return t('common.justNow')
if (diff < 3_600_000) return t('common.minutesAgo', { n: Math.floor(diff / 60_000) })
if (diff < 86_400_000) return d.toLocaleTimeString(locale.value, { hour: '2-digit', minute: '2-digit' })
return d.toLocaleDateString(locale.value)
}
// One clock for every label on screen. Each useTimeLabel() used to install its
// own setInterval: a sidebar of 30 sessions plus every message timestamp meant
// dozens of timers waking independently. They all read the same "now", so one
// shared ticker is enough; it runs only while at least one label is mounted.
const now = ref(Date.now())
let timer = null
let subscribers = 0
function subscribe() {
subscribers++
if (subscribers === 1) {
now.value = Date.now()
timer = setInterval(() => { now.value = Date.now() }, 30_000)
}
}
function unsubscribe() {
subscribers = Math.max(0, subscribers - 1)
if (subscribers === 0 && timer) {
clearInterval(timer)
timer = null
}
}
/**
* Reactive time label that auto-updates every 30 s.
* Returns a computed that ticks so "5 min ago" stays current. It also tracks
* the interface language: formatTimeLabel() reads locale, so a language change
* recomputes every label without a separate watcher.
*/
export function useTimeLabel(tsRef) {
const label = computed(() => {
now.value // register the shared ticker as a dependency
return formatTimeLabel(tsRef.value)
})
onMounted(subscribe)
onUnmounted(unsubscribe)
return label
}