feather-reader 0.2.4

A minimalist, atproto-native RSS/Atom reader in Rust — your feed subscriptions live in your own PDS.
Documentation
{% extends "base.html" %}

{% block title %}{{ heading }} — FeatherReader{% endblock %}

{% block body %}
<div class="shell" id="shell">

  <header class="topbar">
    <button class="icon-btn" id="rail-toggle" aria-label="Open navigation"
            aria-expanded="false" aria-controls="rail">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
           stroke-linecap="round" aria-hidden="true">
        <path d="M4 7h16M4 12h16M4 17h16"/>
      </svg>
    </button>
    <h1 class="topbar-title">{{ heading }} <span class="topbar-count">{{ entries.len() }}</span></h1>
    {% if !entries.is_empty() %}
      <button class="icon-btn js-mark-all" type="submit" form="mark-all-form" aria-label="Mark all read">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
             stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
          <path d="M3 13l4 4L15 9"/><path d="M9 13l4 4 8-8"/>
        </svg>
      </button>
    {% else %}
      <span class="icon-btn" aria-hidden="true"></span>
    {% endif %}
  </header>

  <button class="scrim" id="scrim" tabindex="-1" aria-hidden="true"></button>

  {% include "rail.html" %}

  <main class="content" id="content">
    {% if !flash.is_empty() %}
      <p class="flash" role="status">{{ flash }}</p>
    {% endif %}

    <div class="content-head">
      <h1 class="content-title">{{ heading }}</h1>
      <span class="content-count">{{ entries.len() }} entries</span>
      <span class="content-spacer"></span>
      {% if !entries.is_empty() %}
        <form id="mark-all-form" method="post"
              action="/read-all{% if let Some(f) = feed_scope %}?feed={{ f|urlencode }}{% endif %}">
          <button class="btn-quiet js-mark-all" type="submit">Mark all read</button>
        </form>
      {% endif %}
    </div>

    {% if entries.is_empty() %}
      <div class="empty">
        <svg class="empty-mark" viewBox="0 0 32 32" fill="currentColor" aria-hidden="true">
          <g transform="translate(16 16) scale(1.07) translate(-16 -16)">
            <path fill-rule="evenodd" d="M29.00 2.60 L29.35 3.46 L29.51 4.19 L29.61 4.90 L29.67 5.58 L29.69 6.26 L29.68 6.91 L29.65 7.56 L29.59 8.21 L29.51 8.84 L29.41 9.47 L29.29 10.09 L29.16 10.70 L29.00 11.31 L28.83 11.91 L28.63 12.51 L28.43 13.10 L28.20 13.68 L27.96 14.26 L27.70 14.83 L27.43 15.39 L27.14 15.95 L26.84 16.49 L26.52 17.04 L26.18 17.57 L25.83 18.10 L25.46 18.61 L25.08 19.12 L24.68 19.62 L24.26 20.11 L23.83 20.59 L23.38 21.06 L22.91 21.51 L22.43 21.95 L21.92 22.38 L21.39 22.80 L20.85 23.19 L20.28 23.57 L19.69 23.93 L19.07 24.27 L18.42 24.58 L17.74 24.86 L17.02 25.10 L16.26 25.30 L15.44 25.44 L14.55 25.50 L13.54 25.44 L12.33 25.15 L9.80 23.40 L9.80 23.40 L8.96 21.44 L9.13 20.62 L9.42 19.94 L9.77 19.33 L10.15 18.76 L10.55 18.22 L10.97 17.71 L11.41 17.22 L11.85 16.75 L12.29 16.29 L12.75 15.84 L13.20 15.41 L13.66 14.98 L14.13 14.57 L14.59 14.16 L15.06 13.76 L15.53 13.36 L15.99 12.97 L16.46 12.59 L16.93 12.21 L17.40 11.84 L17.86 11.47 L18.33 11.11 L18.79 10.74 L19.25 10.39 L19.71 10.03 L20.17 9.68 L20.63 9.34 L21.08 8.99 L21.53 8.65 L21.98 8.31 L22.43 7.97 L22.88 7.63 L23.32 7.30 L23.75 6.96 L24.19 6.63 L24.62 6.30 L25.05 5.97 L25.47 5.64 L25.89 5.30 L26.30 4.97 L26.71 4.64 L27.12 4.31 L27.51 3.98 L27.90 3.64 L28.28 3.30 L28.65 2.96 L29.00 2.60 Z M28.02 4.87 L27.75 5.22 L27.48 5.58 L27.20 5.94 L26.92 6.30 L26.63 6.66 L26.35 7.02 L26.05 7.38 L25.76 7.75 L25.46 8.11 L25.15 8.48 L24.85 8.85 L24.54 9.21 L24.22 9.58 L23.90 9.95 L23.58 10.32 L23.26 10.69 L22.93 11.07 L22.60 11.44 L22.26 11.82 L21.92 12.19 L21.58 12.57 L21.23 12.95 L20.88 13.33 L20.52 13.71 L20.16 14.09 L19.80 14.47 L19.44 14.85 L19.07 15.24 L18.69 15.62 L18.32 16.01 L17.94 16.40 L17.55 16.78 L17.17 17.17 L16.77 17.56 L16.38 17.95 L15.98 18.35 L15.58 18.74 L15.17 19.13 L14.76 19.53 L14.35 19.93 L13.93 20.32 L13.51 20.72 L13.09 21.12 L12.66 21.52 L12.23 21.92 L11.79 22.33 L11.35 22.73 L10.91 23.14 L10.17 22.32 L10.61 21.92 L11.05 21.52 L11.48 21.12 L11.91 20.72 L12.33 20.32 L12.76 19.92 L13.17 19.53 L13.59 19.13 L14.00 18.74 L14.41 18.34 L14.81 17.95 L15.21 17.56 L15.61 17.17 L16.00 16.78 L16.39 16.40 L16.77 16.01 L17.15 15.62 L17.53 15.24 L17.91 14.85 L18.28 14.47 L18.64 14.09 L19.01 13.71 L19.36 13.33 L19.72 12.95 L20.07 12.58 L20.42 12.20 L20.76 11.83 L21.10 11.45 L21.44 11.08 L21.78 10.71 L22.11 10.34 L22.43 9.97 L22.75 9.60 L23.07 9.23 L23.39 8.87 L23.70 8.50 L24.01 8.14 L24.31 7.77 L24.61 7.41 L24.91 7.05 L25.20 6.69 L25.49 6.33 L25.77 5.98 L26.06 5.62 L26.33 5.26 L26.61 4.91 L26.88 4.56 L27.14 4.20 Z M24.61 9.81 L28.83 10.21 L28.91 9.37 L24.69 8.98 Z M20.90 13.94 L26.20 14.68 L26.31 13.85 L21.02 13.11 Z M16.76 18.20 L22.11 19.16 L22.26 18.34 L16.91 17.37 Z M22.15 10.35 L21.77 8.76 L20.96 8.95 L21.33 10.54 Z M18.29 14.52 L17.86 12.31 L17.04 12.46 L17.46 14.68 Z"/>
            <path d="M9.80 23.40 Q7.28 25.68 5.95 27.69" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" fill="none"/>
          </g>
        </svg>
        <h2 class="empty-title">All caught up</h2>
        <p class="empty-note">Nothing unread. The quiet is the point.</p>
      </div>
    {% else %}
      <ul class="entry-list" id="entry-list">
        {% for e in entries %}
          {% include "entry_row.html" %}
        {% endfor %}
      </ul>
    {% endif %}

    {% include "footer.html" %}
  </main>
</div>

{% include "overlay.html" %}
{% endblock %}