5896ec0893
frame-ancestors is ignored inside a <meta> CSP, so move clickjacking protection to real response headers (X-Frame-Options: DENY) and add X-Content-Type-Options: nosniff and Referrer-Policy: no-referrer on all responses. Drop the ineffective frame-ancestors token from the meta CSP. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
100 lines
4.8 KiB
HTML
100 lines
4.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: blob:; connect-src 'self' ws: wss:; object-src 'none'; base-uri 'none'">
|
||
<meta name="theme-color" content="#15161a" media="(prefers-color-scheme: dark)">
|
||
<meta name="theme-color" content="#eceef4" media="(prefers-color-scheme: light)">
|
||
<meta name="description" content="Remote macro control for your desktop">
|
||
|
||
<!-- PWA / iOS specific -->
|
||
<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="MacroPad">
|
||
<meta name="application-name" content="MacroPad">
|
||
<meta name="msapplication-TileColor" content="#7c5cff">
|
||
<meta name="msapplication-tap-highlight" content="no">
|
||
|
||
<title>MacroPad</title>
|
||
|
||
<link rel="manifest" href="/manifest.json">
|
||
<link rel="icon" type="image/png" sizes="192x192" href="/static/icons/icon-192.png">
|
||
<link rel="icon" type="image/png" sizes="512x512" href="/static/icons/icon-512.png">
|
||
<link rel="apple-touch-icon" href="/static/icons/icon-192.png">
|
||
<link rel="apple-touch-icon" sizes="512x512" href="/static/icons/icon-512.png">
|
||
<link rel="stylesheet" href="/static/css/styles.css">
|
||
</head>
|
||
<body>
|
||
<!-- Header -->
|
||
<header class="header">
|
||
<h1>MacroPad</h1>
|
||
<div class="header-actions">
|
||
<div class="connection-status" id="connection-status" role="status" aria-live="polite">
|
||
<div class="status-dot"></div>
|
||
<span>Disconnected</span>
|
||
</div>
|
||
<button type="button" class="wake-lock-status" id="wake-lock-status" title="Screen wake lock" aria-label="Toggle screen wake lock">
|
||
<span class="wake-icon" aria-hidden="true">☀</span>
|
||
</button>
|
||
<button type="button" class="header-btn icon-btn" id="fullscreen-btn" title="Toggle fullscreen" aria-label="Toggle fullscreen">⛶</button>
|
||
<button type="button" class="header-btn secondary" id="refresh-btn">Refresh</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Tabs -->
|
||
<nav class="tabs" id="tabs-container" role="tablist" aria-label="Macro categories">
|
||
<!-- Tabs rendered dynamically -->
|
||
</nav>
|
||
|
||
<!-- Macro Grid -->
|
||
<main class="macro-grid" id="macro-grid">
|
||
<div class="loading">
|
||
<div class="spinner"></div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Floating action button: create new macro -->
|
||
<button type="button" class="fab" id="new-macro-btn" aria-label="New macro">+</button>
|
||
|
||
<!-- Macro create/edit modal -->
|
||
<div class="modal" id="macro-modal" role="dialog" aria-modal="true" aria-labelledby="macro-modal-title" hidden>
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 id="macro-modal-title">New Macro</h2>
|
||
<button type="button" class="modal-close" id="macro-modal-close" aria-label="Close dialog">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="form-group">
|
||
<label for="macro-name-input">Name</label>
|
||
<input type="text" id="macro-name-input" autocomplete="off" placeholder="Macro name">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="macro-category-input">Category</label>
|
||
<input type="text" id="macro-category-input" autocomplete="off" list="macro-category-list" placeholder="Category (optional)">
|
||
<datalist id="macro-category-list"></datalist>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Commands</label>
|
||
<div class="command-list" id="command-list"></div>
|
||
<div class="add-command-btns">
|
||
<button type="button" class="add-command-btn" id="add-command-btn">+ Add step</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-danger" id="delete-macro-btn" hidden>Delete</button>
|
||
<button type="button" class="btn btn-secondary" id="cancel-macro-btn">Cancel</button>
|
||
<button type="button" class="btn btn-primary" id="save-macro-btn">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Toast Container -->
|
||
<div class="toast-container" id="toast-container" role="status" aria-live="polite"></div>
|
||
|
||
<script src="/static/js/app.js"></script>
|
||
</body>
|
||
</html>
|