Versiyon yenileme

This commit is contained in:
Sedat Öztürk 2025-09-22 22:37:28 +03:00
parent d406d8956e
commit f55b777a17
4 changed files with 50 additions and 22 deletions

View file

@ -7,9 +7,12 @@ import { store } from './store'
import { DynamicRoutesProvider } from './routes/dynamicRoutesContext' import { DynamicRoutesProvider } from './routes/dynamicRoutesContext'
import { ComponentProvider } from './contexts/ComponentContext' import { ComponentProvider } from './contexts/ComponentContext'
import ComponentRegistryProvider from './contexts/ComponentRegistryContext' import ComponentRegistryProvider from './contexts/ComponentRegistryContext'
import { registerServiceWorker } from './views/version/swRegistration'
const queryClient = new QueryClient() const queryClient = new QueryClient()
registerServiceWorker()
function App() { function App() {
return ( return (
<StoreProvider store={store}> <StoreProvider store={store}>

View file

@ -1,56 +1,65 @@
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { HiOutlineRefresh, HiX } from 'react-icons/hi' import { HiOutlineRefresh, HiX } from 'react-icons/hi'
import { useStoreState, useStoreActions } from '@/store' import { useStoreActions } from '@/store'
const UpdateNotifier = () => { const UpdateNotifier = () => {
const [lastUiVersion, setLastUiVersion] = useState('')
const [updateAvailable, setUpdateAvailable] = useState(false) const [updateAvailable, setUpdateAvailable] = useState(false)
const navigate = useNavigate() const [newVersion, setNewVersion] = useState<string | null>(null)
const { currentUiVersion } = useStoreState((s) => s.locale)
const { setUiVersion } = useStoreActions((s) => s.locale) const { setUiVersion } = useStoreActions((s) => s.locale)
// SW update olayını dinle
useEffect(() => { useEffect(() => {
const checkVersion = async () => { const handler = async () => {
try { try {
const res = await fetch('/version.json?ts=' + Date.now()) const res = await fetch('/version.json?ts=' + Date.now())
const data = await res.json() const data = await res.json()
const latestVersion = data?.releases?.[0]?.version const latest = data?.releases?.[0]?.version
if (latestVersion && latestVersion !== currentUiVersion) { if (latest) {
setUpdateAvailable(true) setNewVersion(latest)
setLastUiVersion(latestVersion)
} }
} catch (err) { } catch {
console.error('Version check failed', err) console.warn('Yeni versiyon bilgisi alınamadı')
} }
setUpdateAvailable(true)
} }
checkVersion() window.addEventListener('sw-update-available', handler)
const interval = setInterval(checkVersion, 30000) // 30sde bir kontrol return () => window.removeEventListener('sw-update-available', handler)
return () => clearInterval(interval) }, [])
}, [currentUiVersion])
if (!updateAvailable) return null if (!updateAvailable) return null
return ( return (
<div <div className="fixed bottom-5 right-5 z-50 flex items-center justify-between gap-4 rounded-lg bg-sky-500 p-4 text-white shadow-lg animate-bounce">
className="fixed bottom-5 right-5 z-50 flex items-center justify-between gap-4 rounded-lg bg-sky-500 p-4 text-white shadow-lg animate-bounce"
>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<HiOutlineRefresh className="h-8 w-8 animate-spin" /> <HiOutlineRefresh className="h-8 w-8 animate-spin" />
<div> <div>
<p className="font-semibold">Yeni güncelleme mevcut! (v{lastUiVersion})</p> <p className="font-semibold">
Yeni güncelleme mevcut {newVersion && `(v${newVersion})`}!
</p>
<p className="text-sm">En son özellikler için sayfayı yenileyin.</p> <p className="text-sm">En son özellikler için sayfayı yenileyin.</p>
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={() => { onClick={() => {
setUiVersion(lastUiVersion) navigator.serviceWorker.getRegistration().then((reg) => {
if (reg?.waiting) {
reg.waiting.postMessage({ type: 'SKIP_WAITING' })
}
})
if (newVersion) {
setUiVersion(newVersion)
window.location.href =
ROUTES_ENUM.protected.admin.changeLog + `?v=${newVersion}`
} else {
window.location.reload()
}
setUpdateAvailable(false) setUpdateAvailable(false)
window.location.href = ROUTES_ENUM.protected.admin.changeLog + `?v=${lastUiVersion}`
}} }}
className="rounded bg-white px-4 py-2 text-sm font-bold text-sky-600 transition hover:bg-sky-100" className="rounded bg-white px-4 py-2 text-sm font-bold text-sky-600 transition hover:bg-sky-100"
> >

View file

@ -0,0 +1,15 @@
// src/swRegistration.ts
import { registerSW } from 'virtual:pwa-register'
export const registerServiceWorker = () => {
registerSW({
immediate: true, // Yeni SW hemen yüklensin
onNeedRefresh() {
const event = new CustomEvent('sw-update-available')
window.dispatchEvent(event)
},
onOfflineReady() {
console.log('App offline ready')
},
})
}

View file

@ -1,4 +1,5 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
/// <reference types="vite-plugin-pwa/client" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly VITE_API_URL: string readonly VITE_API_URL: string