Files
espresso_frame/server/app/templates/app_base.html
T
tfaour acdb929a99
Build and push server image / build-and-push (push) Successful in 50s
Move mode picker below device status bar; fix invisible calendar lines; add CalDAV calendar support
Calendar rule/grid lines were light gray, which dithers away to
near-invisible on the 6-color e-ink palette -- now black.

CalDAV accounts (Nextcloud, Fastmail, iCloud, ...) can now be linked
alongside the existing single ICS subscription, since one account can
expose several calendars. A frame's Calendar tab now lists calendars
per person rather than one opt-in per person: your own row shows every
calendar you have available with a full add/remove toggle, while other
linked users' rows show only calendars they've included, toggleable
off (mute) but not on -- only a calendar's owner can add it to a
shared frame. FrameCalendar replaces the old single-boolean
UserFrame.calendar_included; existing opt-ins are migrated forward.
2026-07-22 22:01:05 -04:00

87 lines
3.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}ESPresso Frame{% endblock %}</title>
{% if csrf_token %}<meta name="csrf-token" content="{{ csrf_token }}">{% endif %}
<script>
// Applied before first paint so there's no flash of the wrong theme.
(function () {
try {
var stored = localStorage.getItem('theme');
if (stored === 'light' || stored === 'dark') {
document.documentElement.setAttribute('data-theme', stored);
}
} catch (e) { /* localStorage unavailable (private mode, etc.) */ }
})();
</script>
<link rel="stylesheet" href="/static/theme.css">
{% block extra_head %}{% endblock %}
</head>
<body>
<div class="shell">
<div class="sidebar-backdrop"></div>
<aside class="sidebar">
<div class="brand">
<span class="brand-mark" aria-hidden="true"></span>
<h1>ESPresso Frame</h1>
</div>
<div class="sidebar-section">Frames</div>
{% for f in sidebar_frames %}
<a class="nav-item {% if active_frame and active_frame.id == f.id %}active{% endif %} {% if f.recently_seen %}online{% endif %}"
href="/frames/{{ f.id }}">
<span class="frame-dot" aria-hidden="true"></span>
{{ f.name or ("Frame " ~ f.id) }}
{% if f.owner_user_id is none %}
<span class="nav-sub">unclaimed</span>
{% elif f.battery_percent >= 0 %}
<span class="nav-sub battery-badge" title="Battery">🔋{{ f.battery_percent }}%</span>
{% endif %}
</a>
{% endfor %}
{% if not sidebar_frames %}
<p class="sub" style="padding: 0 10px;">No frames yet.</p>
{% endif %}
<div class="sidebar-footer">
<a class="nav-item {% if active_nav == 'settings' %}active{% endif %}" href="/settings">Settings</a>
{% if user.is_admin %}
<a class="nav-item {% if active_nav == 'admin' %}active{% endif %}" href="/admin">Admin</a>
{% endif %}
<form method="post" action="/logout">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" class="linklike">Log out</button>
</form>
</div>
</aside>
<div class="main-wrap" style="flex: 1; min-width: 0;">
<div class="mobile-bar">
<button type="button" id="sidebar-toggle" class="icon-btn" title="Menu" aria-label="Open menu"></button>
<div class="brand"><span aria-hidden="true"></span><h1>ESPresso Frame</h1></div>
<div class="spacer"></div>
</div>
<main class="main">
<div class="page-head">
<h1>{% block page_title %}{% endblock %}</h1>
<div class="head-actions">
{% block head_actions %}{% endblock %}
<button type="button" id="theme-toggle" class="icon-btn" title="Toggle dark mode" aria-label="Toggle dark mode">🌓</button>
</div>
</div>
{% block device_status %}{% endblock %}
{% block mode_picker %}{% endblock %}
{% block tabs %}{% endblock %}
{% block content %}{% endblock %}
</main>
</div>
</div>
<script src="/static/common.js"></script>
{% block scripts %}{% endblock %}
</body>
</html>