2026-01-03 16:57:14 -08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="en">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<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'; frame-ancestors 'none'">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<meta name="theme-color" content="#007acc">
|
|
|
|
|
|
<meta name="description" content="Remote macro control for your desktop">
|
2026-01-03 18:25:17 -08:00
|
|
|
|
|
|
|
|
|
|
<!-- PWA / iOS specific -->
|
|
|
|
|
|
<meta name="mobile-web-app-capable" content="yes">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<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">
|
2026-01-03 18:25:17 -08:00
|
|
|
|
<meta name="application-name" content="MacroPad">
|
|
|
|
|
|
<meta name="msapplication-TileColor" content="#007acc">
|
|
|
|
|
|
<meta name="msapplication-tap-highlight" content="no">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
|
|
|
|
|
|
<title>MacroPad</title>
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="manifest" href="/manifest.json">
|
|
|
|
|
|
<link rel="icon" type="image/png" sizes="192x192" href="/static/icons/icon-192.png">
|
2026-01-03 18:25:17 -08:00
|
|
|
|
<link rel="icon" type="image/png" sizes="512x512" href="/static/icons/icon-512.png">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<link rel="apple-touch-icon" href="/static/icons/icon-192.png">
|
2026-01-03 18:25:17 -08:00
|
|
|
|
<link rel="apple-touch-icon" sizes="512x512" href="/static/icons/icon-512.png">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<link rel="stylesheet" href="/static/css/styles.css">
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<!-- Header -->
|
|
|
|
|
|
<header class="header">
|
|
|
|
|
|
<h1>MacroPad</h1>
|
|
|
|
|
|
<div class="header-actions">
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<div class="connection-status" id="connection-status" role="status" aria-live="polite">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<div class="status-dot"></div>
|
|
|
|
|
|
<span>Disconnected</span>
|
|
|
|
|
|
</div>
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<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>
|
2026-01-03 16:57:14 -08:00
|
|
|
|
</div>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Tabs -->
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<nav class="tabs" id="tabs-container" role="tablist" aria-label="Macro categories">
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<!-- Tabs rendered dynamically -->
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Macro Grid -->
|
|
|
|
|
|
<main class="macro-grid" id="macro-grid">
|
|
|
|
|
|
<div class="loading">
|
|
|
|
|
|
<div class="spinner"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<!-- 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>
|
|
|
|
|
|
|
2026-01-03 16:57:14 -08:00
|
|
|
|
<!-- Toast Container -->
|
2026-07-17 10:24:14 -07:00
|
|
|
|
<div class="toast-container" id="toast-container" role="status" aria-live="polite"></div>
|
2026-01-03 16:57:14 -08:00
|
|
|
|
|
|
|
|
|
|
<script src="/static/js/app.js"></script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|