added button

This commit is contained in:
2026-03-31 11:15:17 +05:30
parent de7ce040c8
commit fd7571c936
3 changed files with 120 additions and 40 deletions

31
public/sw.js Normal file
View File

@@ -0,0 +1,31 @@
const CACHE = 'gj-v1'
self.addEventListener('install', (e) => {
e.waitUntil(
caches.open(CACHE).then((cache) =>
cache.addAll(['/', '/manifest.json', '/icon.svg'])
)
)
self.skipWaiting()
})
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))
)
)
self.clients.claim()
})
self.addEventListener('fetch', (e) => {
// Only cache GET requests for same-origin non-API resources
if (
e.request.method !== 'GET' ||
e.request.url.includes('/api/')
) return
e.respondWith(
caches.match(e.request).then((cached) => cached || fetch(e.request))
)
})

View File

@@ -3,6 +3,12 @@ import { createRoot } from 'react-dom/client'
import './index.css' import './index.css'
import App from './App.tsx' import App from './App.tsx'
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
})
}
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<StrictMode> <StrictMode>
<App /> <App />

View File

@@ -53,7 +53,7 @@ export default function SettingsPage() {
const navigate = useNavigate() const navigate = useNavigate()
const fileInputRef = useRef<HTMLInputElement>(null) const fileInputRef = useRef<HTMLInputElement>(null)
const { canInstall, isIOS, isInstalled, triggerInstall } = usePWAInstall() const { canInstall, isIOS, isInstalled, triggerInstall } = usePWAInstall()
const [showIOSModal, setShowIOSModal] = useState(false) const [installModal, setInstallModal] = useState<'ios' | 'chrome' | null>(null)
// Edit profile modal state // Edit profile modal state
const [showEditModal, setShowEditModal] = useState(false) const [showEditModal, setShowEditModal] = useState(false)
@@ -286,14 +286,21 @@ export default function SettingsPage() {
</section> </section>
{/* App */} {/* App */}
{!isInstalled && (isIOS || canInstall) && ( <section className="settings-section">
<section className="settings-section">
<h3 className="settings-section-title">APP</h3> <h3 className="settings-section-title">APP</h3>
<div className="settings-card"> <div className="settings-card">
<button <button
type="button" type="button"
className="settings-item settings-item-button" className="settings-item settings-item-button"
onClick={() => isIOS ? setShowIOSModal(true) : triggerInstall()} onClick={() => {
if (isIOS) {
setInstallModal('ios')
} else if (canInstall) {
triggerInstall()
} else {
setInstallModal('chrome')
}
}}
> >
<div className="settings-item-icon settings-item-icon-purple"> <div className="settings-item-icon settings-item-icon-purple">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
@@ -311,7 +318,6 @@ export default function SettingsPage() {
</button> </button>
</div> </div>
</section> </section>
)}
{/* Data & Look */} {/* Data & Look */}
<section className="settings-section"> <section className="settings-section">
@@ -526,48 +532,85 @@ export default function SettingsPage() {
</div> </div>
)} )}
{/* iOS "Add to Home Screen" instructions modal */} {/* Add to Home Screen instructions modal */}
{showIOSModal && ( {installModal && (
<div className="confirm-modal-overlay" onClick={() => setShowIOSModal(false)}> <div className="confirm-modal-overlay" onClick={() => setInstallModal(null)}>
<div className="confirm-modal ios-install-modal" onClick={(e) => e.stopPropagation()}> <div className="confirm-modal ios-install-modal" onClick={(e) => e.stopPropagation()}>
<div className="ios-install-icon">🌱</div> <div className="ios-install-icon">🌱</div>
<h3 className="confirm-modal-title">Add to Home Screen</h3> <h3 className="confirm-modal-title">Add to Home Screen</h3>
<p className="ios-install-subtitle">Follow these steps in Safari:</p>
<ol className="ios-install-steps"> {installModal === 'ios' ? (
<li> <>
<span className="ios-install-step-icon"> <p className="ios-install-subtitle">Follow these steps in Safari:</p>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> <ol className="ios-install-steps">
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> <li>
<polyline points="16 6 12 2 8 6" /> <span className="ios-install-step-icon">
<line x1="12" y1="2" x2="12" y2="15" /> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
</svg> <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" />
</span> <polyline points="16 6 12 2 8 6" />
Tap the <strong>Share</strong> button at the bottom of Safari <line x1="12" y1="2" x2="12" y2="15" />
</li> </svg>
<li> </span>
<span className="ios-install-step-icon"> Tap the <strong>Share</strong> button at the bottom of Safari
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> </li>
<rect x="3" y="3" width="18" height="18" rx="2" /> <li>
<line x1="12" y1="8" x2="12" y2="16" /> <span className="ios-install-step-icon">
<line x1="8" y1="12" x2="16" y2="12" /> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
</svg> <rect x="3" y="3" width="18" height="18" rx="2" />
</span> <line x1="12" y1="8" x2="12" y2="16" />
Scroll down and tap <strong>Add to Home Screen</strong> <line x1="8" y1="12" x2="16" y2="12" />
</li> </svg>
<li> </span>
<span className="ios-install-step-icon"> Scroll down and tap <strong>Add to Home Screen</strong>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> </li>
<polyline points="20 6 9 17 4 12" /> <li>
</svg> <span className="ios-install-step-icon">
</span> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
Tap <strong>Add</strong> to confirm <polyline points="20 6 9 17 4 12" />
</li> </svg>
</ol> </span>
Tap <strong>Add</strong> to confirm
</li>
</ol>
</>
) : (
<>
<p className="ios-install-subtitle">Follow these steps in Chrome:</p>
<ol className="ios-install-steps">
<li>
<span className="ios-install-step-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" />
</svg>
</span>
Tap the <strong> menu</strong> in the top-right corner
</li>
<li>
<span className="ios-install-step-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="5" y="2" width="14" height="20" rx="2" ry="2" />
<line x1="12" y1="18" x2="12.01" y2="18" />
</svg>
</span>
Tap <strong>Add to Home screen</strong>
</li>
<li>
<span className="ios-install-step-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polyline points="20 6 9 17 4 12" />
</svg>
</span>
Tap <strong>Add</strong> to confirm
</li>
</ol>
</>
)}
<button <button
type="button" type="button"
className="edit-modal-save" className="edit-modal-save"
style={{ width: '100%', marginTop: '1rem' }} style={{ width: '100%', marginTop: '1rem' }}
onClick={() => setShowIOSModal(false)} onClick={() => setInstallModal(null)}
> >
Got it Got it
</button> </button>