mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-17 23:53:58 -06:00
v1
This commit is contained in:
parent
2d4af97f67
commit
38fd41324d
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 425 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 425 KiB |
|
|
@ -2,8 +2,17 @@
|
|||
body {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
font-family: 'Michroma', sans-serif;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, .logo {
|
||||
font-family: 'Goldman', sans-serif;
|
||||
}
|
||||
|
||||
/* Responsiveness Utility Classes */
|
||||
@media (max-width: 767px) { .show-on-desktop { display: none !important; } }
|
||||
@media (min-width: 768px) { .show-on-mobile { display: none !important; } }
|
||||
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
height: 100vh;
|
||||
|
|
@ -305,6 +314,17 @@ body {
|
|||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
background: rgba(17, 17, 19, 0.8);
|
||||
backdrop-filter: blur(16px);
|
||||
-webkit-backdrop-filter: blur(16px);
|
||||
padding: 16px 32px;
|
||||
margin-left: -32px;
|
||||
margin-right: -32px;
|
||||
margin-top: -24px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
|
|
@ -321,7 +341,7 @@ body {
|
|||
/* Buttons */
|
||||
.btn {
|
||||
padding: 8px 16px;
|
||||
border-radius: var(--radius);
|
||||
border-radius: var(--radius-xl);
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
transition: all var(--transition);
|
||||
|
|
@ -329,6 +349,9 @@ body {
|
|||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent);
|
||||
|
|
|
|||
|
|
@ -1,27 +1,45 @@
|
|||
:root {
|
||||
--bg-primary: #111827;
|
||||
--bg-secondary: #1f2937;
|
||||
--bg-card: #1e293b;
|
||||
--bg-card-hover: #283548;
|
||||
--bg-input: #0f172a;
|
||||
--accent: #3b82f6;
|
||||
--accent-hover: #2563eb;
|
||||
--accent-dim: #1d4ed8;
|
||||
--text-primary: #f1f5f9;
|
||||
--text-secondary: #94a3b8;
|
||||
--text-muted: #64748b;
|
||||
--success: #22c55e;
|
||||
--success-dim: #15803d;
|
||||
/* Cores de Destaque */
|
||||
--accent: #ff6b00;
|
||||
--accent-hover: #e65c00;
|
||||
--accent-dim: rgba(255, 107, 0, 0.15);
|
||||
--accent-glow: rgba(255, 107, 0, 0.35);
|
||||
|
||||
/* Sistema de Feedback */
|
||||
--success: #34d399;
|
||||
--danger: #ef4444;
|
||||
--danger-dim: #991b1b;
|
||||
--warning: #f59e0b;
|
||||
--warning-dim: #92400e;
|
||||
--border: #334155;
|
||||
--border-light: #475569;
|
||||
--radius: 8px;
|
||||
--radius-lg: 12px;
|
||||
--shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
|
||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
--warning: #fbbf24;
|
||||
|
||||
/* Borda arredondada / Glassmorphism */
|
||||
--radius-sm: 8px;
|
||||
--radius-md: 14px;
|
||||
--radius-lg: 20px;
|
||||
--radius-xl: 28px;
|
||||
|
||||
--transition: 0.22s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--sidebar-width: 220px;
|
||||
--transition: 0.2s ease;
|
||||
}
|
||||
|
||||
[data-theme="dark"], :root {
|
||||
--bg-base: #09090b;
|
||||
--bg-surface: #111113;
|
||||
--bg-card: #1a1a1e;
|
||||
--bg-card-hover: #242429;
|
||||
--bg-input: #0d0d10;
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #a1a1aa;
|
||||
--text-muted: #6b7280;
|
||||
--border: #27272a;
|
||||
--border-highlight: #3f3f46;
|
||||
--shadow: rgba(0, 0, 0, 0.5);
|
||||
|
||||
/* Mapping old variables to new ones for compatibility */
|
||||
--bg-primary: var(--bg-base);
|
||||
--bg-secondary: var(--bg-surface);
|
||||
--radius: var(--radius-sm);
|
||||
--success-dim: rgba(52, 211, 153, 0.2);
|
||||
--danger-dim: rgba(239, 68, 68, 0.2);
|
||||
--warning-dim: rgba(251, 191, 36, 0.2);
|
||||
--border-light: var(--border-highlight);
|
||||
--shadow-sm: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html data-theme="dark" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="theme-color" content="#111827">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="theme-color" content="#ff6b00">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="icon" href="/assets/icon-192.png">
|
||||
<link rel="apple-touch-icon" href="/assets/icon-192.png">
|
||||
<title>ScreenTinker</title>
|
||||
<title>GoldenSignage</title>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Goldman:wght@400;700&family=Michroma&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="/css/variables.css">
|
||||
<link rel="stylesheet" href="/css/reset.css">
|
||||
<link rel="stylesheet" href="/css/main.css">
|
||||
|
|
@ -30,7 +35,7 @@
|
|||
<line x1="8" y1="21" x2="16" y2="21"/>
|
||||
<line x1="12" y1="17" x2="12" y2="21"/>
|
||||
</svg>
|
||||
<span id="brandName">ScreenTinker</span>
|
||||
<span id="brandName">GoldenSignage</span>
|
||||
</div>
|
||||
<!-- #38: apply cached white-label before first paint (no ScreenTinker flash) -->
|
||||
<script src="/js/brand-prime.js"></script>
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ window.addEventListener('hashchange', () => { if (isAuthenticated()) refreshCurr
|
|||
|
||||
// Register PWA service worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw-admin.js').catch(() => {});
|
||||
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
||||
}
|
||||
|
||||
// Mobile sidebar: open/close via hamburger, backdrop, nav tap, Escape
|
||||
|
|
@ -640,3 +640,45 @@ document.addEventListener('click', (e) => {
|
|||
const modal = document.getElementById(id);
|
||||
if (modal) modal.style.display = 'none';
|
||||
});
|
||||
|
||||
// Custom Pull-to-Refresh logic for mobile PWA standalone
|
||||
let pwaTouchStartY = 0;
|
||||
let pwaIsPulling = false;
|
||||
|
||||
document.addEventListener('touchstart', (e) => {
|
||||
// Only start pull-to-refresh if we are at the very top of the page
|
||||
const scrollElement = document.querySelector('.content') || document.documentElement;
|
||||
if (scrollElement.scrollTop === 0) {
|
||||
pwaTouchStartY = e.changedTouches[0].screenY;
|
||||
pwaIsPulling = true;
|
||||
} else {
|
||||
pwaIsPulling = false;
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
document.addEventListener('touchend', (e) => {
|
||||
if (!pwaIsPulling) return;
|
||||
const pwaTouchEndY = e.changedTouches[0].screenY;
|
||||
|
||||
if (pwaTouchEndY - pwaTouchStartY > 150) {
|
||||
if ('caches' in window) {
|
||||
caches.keys().then((names) => {
|
||||
Promise.all(names.map(name => caches.delete(name)))
|
||||
.then(() => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.getRegistrations().then((registrations) => {
|
||||
for (let registration of registrations) {
|
||||
registration.unregister();
|
||||
}
|
||||
window.location.reload(true);
|
||||
});
|
||||
} else {
|
||||
window.location.reload(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
window.location.reload(true);
|
||||
}
|
||||
}
|
||||
}, { passive: true });
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "ScreenTinker",
|
||||
"short_name": "ScreenTinker",
|
||||
"name": "GoldenSignage",
|
||||
"short_name": "GoldenSignage",
|
||||
"description": "Digital Signage Management",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#111827",
|
||||
"theme_color": "#3B82F6",
|
||||
"background_color": "#09090b",
|
||||
"theme_color": "#ff6b00",
|
||||
"orientation": "any",
|
||||
"icons": [
|
||||
{
|
||||
|
|
|
|||
54
frontend/sw.js
Normal file
54
frontend/sw.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
const CACHE_NAME = 'goldensignage-v1';
|
||||
const ASSETS_TO_CACHE = [
|
||||
'/',
|
||||
'/index.html',
|
||||
'/manifest.json',
|
||||
'/css/reset.css',
|
||||
'/css/variables.css',
|
||||
'/css/main.css',
|
||||
'/js/app.js',
|
||||
'/assets/icon-192.png',
|
||||
'/assets/icon-512.png',
|
||||
'https://fonts.googleapis.com/css2?family=Goldman:wght@400;700&family=Michroma&display=swap'
|
||||
];
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME).then((cache) => {
|
||||
return cache.addAll(ASSETS_TO_CACHE);
|
||||
})
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((cacheNames) => {
|
||||
return Promise.all(
|
||||
cacheNames.map((cacheName) => {
|
||||
if (cacheName !== CACHE_NAME) {
|
||||
return caches.delete(cacheName);
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
// Cache-First Strategy
|
||||
event.respondWith(
|
||||
caches.match(event.request).then((cachedResponse) => {
|
||||
if (cachedResponse) {
|
||||
return cachedResponse;
|
||||
}
|
||||
return fetch(event.request).then((networkResponse) => {
|
||||
// Cache dynamic assets if needed, but for now just return network response
|
||||
return networkResponse;
|
||||
}).catch(() => {
|
||||
// Handle offline fallback if needed
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
Loading…
Reference in a new issue