Merge pull request #44 from josedario87/codex/implementar-view-transition-api
All checks were successful
build-and-deploy / filter (push) Successful in 2s
build-and-deploy / build (push) Successful in 10s
build-and-deploy / deploy (push) Successful in 25s

Fix realtime feed transitions
This commit is contained in:
josedario87
2025-06-10 00:12:10 -06:00
committed by GitHub
3 changed files with 50 additions and 9 deletions

View File

@@ -114,6 +114,7 @@ const operationClass = computed(() => {
.realtime-event {
margin-bottom: 1rem;
padding: 0.5rem;
view-transition-name: auto;
}
.old-card,

View File

@@ -27,15 +27,33 @@ export const useRealtimeStore = defineStore('realtime', {
};
this._sse.onmessage = (e) => {
console.log('📩 SSE message raw:', e.data);
// console.log('📩 SSE message raw:', e.data);
try {
const payload = JSON.parse(e.data);
console.log('📦 Payload parseado:', payload);
console.log('🧪 Tabla recibida:', payload.table);
// console.log('📦 Payload parseado:', payload);
// console.log('🧪 Tabla recibida:', payload.table);
console.log('📬 Evento SSE recibido:');
// store event for feed
this.events.unshift({ ...payload, receivedAt: new Date().toISOString() });
// store event for feed with View Transition if available
const addEvent = () => {
const event = {
id: crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).slice(2),
...payload,
receivedAt: new Date().toISOString(),
};
// console.log('🔄 Adding realtime event', event);
this.events.unshift(event);
// console.log('📊 Events in feed:', this.events.length);
};
if (document.startViewTransition) {
console.log('🎬 Using View Transition API for new event');
document.startViewTransition(addEvent);
} else {
console.log('⚠️ View Transition API not supported');
addEvent();
}
// mark badge for module and operation
if (this.badges[payload.table]) {
@@ -64,7 +82,7 @@ export const useRealtimeStore = defineStore('realtime', {
this._sse.onerror = () => {
console.warn('SSE connection lost, reloading...');
};
}
},
clearBadgesForTable(table) {
if (this.badges[table]) {
this.badges[table].INSERT = false;

View File

@@ -1,10 +1,17 @@
<script setup>
import { onMounted } from 'vue'
import { onMounted, watch } from 'vue'
import { useRealtimeStore } from '@/stores/useRealtime'
import RealtimeEventCard from '@/components/realtime/RealtimeEventCard.vue'
const realtime = useRealtimeStore()
watch(
() => realtime.events.length,
(newLen, oldLen) => {
console.log(`📈 Feed length changed: ${oldLen} -> ${newLen}`)
}
)
onMounted(() => {
realtime.init()
})
@@ -23,8 +30,8 @@ onMounted(() => {
style="max-height: calc(100vh - 160px); min-width: 60vw;"
>
<RealtimeEventCard
v-for="(ev, idx) in realtime.events"
:key="ev.receivedAt + idx"
v-for="ev in realtime.events"
:key="ev.id"
:event="ev"
style="max-width: 100%; border-bottom: white 1px solid; padding: 20px 0 40px 20px ;"
/>
@@ -79,4 +86,19 @@ onMounted(() => {
.feed-list::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
:global(::view-transition-old(.realtime-event)),
:global(::view-transition-new(.realtime-event)) {
animation: slide 0.25s ease both;
}
@keyframes slide {
from {
transform: translateY(var(--view-transition-slide-y, 0));
opacity: 0;
}
to {
transform: none;
opacity: 1;
}
}
</style>