|
|
|
|
|
class PWAIntegration: |
|
|
""" |
|
|
Progressive Web App features for mobile enhancement |
|
|
""" |
|
|
|
|
|
@staticmethod |
|
|
def generate_manifest(): |
|
|
return { |
|
|
"name": "AI Research Assistant", |
|
|
"short_name": "ResearchAI", |
|
|
"description": "Academic AI assistant with transparent reasoning", |
|
|
"start_url": "/", |
|
|
"display": "standalone", |
|
|
"background_color": "#ffffff", |
|
|
"theme_color": "#3498db", |
|
|
"icons": [ |
|
|
{ |
|
|
"src": "/icon-192x192.png", |
|
|
"sizes": "192x192", |
|
|
"type": "image/png" |
|
|
}, |
|
|
{ |
|
|
"src": "/icon-512x512.png", |
|
|
"sizes": "512x512", |
|
|
"type": "image/png" |
|
|
} |
|
|
], |
|
|
"categories": ["education", "productivity"], |
|
|
"lang": "en-US" |
|
|
} |
|
|
|
|
|
@staticmethod |
|
|
def get_service_worker_script(): |
|
|
return """ |
|
|
const CACHE_NAME = 'research-ai-v1'; |
|
|
const urlsToCache = [ |
|
|
'/', |
|
|
'/static/css/main.css', |
|
|
'/static/js/main.js' |
|
|
]; |
|
|
|
|
|
self.addEventListener('install', (event) => { |
|
|
event.waitUntil( |
|
|
caches.open(CACHE_NAME) |
|
|
.then((cache) => cache.addAll(urlsToCache)) |
|
|
); |
|
|
}); |
|
|
|
|
|
self.addEventListener('fetch', (event) => { |
|
|
event.respondWith( |
|
|
caches.match(event.request) |
|
|
.then((response) => response || fetch(event.request)) |
|
|
); |
|
|
}); |
|
|
""" |
|
|
|
|
|
@staticmethod |
|
|
def get_pwa_html_integration(): |
|
|
""" |
|
|
Return HTML meta tags and link tags for PWA |
|
|
""" |
|
|
return """ |
|
|
<!-- PWA Meta Tags --> |
|
|
<meta name="theme-color" content="#3498db"> |
|
|
<meta name="mobile-web-app-capable" content="yes"> |
|
|
<meta name="apple-mobile-web-app-capable" content="yes"> |
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> |
|
|
<meta name="apple-mobile-web-app-title" content="ResearchAI"> |
|
|
|
|
|
<!-- PWA Manifest Link --> |
|
|
<link rel="manifest" href="/manifest.json"> |
|
|
|
|
|
<!-- Apple Touch Icon --> |
|
|
<link rel="apple-touch-icon" href="/icon-192x192.png"> |
|
|
|
|
|
<!-- PWA Registration --> |
|
|
<script> |
|
|
if ('serviceWorker' in navigator) { |
|
|
window.addEventListener('load', () => { |
|
|
navigator.serviceWorker.register('/service-worker.js') |
|
|
.then((reg) => console.log('Service Worker registered')) |
|
|
.catch((err) => console.log('Service Worker registration failed')); |
|
|
}); |
|
|
} |
|
|
</script> |
|
|
""" |
|
|
|
|
|
@staticmethod |
|
|
def get_offline_fallback(): |
|
|
""" |
|
|
Return offline fallback HTML |
|
|
""" |
|
|
return """ |
|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Offline - Research Assistant</title> |
|
|
<style> |
|
|
body { |
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
height: 100vh; |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
color: white; |
|
|
text-align: center; |
|
|
} |
|
|
.container { |
|
|
padding: 2rem; |
|
|
} |
|
|
h1 { font-size: 2rem; margin-bottom: 1rem; } |
|
|
p { font-size: 1.1rem; opacity: 0.9; } |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="container"> |
|
|
<h1>📡 Offline</h1> |
|
|
<p>You're currently offline. Please check your connection and try again.</p> |
|
|
</div> |
|
|
</body> |
|
|
</html> |
|
|
""" |
|
|
|
|
|
|