mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix(web): fix push notification click 404 on GitHub Pages (#322)
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>HAPI</title>
|
||||||
|
<script>
|
||||||
|
sessionStorage.setItem('spaRedirect', window.location.pathname + window.location.search + window.location.hash)
|
||||||
|
window.location.replace('/')
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
|
import { restoreSpaRedirect, storeSpaRedirect } from './spaRedirect'
|
||||||
|
|
||||||
|
describe('spaRedirect', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
sessionStorage.clear()
|
||||||
|
vi.spyOn(window.history, 'replaceState')
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('restoreSpaRedirect', () => {
|
||||||
|
it('restores stored path via replaceState', () => {
|
||||||
|
sessionStorage.setItem('spaRedirect', '/sessions/abc123')
|
||||||
|
|
||||||
|
restoreSpaRedirect()
|
||||||
|
|
||||||
|
expect(window.history.replaceState).toHaveBeenCalledWith(null, '', '/sessions/abc123')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removes spaRedirect from sessionStorage after restoring', () => {
|
||||||
|
sessionStorage.setItem('spaRedirect', '/sessions/abc123')
|
||||||
|
|
||||||
|
restoreSpaRedirect()
|
||||||
|
|
||||||
|
expect(sessionStorage.getItem('spaRedirect')).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does nothing when spaRedirect is not set', () => {
|
||||||
|
restoreSpaRedirect()
|
||||||
|
|
||||||
|
expect(window.history.replaceState).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('preserves query string and hash in restored path', () => {
|
||||||
|
sessionStorage.setItem('spaRedirect', '/sessions/abc123?foo=bar#section')
|
||||||
|
|
||||||
|
restoreSpaRedirect()
|
||||||
|
|
||||||
|
expect(window.history.replaceState).toHaveBeenCalledWith(null, '', '/sessions/abc123?foo=bar#section')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('storeSpaRedirect', () => {
|
||||||
|
it('stores the current pathname in sessionStorage', () => {
|
||||||
|
Object.defineProperty(window, 'location', {
|
||||||
|
value: { pathname: '/sessions/abc123', search: '', hash: '' },
|
||||||
|
configurable: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
storeSpaRedirect()
|
||||||
|
|
||||||
|
expect(sessionStorage.getItem('spaRedirect')).toBe('/sessions/abc123')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('stores pathname with search and hash', () => {
|
||||||
|
Object.defineProperty(window, 'location', {
|
||||||
|
value: { pathname: '/sessions/abc123', search: '?foo=bar', hash: '#section' },
|
||||||
|
configurable: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
storeSpaRedirect()
|
||||||
|
|
||||||
|
expect(sessionStorage.getItem('spaRedirect')).toBe('/sessions/abc123?foo=bar#section')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const SPA_REDIRECT_KEY = 'spaRedirect'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the current path in sessionStorage before GitHub Pages redirects to /.
|
||||||
|
* Called from public/404.html when GitHub Pages serves a 404 for SPA routes.
|
||||||
|
*/
|
||||||
|
export function storeSpaRedirect(): void {
|
||||||
|
const path = window.location.pathname + window.location.search + window.location.hash
|
||||||
|
sessionStorage.setItem(SPA_REDIRECT_KEY, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the path stored by storeSpaRedirect() using replaceState,
|
||||||
|
* so TanStack Router initializes at the correct URL without a server round-trip.
|
||||||
|
*/
|
||||||
|
export function restoreSpaRedirect(): void {
|
||||||
|
const redirect = sessionStorage.getItem(SPA_REDIRECT_KEY)
|
||||||
|
if (redirect) {
|
||||||
|
sessionStorage.removeItem(SPA_REDIRECT_KEY)
|
||||||
|
window.history.replaceState(null, '', redirect)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import { getTelegramWebApp, isTelegramEnvironment, loadTelegramSdk } from './hoo
|
|||||||
import { queryClient } from './lib/query-client'
|
import { queryClient } from './lib/query-client'
|
||||||
import { createAppRouter } from './router'
|
import { createAppRouter } from './router'
|
||||||
import { I18nProvider } from './lib/i18n-context'
|
import { I18nProvider } from './lib/i18n-context'
|
||||||
|
import { restoreSpaRedirect } from './lib/spaRedirect'
|
||||||
|
|
||||||
function getStartParam(): string | null {
|
function getStartParam(): string | null {
|
||||||
const query = new URLSearchParams(window.location.search)
|
const query = new URLSearchParams(window.location.search)
|
||||||
@@ -41,6 +42,13 @@ async function bootstrap() {
|
|||||||
await loadTelegramSdk()
|
await loadTelegramSdk()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle GitHub Pages 404 redirect for SPA routing
|
||||||
|
// When GitHub Pages can't find a path (e.g. /sessions/xxx), it serves 404.html
|
||||||
|
// which stores the path in sessionStorage and redirects to /
|
||||||
|
if (!isTelegram) {
|
||||||
|
restoreSpaRedirect()
|
||||||
|
}
|
||||||
|
|
||||||
const updateSW = registerSW({
|
const updateSW = registerSW({
|
||||||
onNeedRefresh() {
|
onNeedRefresh() {
|
||||||
if (confirm('New version available! Reload to update?')) {
|
if (confirm('New version available! Reload to update?')) {
|
||||||
|
|||||||
Reference in New Issue
Block a user