Fix for margins on iOS PWA
2
.gitignore
vendored
@@ -44,7 +44,7 @@ frontend/app/yarn-debug.log*
|
||||
frontend/app/yarn-error.log*
|
||||
frontend/app/pnpm-debug.log*
|
||||
frontend/app/lerna-debug.log*
|
||||
|
||||
frontend/app/dev-dist
|
||||
frontend/app/node_modules
|
||||
frontend/app/.DS_Store
|
||||
frontend/app/dist
|
||||
|
||||
@@ -2,39 +2,37 @@
|
||||
<html class="bg-body" data-bs-theme="dark" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/logo/logo.png">
|
||||
<link rel="apple-touch-icon" href="/logo/logo.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<meta name="theme-color" content="#212529">
|
||||
<title>Endurain</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<meta name="description" content="A self-hosted fitness tracking service">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#212529" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" href="/logo/favicon.ico">
|
||||
<link rel="icon" href="/logo/favicon-32x32.png" type="image/png" sizes="32x32">
|
||||
<link rel="icon" href="/logo/favicon-16x16.png" type="image/png" sizes="16x16">
|
||||
<link rel="apple-touch-icon" href="/logo/apple-touch-icon.png">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script>
|
||||
// Function to update theme-color meta tag
|
||||
function updateThemeColor(isDark) {
|
||||
const metaThemeColor = document.querySelector('meta[name="theme-color"]');
|
||||
metaThemeColor.setAttribute('content', isDark ? '#212529' : '#ffffff');
|
||||
}
|
||||
|
||||
// Detects if the user has set their system to use dark mode
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
// Applies dark theme by setting data-bs-theme="dark"
|
||||
document.documentElement.setAttribute('data-bs-theme', 'dark');
|
||||
updateThemeColor(true);
|
||||
} else {
|
||||
// Applies light theme or removes the attribute for default behavior
|
||||
document.documentElement.setAttribute('data-bs-theme', 'light');
|
||||
updateThemeColor(false);
|
||||
}
|
||||
|
||||
// Optional: Listen for changes in the preference and adjust on the fly
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
const newColorScheme = event.matches ? "dark" : "light";
|
||||
document.documentElement.setAttribute('data-bs-theme', newColorScheme);
|
||||
updateThemeColor(event.matches);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
BIN
frontend/app/public/logo/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
frontend/app/public/logo/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 393 B |
BIN
frontend/app/public/logo/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 719 B |
BIN
frontend/app/public/logo/favicon.ico
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
frontend/app/public/logo/pwa-192x192.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
frontend/app/public/logo/pwa-512x512.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
frontend/app/public/logo/pwa-maskable-192x192.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
frontend/app/public/logo/pwa-maskable-512x512.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
@@ -36,9 +36,13 @@ import {
|
||||
|
||||
<style>
|
||||
.safe-area-container {
|
||||
display: block;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
padding-left: env(safe-area-inset-left);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,10 @@ import { useAuthStore } from "./stores/authStore";
|
||||
import { useThemeStore } from "./stores/themeStore";
|
||||
import { useServerSettingsStore } from "./stores/serverSettingsStore";
|
||||
|
||||
// PWA service worker registration (required for `injectRegister: 'auto'`)
|
||||
import { registerSW } from 'virtual:pwa-register';
|
||||
registerSW();
|
||||
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "bootstrap/dist/js/bootstrap.bundle.min.js";
|
||||
|
||||
|
||||
@@ -10,10 +10,76 @@ export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
strategies: 'generateSW',
|
||||
injectRegister: 'auto',
|
||||
minify: true,
|
||||
manifest: {
|
||||
name: 'Endurain',
|
||||
short_name: 'Endurain',
|
||||
description: 'A self-hosted fitness tracking service',
|
||||
start_url: '/',
|
||||
display: 'standalone',
|
||||
background_color: '#212529',
|
||||
theme_color: '#FFFFFF',
|
||||
icons: [
|
||||
{
|
||||
src: '/logo/pwa-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'any'
|
||||
},
|
||||
{
|
||||
src: '/logo/pwa-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any'
|
||||
},
|
||||
{
|
||||
src: '/logo/logo-512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any'
|
||||
},
|
||||
{
|
||||
src: '/logo/pwa-maskable-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable'
|
||||
},
|
||||
{
|
||||
src: '/logo/pwa-maskable-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable'
|
||||
}
|
||||
]
|
||||
},
|
||||
workbox: {
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
|
||||
clientsClaim: true,
|
||||
skipWaiting: true,
|
||||
sourcemap: false,
|
||||
navigateFallback: '/',
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: ({ url }) => /^\/api\/v1(?:\/|$)/.test(url.pathname),
|
||||
handler: 'NetworkFirst',
|
||||
options: {
|
||||
cacheName: 'api-cache',
|
||||
expiration: {
|
||||
maxEntries: 100,
|
||||
maxAgeSeconds: 86400
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
registerType: 'autoUpdate' ,
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
type: 'module',
|
||||
}
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
|
||||