Enhance: Update Activity component and ProseIcon styles

- Added optional 'assets' field to LanyardActivity interface for small text.
- Introduced 'Cursor' IDE to the IDEs list.
- Improved color variant styles in ProseIcon component for better visibility.
- Refactored Activity component to handle 'Cursor' IDE and updated activity message formatting.
This commit is contained in:
2025-04-06 20:06:54 +02:00
parent 9aa904e18a
commit d3a8243abf
4 changed files with 50 additions and 41 deletions

View File

@@ -11,19 +11,19 @@ defineProps({
})
const colorVariants = {
gray: 'text-gray-500 decoration-gray-400',
red: 'text-red-500 decoration-red-400',
yellow: 'text-yellow-500 decoration-yellow-400',
green: 'text-green-500 decoration-green-400',
blue: 'text-blue-500 decoration-blue-400',
indigo: 'text-indigo-500 decoration-indigo-400',
purple: 'text-purple-500 decoration-purple-400',
pink: 'text-pink-500 decoration-pink-400',
sky: 'text-sky-500 decoration-sky-400',
zinc: 'text-zinc-500 decoration-zinc-400',
orange: 'text-orange-500 decoration-orange-400',
amber: 'text-amber-500 decoration-amber-400',
emerald: 'text-emerald-500 decoration-emerald-400',
gray: 'text-gray-500/60 decoration-gray-400/60',
red: 'text-red-500/60 decoration-red-400/60',
yellow: 'text-yellow-500/60 decoration-yellow-400/60',
green: 'text-green-500/60 decoration-green-400/60',
blue: 'text-blue-500/60 decoration-blue-400/60',
indigo: 'text-indigo-500/60 decoration-indigo-400/60',
purple: 'text-purple-500/60 decoration-purple-400/60',
pink: 'text-pink-500/60 decoration-pink-400/60',
sky: 'text-sky-500/60 decoration-sky-400/60',
zinc: 'text-zinc-500/60 decoration-zinc-400/60',
orange: 'text-orange-500/60 decoration-orange-400/60',
amber: 'text-amber-500/60 decoration-amber-400/60',
emerald: 'text-emerald-500/60 decoration-emerald-400/60',
}
</script>
@@ -34,7 +34,7 @@ const colorVariants = {
:name="`i-logos:${icon}`"
/>
<span
:class="colorVariants[color]"
:class="colorVariants[color as keyof typeof colorVariants]"
class="sofia font-medium underline-offset-2 underline"
>
<slot />

View File

@@ -3,16 +3,22 @@ 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))
if (activities.length > 1) {
const randomIndex = Math.floor(Math.random() * activities.length)
return activities[randomIndex]
}
return activities[0]
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()
@@ -24,7 +30,7 @@ const isActive = computed(() => {
const { name, details, state } = codingActivity.value
return name === 'Visual Studio Code'
return name === 'Visual Studio Code' || name === 'Cursor'
? !details.includes('Idling')
: state.toLowerCase().includes('editing')
})
@@ -44,7 +50,7 @@ const getActivity = computed(() => {
.replace('Workspace:', '')
.trim()
: ''
const stateWord = state.split(' ')[1]
const stateWord = state.split(' ')[1] || t('secret')
const ago = useTimeAgo(timestamps.start, {
messages: activityMessages[locale.value] as UseTimeAgoMessages,
}).value
@@ -63,10 +69,6 @@ const getActivity = computed(() => {
},
}
})
const { t } = useI18n({
useScope: 'local',
})
</script>
<template>
@@ -92,11 +94,11 @@ const { t } = useI18n({
keypath="working"
tag="div"
>
<template #project>
<strong>{{ getActivity.project }}</strong>
</template>
<template #state>
<i>{{ getActivity.state }}</i>
<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">
@@ -149,36 +151,39 @@ const { t } = useI18n({
{
"en": {
"offline": "I'm currently offline. Come back later to see what I'm working on.",
"working": "I'm actually working on {project}, editing {state}, using {editor}. I've started {start}, the {format}.",
"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"
"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 {project}, éditant {state}, en utilisant {editor}. J'ai commencé {start}, le {format}.",
"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": "à"
"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 {project}, editando {state}, y utilizando {editor}. He empezado {start}, el {format}.",
"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"
"separator": "a",
"secret": "Proyecto Secreto"
}
}
</i18n>

View File

@@ -31,8 +31,8 @@ defineProps({
/>
<span
class="duration-300 underline-offset-2 font-bold text-md text-black dark:text-white underline decoration-gray-300 dark:decoration-neutral-700 group-hover:decoration-black dark:group-hover:decoration-white"
>{{
label
}}</span>
>
{{ label }}
</span>
</NuxtLink>
</template>

View File

@@ -32,6 +32,9 @@ interface LanyardActivity {
timestamps: {
start: number
}
assets?: {
small_text: string
}
}
export interface Activity {
@@ -45,6 +48,7 @@ export const IDEs = [
{ name: 'IntelliJ IDEA Ultimate', icon: 'i-logos:intellij-idea' },
{ name: 'WebStorm', icon: 'i-logos:webstorm' },
{ name: 'PyCharm Professional', icon: 'i-logos:pycharm' },
{ name: 'Cursor', icon: 'i-vscode-icons-file-type-cursorrules' },
]
export const activityMessages = {
@@ -66,13 +70,13 @@ export const activityMessages = {
invalid: '',
},
fr: {
justNow: 'à linstant',
justNow: 'à l\'instant',
past: (n: string) => (n.match(/\d/) ? `il y a ${n}` : n),
future: (n: string) => (n.match(/\d/) ? `dans ${n}` : n),
month: (n: number, past: boolean) =>
n === 1 ? (past ? 'le mois dernier' : 'le mois prochain') : `${n} mois`,
year: (n: number, past: boolean) =>
n === 1 ? (past ? 'lannée dernière' : 'lannée prochaine') : `${n} ans`,
n === 1 ? (past ? 'l\'année dernière' : 'l\'année prochaine') : `${n} ans`,
day: (n: number, past: boolean) =>
n === 1 ? (past ? 'hier' : 'demain') : `${n} jours`,
week: (n: number, past: boolean) =>