From 38bcbfc697cebf9967e9202785b523e578825ae5 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 20 Aug 2026 09:08:24 +0800 Subject: [PATCH] fix: sync program status updates --- backend/routes/streams.py | 1 + frontend/src/App.tsx | 7 +++++-- frontend/src/admin/AdminLayout.tsx | 9 ++++++--- frontend/src/pageTransitions.css | 28 ++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 frontend/src/pageTransitions.css diff --git a/backend/routes/streams.py b/backend/routes/streams.py index 47459a8..d1831fe 100644 --- a/backend/routes/streams.py +++ b/backend/routes/streams.py @@ -205,6 +205,7 @@ async def catalog_events(request: Request, db: AsyncSession = Depends(get_db)): async def events(): previous = None while not await request.is_disconnected(): + db.expire_all() streams = await StreamService(db).get_public_streams() payload = json.dumps( [_serialize(stream, include_private=False) for stream in streams], diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 69c448b..5dbc426 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,8 +1,9 @@ import { Component, lazy, Suspense, useState, useEffect, type ErrorInfo, type ReactNode } from 'react' -import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom' +import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom' import { Button, ConfigProvider, Result } from 'antd' import zhCN from 'antd/locale/zh_CN' import theme from './theme/anthropic' +import './pageTransitions.css' import { BrandProvider, useBrand } from './brand/BrandContext' import { verifyToken } from './api/auth' import { getToken } from './api/client' @@ -60,6 +61,8 @@ function AdminGuard({ children }: { children: React.ReactNode }) { } function AppRoutes() { + const location = useLocation() + const routeTransitionKey = location.pathname.startsWith('/admin') ? '/admin' : location.pathname const { brand } = useBrand() useEffect(() => { document.title = brand.brand_name }, [brand.brand_name]) return ( @@ -98,4 +101,4 @@ export default function App() { ) -} +} \ No newline at end of file diff --git a/frontend/src/admin/AdminLayout.tsx b/frontend/src/admin/AdminLayout.tsx index 85f2134..d0cefe6 100644 --- a/frontend/src/admin/AdminLayout.tsx +++ b/frontend/src/admin/AdminLayout.tsx @@ -1,5 +1,5 @@ import { Suspense, useEffect, useState } from 'react' -import { Outlet, useNavigate, useLocation } from 'react-router-dom' +import { Outlet, useNavigate, useLocation , useOutlet } from 'react-router-dom' import { Layout, Menu, Button, Typography } from 'antd' import { DashboardOutlined, VideoCameraOutlined, PlusOutlined, MonitorOutlined, @@ -35,6 +35,7 @@ export default function AdminLayout() { const [collapsed, setCollapsed] = useState(false) const navigate = useNavigate() const location = useLocation() + const outlet = useOutlet() const selectedKey = menuItems.find( item => location.pathname === item.key || (location.pathname === '/' && item.key === '/admin') @@ -78,9 +79,11 @@ export default function AdminLayout() { - +
+ {outlet} +
) -} +} \ No newline at end of file diff --git a/frontend/src/pageTransitions.css b/frontend/src/pageTransitions.css new file mode 100644 index 0000000..6385155 --- /dev/null +++ b/frontend/src/pageTransitions.css @@ -0,0 +1,28 @@ +.app-route-transition, +.admin-page-transition { + min-height: 100%; + animation: page-fade-slide-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both; + will-change: opacity, transform; +} + +.admin-page-transition { + transform-origin: top center; +} + +@keyframes page-fade-slide-in { + from { + opacity: 0; + transform: translateY(14px) scale(0.995); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@media (prefers-reduced-motion: reduce) { + .app-route-transition, + .admin-page-transition { + animation: none; + } +}