hot fix #1
@@ -0,0 +1,103 @@
|
||||
// Admin Sidebar Scroll Test - Run directly in browser console
|
||||
// Copy and paste this entire script into the browser console on any admin page
|
||||
|
||||
(function adminScrollTest() {
|
||||
console.clear();
|
||||
console.log('=== ADMIN SIDEBAR SCROLL TEST ===\n');
|
||||
|
||||
// Find sidebar
|
||||
const sidebar = document.querySelector('[data-sidebar="true"]');
|
||||
if (!sidebar) {
|
||||
console.error('❌ No sidebar found. Make sure you are on an admin page (/admin/*)');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ Sidebar found');
|
||||
console.log('📏 Current scroll:', sidebar.scrollTop);
|
||||
console.log('📏 Scroll height:', sidebar.scrollHeight);
|
||||
console.log('📏 Client height:', sidebar.clientHeight);
|
||||
console.log('📏 Scrollable:', sidebar.scrollHeight > sidebar.clientHeight ? '✅ YES' : '❌ NO');
|
||||
|
||||
// Check if scrollable
|
||||
if (sidebar.scrollHeight <= sidebar.clientHeight) {
|
||||
console.log('\n⚠️ Sidebar is NOT scrollable!');
|
||||
console.log(' To test scroll retention, the sidebar needs to be scrollable.');
|
||||
console.log(' Try: 1) Reducing browser window height, or 2) Zoom in (Ctrl +)');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n🧪 Testing scroll retention...');
|
||||
|
||||
// Clear any existing scroll data
|
||||
sessionStorage.removeItem('admin-sidebar-scroll');
|
||||
sessionStorage.removeItem('admin-sidebar-scroll-emergency');
|
||||
delete window.__adminSidebarScrollTarget;
|
||||
|
||||
// Scroll to a test position (middle of scrollable area)
|
||||
const maxScroll = sidebar.scrollHeight - sidebar.clientHeight;
|
||||
const testScroll = Math.floor(maxScroll * 0.5);
|
||||
|
||||
console.log('📍 Scrolling to test position:', testScroll, 'px');
|
||||
sidebar.scrollTop = testScroll;
|
||||
|
||||
setTimeout(() => {
|
||||
const actualScroll = sidebar.scrollTop;
|
||||
console.log('📍 Current position after scroll:', actualScroll, 'px');
|
||||
|
||||
// Check if scroll was saved
|
||||
const savedData = sessionStorage.getItem('admin-sidebar-scroll');
|
||||
const emergencyData = sessionStorage.getItem('admin-sidebar-scroll-emergency');
|
||||
const globalTarget = window.__adminSidebarScrollTarget;
|
||||
|
||||
console.log('\n💾 Storage check:');
|
||||
console.log(' Main saved data:', savedData);
|
||||
console.log(' Emergency saved:', emergencyData);
|
||||
console.log(' Global target:', globalTarget);
|
||||
|
||||
console.log('\n🚀 NOW CLICK ANY ADMIN NAVIGATION LINK');
|
||||
console.log(' The test will automatically detect navigation and check scroll preservation');
|
||||
|
||||
// Intercept navigation to test
|
||||
let navDetected = false;
|
||||
const originalPushState = history.pushState;
|
||||
|
||||
history.pushState = function(...args) {
|
||||
if (!navDetected) {
|
||||
navDetected = true;
|
||||
const scrollBefore = sidebar.scrollTop;
|
||||
console.log('\n🚦 Navigation detected!');
|
||||
console.log(' Scroll position before navigation:', scrollBefore, 'px');
|
||||
|
||||
// Check scroll preservation at multiple intervals
|
||||
const checkPoints = [100, 300, 600, 1000];
|
||||
checkPoints.forEach((delay, index) => {
|
||||
setTimeout(() => {
|
||||
const scrollAfter = sidebar.scrollTop;
|
||||
const difference = Math.abs(scrollAfter - scrollBefore);
|
||||
|
||||
console.log(` 📍 Check ${index + 1} (${delay}ms): ${scrollAfter}px (diff: ${difference}px)`);
|
||||
|
||||
if (delay === 1000) {
|
||||
if (difference < 10) {
|
||||
console.log('\n✅ SUCCESS: Scroll position preserved!');
|
||||
console.log(' The admin sidebar scroll retention is working correctly.');
|
||||
} else {
|
||||
console.log('\n❌ FAILURE: Scroll position was reset');
|
||||
console.log(' Difference:', difference, 'px');
|
||||
console.log('\n🔍 Debugging info:');
|
||||
console.log(' - Check browser console for any scroll-related errors');
|
||||
console.log(' - Verify AdminScrollManager is loaded');
|
||||
console.log(' - Check if CSS is interfering');
|
||||
}
|
||||
|
||||
// Restore original history function
|
||||
history.pushState = originalPushState;
|
||||
}
|
||||
}, delay);
|
||||
});
|
||||
}
|
||||
return originalPushState.apply(this, args);
|
||||
};
|
||||
|
||||
}, 500);
|
||||
})();
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128px" height="128px"><path fill="#F7F7FB" d="M109.7,110H18.2c-5.1,0-9.2-4.1-9.2-9.2V22.6c0-2.5,2.1-4.6,4.6-4.6H96c2.5,0,4.6,2.1,4.6,4.6v23.1v55.2C100.6,105.9,104.7,110,109.7,110L109.7,110c5.1,0,9.2-4.1,9.2-9.2V50.2c0-2.5-2.1-4.6-4.6-4.6h-4.6"/><path fill="#DEDFE6" d="M23 31.9h63.1c1.7 0 3 1.3 3 3v16.9c0 1.7-1.3 3-3 3H23c-1.7 0-3-1.3-3-3V34.9C20 33.2 21.3 31.9 23 31.9zM109.7 110L109.7 110c5.1 0 9.2-4.1 9.2-9.2V50.2c0-2.5-2.1-4.6-4.6-4.6h-13.8v55.2C100.6 105.9 104.7 110 109.7 110z"/><path fill="#464C55" d="M109.7,113H18.2C11.5,113,6,107.5,6,100.8V22.6c0-4.2,3.4-7.6,7.6-7.6H96c4.2,0,7.6,3.4,7.6,7.6v78.3c0,3.4,2.8,6.2,6.2,6.2s6.2-2.8,6.2-6.2V50.2c0-0.9-0.7-1.6-1.6-1.6h-4.6c-1.7,0-3-1.3-3-3s1.3-3,3-3h4.6c4.2,0,7.6,3.4,7.6,7.6v50.6C121.9,107.6,116.4,113,109.7,113z M13.6,21c-0.9,0-1.6,0.7-1.6,1.6v78.3c0,3.4,2.8,6.2,6.2,6.2h81.1c-1.1-1.8-1.7-3.9-1.7-6.2V22.6c0-0.9-0.7-1.6-1.6-1.6L13.6,21z"/><path fill="#DEDFE6" d="M41.2 72.9H23c-1.7 0-3-1.3-3-3s1.3-3 3-3h18.2c1.7 0 3 1.3 3 3S42.9 72.9 41.2 72.9zM41.2 98.7H23c-1.7 0-3-1.3-3-3s1.3-3 3-3h18.2c1.7 0 3 1.3 3 3S42.9 98.7 41.2 98.7zM41.2 85.7H23c-1.7 0-3-1.3-3-3s1.3-3 3-3h18.2c1.7 0 3 1.3 3 3S42.9 85.7 41.2 85.7z"/><path fill="#464C55" d="M86,99.1H58c-1.7,0-3-1.3-3-3V68.6c0-1.7,1.3-3,3-3h28c1.7,0,3,1.3,3,3v27.5C89,97.7,87.7,99.1,86,99.1z M61,93.1h22V71.6H61V93.1z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,46 @@
|
||||
// Quick debug to check if AdminScrollManager is working
|
||||
// Run this in browser console
|
||||
|
||||
(function debugAdminScrollManager() {
|
||||
console.clear();
|
||||
console.log('=== DEBUGGING AdminScrollManager ===\n');
|
||||
|
||||
// Check if AdminScrollManager is loaded
|
||||
console.log('🔍 Checking AdminScrollManager...');
|
||||
|
||||
// Look for AdminScrollManager logs
|
||||
console.log('📋 Recent console logs:');
|
||||
const logs = console.logs || [];
|
||||
console.log(' - Look for "[AdminScrollManager] Component mounted" message');
|
||||
console.log(' - Look for "[AdminScrollManager] Saved position" message');
|
||||
console.log(' - Look for "[AdminScrollManager] Restoring position" message');
|
||||
|
||||
// Check if AdminLayout is being used
|
||||
const adminLayout = document.querySelector('.admin-layout');
|
||||
console.log('\n🏗️ AdminLayout check:');
|
||||
console.log(' AdminLayout element found:', !!adminLayout);
|
||||
|
||||
// Check sidebar
|
||||
const sidebar = document.querySelector('[data-sidebar="true"]');
|
||||
console.log('\n📱 Sidebar check:');
|
||||
console.log(' Sidebar element found:', !!sidebar);
|
||||
console.log(' Sidebar current scroll:', sidebar?.scrollTop);
|
||||
|
||||
// Check if React DevTools shows AdminScrollManager
|
||||
console.log('\n🔧 Manual test:');
|
||||
console.log(' 1. Scroll the sidebar to any position');
|
||||
console.log(' 2. Click an admin navigation link');
|
||||
console.log(' 3. Watch console for AdminScrollManager messages');
|
||||
|
||||
console.log('\n💡 If you don\'t see AdminScrollManager logs, the component is not loading');
|
||||
|
||||
// Force a test
|
||||
if (sidebar) {
|
||||
console.log('\n🧪 Forcing a scroll test...');
|
||||
sidebar.scrollTop = 300;
|
||||
setTimeout(() => {
|
||||
console.log(' Scroll set to:', sidebar.scrollTop);
|
||||
console.log(' Now click a navigation link and watch for AdminScrollManager logs');
|
||||
}, 100);
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="144px" height="144px" baseProfile="basic"><path fill="#536dfe" d="M47.496,10.074c-0.508-0.249-0.727,0.226-1.025,0.467c-0.102,0.078-0.188,0.179-0.274,0.272 c-0.743,0.794-1.611,1.315-2.746,1.253c-1.658-0.093-3.074,0.428-4.326,1.696c-0.266-1.564-1.15-2.498-2.495-3.097 c-0.704-0.311-1.416-0.623-1.909-1.3c-0.344-0.482-0.438-1.019-0.61-1.548c-0.11-0.319-0.219-0.646-0.587-0.7 c-0.399-0.062-0.555,0.272-0.712,0.553c-0.626,1.144-0.868,2.405-0.845,3.681c0.055,2.871,1.267,5.159,3.676,6.785 c0.274,0.187,0.344,0.373,0.258,0.646c-0.164,0.56-0.36,1.105-0.532,1.665c-0.11,0.358-0.274,0.436-0.657,0.28 c-1.322-0.552-2.464-1.369-3.473-2.358c-1.713-1.657-3.262-3.486-5.194-4.918c-0.454-0.335-0.907-0.646-1.377-0.942 c-1.971-1.914,0.258-3.486,0.774-3.673c0.54-0.195,0.188-0.864-1.557-0.856c-1.744,0.008-3.34,0.591-5.374,1.369 c-0.297,0.117-0.61,0.202-0.931,0.272c-1.846-0.35-3.763-0.428-5.765-0.202c-3.77,0.42-6.782,2.202-8.996,5.245 c-2.66,3.657-3.285,7.812-2.519,12.147c0.806,4.568,3.137,8.349,6.719,11.306c3.716,3.066,7.994,4.568,12.876,4.28 c2.965-0.171,6.266-0.568,9.989-3.719c0.939,0.467,1.924,0.654,3.559,0.794c1.259,0.117,2.472-0.062,3.411-0.257 c1.471-0.311,1.369-1.673,0.837-1.922C34,36,33.471,35.441,33.471,35.441c2.19-2.591,5.491-5.284,6.782-14.007 c0.102-0.692,0.016-1.128,0-1.689c-0.008-0.342,0.07-0.475,0.462-0.514c1.079-0.125,2.128-0.42,3.09-0.949 c2.793-1.525,3.919-4.031,4.185-7.034C48.028,10.79,47.981,10.315,47.496,10.074z M23.161,37.107 c-4.177-3.284-6.203-4.365-7.04-4.319c-0.782,0.047-0.641,0.942-0.469,1.525c0.18,0.576,0.415,0.973,0.743,1.478 c0.227,0.335,0.383,0.833-0.227,1.206c-1.345,0.833-3.684-0.28-3.794-0.335c-2.722-1.603-4.998-3.72-6.602-6.614 c-1.549-2.786-2.448-5.774-2.597-8.964c-0.039-0.77,0.188-1.043,0.954-1.183c1.009-0.187,2.049-0.226,3.059-0.078 c4.263,0.623,7.893,2.529,10.936,5.548c1.737,1.72,3.051,3.774,4.404,5.782c1.439,2.132,2.988,4.163,4.959,5.828 c0.696,0.584,1.252,1.027,1.783,1.354C27.667,38.515,24.991,38.554,23.161,37.107L23.161,37.107z M25.164,24.228 c0-0.342,0.274-0.615,0.618-0.615c0.078,0,0.149,0.015,0.211,0.039c0.086,0.031,0.164,0.078,0.227,0.148 c0.11,0.109,0.172,0.265,0.172,0.428c0,0.342-0.274,0.615-0.618,0.615S25.164,24.571,25.164,24.228L25.164,24.228z M31.382,27.419 c-0.399,0.163-0.798,0.303-1.181,0.319c-0.595,0.031-1.244-0.21-1.596-0.506c-0.548-0.459-0.939-0.716-1.103-1.517 c-0.07-0.342-0.031-0.872,0.031-1.175c0.141-0.654-0.016-1.074-0.477-1.455c-0.376-0.311-0.853-0.397-1.377-0.397 c-0.196,0-0.375-0.086-0.508-0.156c-0.219-0.109-0.399-0.381-0.227-0.716c0.055-0.109,0.321-0.373,0.383-0.42 c0.712-0.405,1.533-0.272,2.292,0.031c0.704,0.288,1.236,0.817,2.003,1.564c0.782,0.903,0.923,1.152,1.369,1.829 c0.352,0.529,0.673,1.074,0.892,1.696C32.016,26.905,31.844,27.224,31.382,27.419L31.382,27.419z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Grok</title><path d="M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815"></path></svg>
|
||||
|
After Width: | Height: | Size: 756 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="200" height="200" fill="#f7fafc"/>
|
||||
<text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#a0aec0" font-family="Arial, sans-serif" font-size="14">Club Logo</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 257 B |
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,36 @@
|
||||
<svg width="192" height="192" viewBox="0 0 192 192" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Clean white background -->
|
||||
<rect width="192" height="192" fill="#ffffff"/>
|
||||
|
||||
<!-- Enhanced Football/Soccer Ball Design -->
|
||||
<g transform="translate(96,96)">
|
||||
<!-- Outer circle with bold stroke -->
|
||||
<circle cx="0" cy="0" r="48" fill="none" stroke="#000000" stroke-width="3"/>
|
||||
|
||||
<!-- Pentagon pattern - cleaner design -->
|
||||
<g>
|
||||
<!-- Center pentagon -->
|
||||
<path d="M 0,-20 L 19,-6 L 12,16 L -12,16 L -19,-6 Z"
|
||||
fill="#000000" stroke="#000000" stroke-width="2"/>
|
||||
|
||||
<!-- Surrounding hexagons with cleaner lines -->
|
||||
<g stroke="#000000" stroke-width="2" fill="none">
|
||||
<path d="M 0,-20 L 19,-6 L 19,-32 L 0,-45 L -19,-32 L -19,-6 Z"/>
|
||||
<path d="M 19,-6 L 12,16 L 34,16 L 41,-6 L 19,-6 Z"/>
|
||||
<path d="M 12,16 L -12,16 L -19,38 L 3,46 L 25,38 L 12,16 Z"/>
|
||||
<path d="M -12,16 L -19,-6 L -41,-6 L -34,16 L -12,16 Z"/>
|
||||
<path d="M -19,-6 L -19,-32 L -41,-32 L -34,-6 L -19,-6 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Add subtle texture lines -->
|
||||
<g stroke="#000000" stroke-width="0.5" opacity="0.3">
|
||||
<circle cx="0" cy="0" r="35" fill="none"/>
|
||||
<circle cx="0" cy="0" r="25" fill="none"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Enhanced text with better typography -->
|
||||
<text x="96" y="165" font-family="Arial, sans-serif" font-size="16" font-weight="900"
|
||||
text-anchor="middle" fill="#000000" letter-spacing="1">FC CLUB</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -1,25 +1 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
{"short_name": "Fotbal Club", "name": "Fotbal Club - Oficiální aplikace", "description": "Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie", "icons": [{"src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon"}, {"src": "logo192.png", "type": "image/png", "sizes": "192x192"}, {"src": "logo512.png", "type": "image/png", "sizes": "512x512"}], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff"}
|
||||
|
||||
|
After Width: | Height: | Size: 958 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,42 @@
|
||||
<svg width="192" height="192" viewBox="0 0 192 192" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Clean white background -->
|
||||
<rect width="192" height="192" fill="#ffffff"/>
|
||||
|
||||
<!-- Enhanced Player Silhouette -->
|
||||
<g transform="translate(96,96)">
|
||||
<!-- Athletic pose silhouette -->
|
||||
<g fill="#000000">
|
||||
<!-- Head -->
|
||||
<circle cx="0" cy="-28" r="14"/>
|
||||
|
||||
<!-- Body with athletic build -->
|
||||
<path d="M -10,-14 L -7,8 L -4,30 L 4,30 L 7,8 L 10,-14 Z"/>
|
||||
|
||||
<!-- Defined arms in athletic position -->
|
||||
<path d="M -10,-10 L -22,-8 L -24,2 L -18,6 L -10,2 M 10,-10 L 22,-8 L 24,2 L 18,6 L 10,2"/>
|
||||
|
||||
<!-- Strong legs in running stance -->
|
||||
<path d="M -4,30 L -8,52 L -14,52 M 4,30 L 8,52 L 14,52"/>
|
||||
|
||||
<!-- Muscle definition lines -->
|
||||
<g stroke="#ffffff" stroke-width="1" fill="none">
|
||||
<line x1="-7" y1="-5" x2="-5" y2="5"/>
|
||||
<line x1="7" y1="-5" x2="5" y2="5"/>
|
||||
<line x1="-4" y1="15" x2="-4" y2="25"/>
|
||||
<line x1="4" y1="15" x2="4" y2="25"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Motion lines -->
|
||||
<g stroke="#000000" stroke-width="2" opacity="0.3">
|
||||
<line x1="-30" y1="-20" x2="-20" y2="-18"/>
|
||||
<line x1="-32" y1="-10" x2="-22" y2="-8"/>
|
||||
<line x1="30" y1="-20" x2="20" y2="-18"/>
|
||||
<line x1="32" y1="-10" x2="22" y2="-8"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Enhanced typography -->
|
||||
<text x="96" y="165" font-family="Arial, sans-serif" font-size="14" font-weight="900"
|
||||
text-anchor="middle" fill="#000000" letter-spacing="2">PLAYER</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,9 +1,13 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// Service Worker for PWA support and offline functionality
|
||||
|
||||
const CACHE_VERSION = 'v1.0.1';
|
||||
const CACHE_VERSION = 'v1.0.2';
|
||||
const CACHE_NAME = `fotbal-club-cache-${CACHE_VERSION}`;
|
||||
|
||||
// Rate limiting for background updates
|
||||
const BACKGROUND_UPDATE_INTERVAL = 5000; // 5 seconds minimum between updates
|
||||
const lastBackgroundUpdates = new Map();
|
||||
|
||||
// Assets to cache on install
|
||||
const STATIC_ASSETS = [
|
||||
'/',
|
||||
@@ -84,6 +88,11 @@ self.addEventListener('fetch', (event) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip background update requests to prevent infinite loops
|
||||
if (request.headers.get('X-SW-Background-Update') === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle SPA navigations with app shell fallback
|
||||
if (request.mode === 'navigate') {
|
||||
event.respondWith(handleNavigationRequest(request));
|
||||
@@ -106,8 +115,16 @@ async function handleStaticRequest(request) {
|
||||
// Try cache first
|
||||
const cachedResponse = await caches.match(request);
|
||||
if (cachedResponse) {
|
||||
// Return cached response and update in background
|
||||
fetchAndUpdateCache(request);
|
||||
// For static assets with long cache headers, don't update in background
|
||||
const url = new URL(request.url);
|
||||
const isStaticAsset = url.pathname.match(/\.(png|jpg|jpeg|gif|svg|webp|ico|woff|woff2|ttf|eot)$/);
|
||||
const hasLongCache = cachedResponse.headers.get('cache-control')?.includes('max-age=31536000');
|
||||
|
||||
// Only update in background if it's not a static asset with long cache
|
||||
if (!isStaticAsset || !hasLongCache) {
|
||||
fetchAndUpdateCache(request);
|
||||
}
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
@@ -198,9 +215,28 @@ async function handleAPIRequest(request) {
|
||||
// Update cache in background
|
||||
async function fetchAndUpdateCache(request) {
|
||||
try {
|
||||
const response = await fetch(request);
|
||||
// Skip if this is already a background update request to prevent infinite loops
|
||||
if (request.headers.get('X-SW-Background-Update') === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rate limit background updates to prevent excessive requests
|
||||
const now = Date.now();
|
||||
const lastUpdate = lastBackgroundUpdates.get(request.url);
|
||||
if (lastUpdate && (now - lastUpdate) < BACKGROUND_UPDATE_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
lastBackgroundUpdates.set(request.url, now);
|
||||
|
||||
// Use fetch with cache: 'no-store' to bypass service worker and avoid infinite loops
|
||||
const response = await fetch(request.url, {
|
||||
cache: 'no-store',
|
||||
headers: { 'X-SW-Background-Update': 'true' }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const cache = await caches.open(CACHE_NAME);
|
||||
// Use the original request as key, but the new response
|
||||
cache.put(request, response);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<svg width="192" height="192" viewBox="0 0 192 192" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Clean white background -->
|
||||
<rect width="192" height="192" fill="#ffffff"/>
|
||||
|
||||
<!-- Enhanced Sponsor/Partner placeholder -->
|
||||
<g transform="translate(96,96)">
|
||||
<!-- Premium shield shape with better proportions -->
|
||||
<g>
|
||||
<!-- Shadow -->
|
||||
<path d="M 2,-47 L 37,-27 L 37,12 L 2,47 L -33,12 L -33,-27 Z"
|
||||
fill="#000000" opacity="0.1"/>
|
||||
<!-- Main shield -->
|
||||
<path d="M 0,-45 L 35,-25 L 35,10 L 0,45 L -35,10 L -35,-25 Z"
|
||||
fill="#ffffff" stroke="#000000" stroke-width="3"/>
|
||||
|
||||
<!-- Inner decorative border -->
|
||||
<path d="M 0,-38 L 28,-20 L 28,8 L 0,38 L -28,8 L -28,-20 Z"
|
||||
fill="none" stroke="#000000" stroke-width="1.5"/>
|
||||
|
||||
<!-- Enhanced star with better geometry -->
|
||||
<g transform="scale(1.2)">
|
||||
<path d="M 0,-18 L 5,-5 L 18,-3 L 9,6 L 11,19 L 0,13 L -11,19 L -9,6 L -18,-3 L -5,-5 Z"
|
||||
fill="#000000"/>
|
||||
<!-- Inner star detail -->
|
||||
<path d="M 0,-10 L 2,-3 L 9,-2 L 4,3 L 5,10 L 0,7 L -5,10 L -4,3 L -9,-2 L -2,-3 Z"
|
||||
fill="#ffffff"/>
|
||||
</g>
|
||||
|
||||
<!-- Ribbon with better design -->
|
||||
<g>
|
||||
<path d="M -12,38 L 0,48 L 12,38 L 8,45 L 0,50 L -8,45 Z" fill="#000000"/>
|
||||
<text x="0" y="44" font-family="Arial, sans-serif" font-size="8" font-weight="bold"
|
||||
text-anchor="middle" fill="#ffffff">PREMIUM</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Decorative corner elements -->
|
||||
<g stroke="#000000" stroke-width="1.5" fill="none">
|
||||
<circle cx="-25" cy="-35" r="3"/>
|
||||
<circle cx="25" cy="-35" r="3"/>
|
||||
<circle cx="-25" cy="30" r="3"/>
|
||||
<circle cx="25" cy="30" r="3"/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- Enhanced typography -->
|
||||
<text x="96" y="165" font-family="Arial, sans-serif" font-size="14" font-weight="900"
|
||||
text-anchor="middle" fill="#000000" letter-spacing="2">SPONSOR</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.1 KiB |