Files
nextsnap/app/routes/views.py
kamaji 37f417eb5b Fix SW scope to intercept page navigations for offline support
The SW was served from /static/sw.js with default scope /static/,
so it only intercepted static asset requests. Page navigations to
/capture, /queue, /browser were not handled by the SW at all —
Safari showed its native offline error.

Fix: serve SW from /sw.js route with Service-Worker-Allowed: / header
and register with scope: /. Now the SW intercepts all navigations and
serves the offline fallback page when the network is unavailable.

Also remove auth-protected page routes from precache (they would cache
the login redirect). Pages are cached via network-first on visit instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 22:16:07 -06:00

97 lines
2.8 KiB
Python

from flask import Blueprint, render_template, redirect, url_for, session, jsonify, send_from_directory, current_app
bp = Blueprint('views', __name__)
@bp.route('/sw.js')
def service_worker():
"""Serve service worker from root scope."""
response = send_from_directory(
current_app.static_folder, 'sw.js',
mimetype='application/javascript'
)
response.headers['Service-Worker-Allowed'] = '/'
response.headers['Cache-Control'] = 'no-cache'
return response
@bp.route('/')
def index():
"""Root route - redirect to capture if logged in, otherwise show login."""
if 'username' in session:
return redirect(url_for('views.capture'))
return render_template('login.html')
@bp.route('/login')
def login_page():
"""Render login page."""
if 'username' in session:
return redirect(url_for('views.capture'))
return render_template('login.html')
@bp.route('/capture')
def capture():
"""Render capture page (requires authentication)."""
if 'username' not in session:
return redirect(url_for('views.login_page'))
return render_template(
'capture.html',
username=session['username'],
show_nav=True,
is_admin=session.get('is_admin', False)
)
@bp.route('/queue')
def queue():
"""Render queue page (requires authentication)."""
if 'username' not in session:
return redirect(url_for('views.login_page'))
return render_template(
'queue.html',
username=session['username'],
show_nav=True,
is_admin=session.get('is_admin', False)
)
@bp.route('/browser')
def browser():
"""Render file browser page (requires authentication)."""
if 'username' not in session:
return redirect(url_for('views.login_page'))
return render_template(
'browser.html',
username=session['username'],
show_nav=True,
is_admin=session.get('is_admin', False)
)
@bp.route('/reviewer')
def reviewer():
"""Render photo reviewer page (requires authentication)."""
if 'username' not in session:
return redirect(url_for('views.login_page'))
return render_template(
'reviewer.html',
username=session['username'],
show_nav=False,
is_admin=session.get('is_admin', False)
)
@bp.route('/admin')
def admin():
"""Render admin page (requires admin privileges)."""
if 'username' not in session:
return redirect(url_for('views.login_page'))
if not session.get('is_admin', False):
return "Access denied: Admin privileges required", 403
return render_template(
'admin.html',
username=session['username'],
show_nav=True,
is_admin=True
)
@bp.route('/test')
def test():
"""Test page for camera functionality."""
return render_template('test.html')