mirror of
https://github.com/ArthurDanjou/artsite.git
synced 2026-01-14 18:59:59 +01:00
- Updated '@iconify-json/lucide' dependency to version 1.2.35 in package.json and pnpm-lock.yaml for compatibility. - Enhanced stateWord logic in Activity component to handle cases where the state string may be empty, ensuring it defaults to 'secret' when necessary.
191 lines
5.9 KiB
Vue
191 lines
5.9 KiB
Vue
<script lang="ts" setup>
|
|
import type { UseTimeAgoMessages } from '@vueuse/core'
|
|
import type { Activity } from '~~/types'
|
|
import { activityMessages, IDEs } from '~~/types'
|
|
|
|
const { t } = useI18n({
|
|
useScope: 'local',
|
|
})
|
|
|
|
const { data: activity, refresh } = await useAsyncData<Activity>('activity', () => $fetch<Activity>('/api/activity'))
|
|
|
|
useIntervalFn(async () => await refresh(), 5000)
|
|
const codingActivity = computed(() => {
|
|
const activities = activity.value!.data.activities.filter(activity => IDEs.some(ide => ide.name === activity.name)).map(activity => ({
|
|
...activity,
|
|
name: activity.assets?.small_text === 'Cursor' ? 'Cursor' : activity.name,
|
|
}))
|
|
|
|
return activities.length > 1
|
|
? activities[Math.floor(Math.random() * activities.length)]
|
|
: activities[0]
|
|
})
|
|
|
|
const { locale, locales } = useI18n()
|
|
const currentLocale = computed(() => locales.value.find(l => l.code === locale.value))
|
|
|
|
const isActive = computed(() => {
|
|
if (!codingActivity.value)
|
|
return
|
|
|
|
const { name, details, state } = codingActivity.value
|
|
|
|
return name === 'Visual Studio Code' || name === 'Cursor'
|
|
? !details.includes('Idling')
|
|
: state.toLowerCase().includes('editing')
|
|
})
|
|
|
|
const getActivity = computed(() => {
|
|
if (!codingActivity.value)
|
|
return
|
|
|
|
const { name, details, state, timestamps } = codingActivity.value
|
|
|
|
const project = details
|
|
? details
|
|
.charAt(0)
|
|
.toUpperCase()
|
|
+ details
|
|
.slice(1)
|
|
.replace('Workspace:', '')
|
|
.trim()
|
|
: ''
|
|
|
|
const stateWord = state && state.split(' ').length >= 2 ? state.split(' ')[1] : t('secret')
|
|
const ago = useTimeAgo(timestamps.start, {
|
|
messages: activityMessages[locale.value] as UseTimeAgoMessages,
|
|
}).value
|
|
const formatDate = (date: number, format: string) => useDateFormat(date, format, { locales: currentLocale.value?.code ?? 'en' }).value
|
|
|
|
return {
|
|
name,
|
|
project,
|
|
state: stateWord,
|
|
start: {
|
|
ago,
|
|
formated: {
|
|
date: formatDate(timestamps.start, 'DD MMM YYYY'),
|
|
time: formatDate(timestamps.start, 'HH:mm'),
|
|
},
|
|
},
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<ClientOnly>
|
|
<div
|
|
v-if="getActivity"
|
|
class="flex items-start gap-2"
|
|
>
|
|
<UTooltip :text="isActive ? t('tooltip.online') : t('tooltip.idling')">
|
|
<div class="relative flex h-3 w-3 mt-2">
|
|
<div
|
|
v-if="isActive"
|
|
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-500 opacity-75"
|
|
/>
|
|
<div
|
|
:class="isActive ? 'bg-green-500' : 'bg-amber-500'"
|
|
class="relative inline-flex rounded-full h-3 w-3"
|
|
/>
|
|
</div>
|
|
</UTooltip>
|
|
<i18n-t
|
|
v-if="isActive"
|
|
keypath="working"
|
|
tag="div"
|
|
>
|
|
<template #state>
|
|
<strong>{{ getActivity.state!.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ') }}</strong>
|
|
</template>
|
|
<template #project>
|
|
<i>{{ getActivity.project.replaceAll('Editing', '') }}</i>
|
|
</template>
|
|
<template #editor>
|
|
<span class="space-x-1">
|
|
<UIcon
|
|
:name="IDEs.find(ide => ide.name === getActivity!.name)!.icon"
|
|
size="16"
|
|
/>
|
|
<strong>{{ getActivity.name }}</strong></span>
|
|
</template>
|
|
<template #start>
|
|
<strong>{{ getActivity.start.ago }}</strong>
|
|
</template>
|
|
<template #format>
|
|
<strong>{{ getActivity.start.formated.date }}</strong> {{ t('separator') }}
|
|
<strong>{{ getActivity.start.formated.time }}</strong>
|
|
</template>
|
|
</i18n-t>
|
|
<i18n-t
|
|
v-else
|
|
keypath="idling"
|
|
tag="div"
|
|
class="space-x-1"
|
|
>
|
|
<template #editor>
|
|
<span class="space-x-1">
|
|
<UIcon
|
|
:name="IDEs.find(ide => ide.name === getActivity!.name)!.icon"
|
|
size="16"
|
|
/>
|
|
<strong>{{ getActivity.name }}</strong>
|
|
</span>
|
|
</template>
|
|
</i18n-t>
|
|
</div>
|
|
<div
|
|
v-else
|
|
class="my-5 flex md:items-start gap-2"
|
|
>
|
|
<UTooltip :text="t('tooltip.offline')">
|
|
<span class="cursor-not-allowed h-3 w-3 inline-flex rounded-full bg-red-500 mt-2" />
|
|
</UTooltip>
|
|
<p class="not-prose">
|
|
{{ t('offline') }}
|
|
</p>
|
|
</div>
|
|
</ClientOnly>
|
|
</template>
|
|
|
|
<i18n lang="json">
|
|
{
|
|
"en": {
|
|
"offline": "I'm currently offline. Come back later to see what I'm working on.",
|
|
"working": "I'm actually working on {state}, editing {project}, using {editor}. I've started {start}, the {format}.",
|
|
"idling": "I'm idling on my computer with {editor} running in background.",
|
|
"tooltip": {
|
|
"online": "I'm online 👋",
|
|
"offline": "I'm offline 🫥",
|
|
"idling": "I'm sleeping 😴"
|
|
},
|
|
"separator": "at",
|
|
"secret": "Secret Project"
|
|
},
|
|
"fr": {
|
|
"offline": "Je suis actuellement hors ligne. Revenez plus tard pour voir sur quoi je travaille.",
|
|
"working": "Je travaille actuellement sur {state}, éditant {project}, en utilisant {editor}. J'ai commencé {start}, le {format}.",
|
|
"idling": "Je suis en veille sur mon ordinateur avec {editor} en arrière-plan.",
|
|
"tooltip": {
|
|
"online": "Je suis connecté 👋",
|
|
"offline": "Je suis déconnecté 🫥",
|
|
"idling": "Je dors 😴"
|
|
},
|
|
"separator": "à",
|
|
"secret": "Projet Secret"
|
|
},
|
|
"es": {
|
|
"offline": "Ahora mismo estoy desconectado. Vuelve más tarde para ver en lo que estoy trabajando.",
|
|
"working": "Estoy trabajando en {state}, editando {project}, y utilizando {editor}. He empezado {start}, el {format}.",
|
|
"idling": "Estoy en reposo en mi ordenador con {editor} en segundo plano.",
|
|
"tooltip": {
|
|
"online": "Estoy conectado 👋",
|
|
"offline": "Estoy desconectado 🫥",
|
|
"idling": "Estoy durmiendo 😴"
|
|
},
|
|
"separator": "a",
|
|
"secret": "Proyecto Secreto"
|
|
}
|
|
}
|
|
</i18n>
|