Ctrl K
ComunidadGuías…

templates/read_mode.html

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Read Mode — Lectio</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="robots" content="noindex">
  <script>
    // Resume where you left off — Read Mode's own, separate from the main
    // app's (a different localStorage key: the two surfaces should not
    // redirect into each other, only remember their own last spot). Plain
    // page navigation here, not the main app's pane state, so there is no
    // scroll offset to restore — the URL alone is the position.
    (function () {
      var KEY = 'lectio-read-last-position';
      var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
      try {
        var raw = window.localStorage.getItem(KEY);
        if (raw && window.location.pathname === '/read' && !window.location.search) {
          var saved = JSON.parse(raw);
          if (saved && saved.url && saved.ts && Date.now() - saved.ts <= MAX_AGE_MS) {
            var target = new URL(saved.url, window.location.origin);
            if (target.origin === window.location.origin && target.search) {
              window.location.replace(target.href);
            }
          }
        }
      } catch (e) { /* resume is a convenience; never block Read Mode */ }
      try {
        if (window.location.pathname === '/read' && window.location.search) {
          window.localStorage.setItem(KEY, JSON.stringify({
            url: window.location.pathname + window.location.search,
            ts: Date.now(),
          }));
        }
      } catch (e) { /* private mode, or quota */ }
    })();
  </script>
  <link rel="stylesheet" href="/static/reader.css?v={{ static_asset_version }}">
</head>
<body class="rm-body">
  <div class="rm-layout">
    <nav class="rm-tree" aria-label="Read Mode">
      <a class="rm-exit" href="{{ exit_href|default('/') }}" title="Back to Lectio">&#8249; Lectio</a>

      {% if scope_tabs %}
      <div class="rm-scope-tabs">
        {% for t in scope_tabs %}
        <a class="rm-node rm-scope-tab{% if t.active %} active{% endif %}" href="{{ t.href }}">
          <span class="rm-glyph" aria-hidden="true">{{ t.glyph }}</span>
          <span class="rm-label">{{ t.label }}</span>
        </a>
        {% endfor %}
      </div>
      {% endif %}

      <div class="rm-tree-scroll">
        <div class="rm-tree-section">
          {% for n in folder_nodes %}
          {% if n.feeds %}
          <details class="rm-folder"{% if n.open %} open{% endif %}>
            <summary class="rm-node rm-folder-summary{% if n.active %} active{% endif %}">
              <span class="rm-glyph rm-folder-caret" aria-hidden="true">&#9656;</span>
              <a class="rm-folder-link" href="{{ n.href }}">{{ n.label }}</a>
              {% if n.count %}<span class="rm-count">{{ n.count }}</span>{% endif %}
            </summary>
            {% for f in n.feeds %}
            <a class="rm-node rm-feed-node{% if f.active %} active{% endif %}" href="{{ f.href }}">
              <span class="rm-label">{{ f.label }}</span>
              {% if f.count %}<span class="rm-count">{{ f.count }}</span>{% endif %}
            </a>
            {% endfor %}
          </details>
          {% else %}
          <a class="rm-node{% if n.active %} active{% endif %}" href="{{ n.href }}">
            {# An empty glyph still renders the fixed-width spacer so rows
               without an arrow (e.g. "All") stay aligned with folder rows. #}
            {% if n.glyph is defined %}<span class="rm-glyph" aria-hidden="true">{{ n.glyph }}</span>{% endif %}
            <span class="rm-label">{{ n.label }}</span>
            {% if n.count %}<span class="rm-count">{{ n.count }}</span>{% endif %}
          </a>
          {% endif %}
          {% endfor %}
        </div>

        {% if tag_nodes %}
        <details class="rm-tree-section rm-tree-tags"{% if tags_open %} open{% endif %}>
          <summary class="rm-node rm-tags-summary">
            <span class="rm-label">Tags</span>
            <span class="rm-count">{{ tag_nodes|length }}</span>
          </summary>
          {% for n in tag_nodes %}
          <a class="rm-node rm-tag-node{% if n.active %} active{% endif %}" href="{{ n.href }}">
            <span class="rm-label">{{ n.label }}</span>
            {% if n.count %}<span class="rm-count">{{ n.count }}</span>{% endif %}
          </a>
          {% endfor %}
        </details>
        {% endif %}
      </div>

      {% if archive_node %}
      <div class="rm-tree-pinned">
        <a class="rm-node{% if archive_node.active %} active{% endif %}" href="{{ archive_node.href }}">
          <span class="rm-glyph" aria-hidden="true">{{ archive_node.glyph }}</span>
          <span class="rm-label">{{ archive_node.label }}</span>
          {% if archive_node.count %}<span class="rm-count">{{ archive_node.count }}</span>{% endif %}
        </a>
      </div>
      {% endif %}
    </nav>

    <main class="rm-list">
      <header class="rm-list-header">
        <span class="rm-list-title">{{ selected_label }}</span>
        <form class="rm-search" method="get" action="/read" role="search">
          {# Carry the selected node so a search stays inside it. #}
          {% for f in search_fields %}<input type="hidden" name="{{ f.name }}" value="{{ f.value }}">{% endfor %}
          <input type="search" name="q" value="{{ search_query }}"
                 placeholder="{% if scope == 'feeds' %}Search feeds…{% else %}Search saved…{% endif %}"
                 aria-label="Search articles">
          <button type="submit" class="rm-search-go" aria-label="Search">Search</button>
          {% if search_query %}
          <a class="rm-search-clear" href="{{ read_clear_search_href }}" aria-label="Clear search">Clear</a>
          {% endif %}
        </form>
        {# Sort switcher: plain links, so it works with no JS and each tap is a
           single e-ink repaint. The chosen order rides the URL, so Next/Prev
           inside the reader walk the list the same way. #}
        {% if sort_options %}
        <div class="rm-sort" role="group" aria-label="Sort order">
          <span class="rm-sort-label">Sort</span>
          {% for s in sort_options %}
          <a class="rm-sort-opt{% if s.active %} active{% endif %}" href="{{ s.href }}"
             {% if s.active %}aria-current="true"{% endif %}>{{ s.label }}</a>
          {% endfor %}
        </div>
        {% endif %}
        {# Offline saving. The Supernote browser has no download handler at all,
           so a service worker is the only in-browser route left — it can serve
           the NAVIGATION, which is what a saved hyperlink needs with WiFi off. #}
        <div class="rm-offline">
          <button type="button" id="rm-offline-btn" class="rm-sort-opt">Save 20 for offline</button>
          <span id="rm-offline-status" class="rm-offline-status">Checking…</span>
          {# Offline action queue depth, filled by outbox.js. Shown here as well
             as in the reader bar: actions are taken inside an article, but the
             list is where you come back to, and a queue that never drains has to
             be visible somewhere you actually look. #}
          <span class="rm-offline-queue" data-outbox-depth hidden></span>
          <pre id="rm-offline-detail" class="rm-offline-detail" hidden></pre>
        </div>

        {# Bulk actions for the drilled-into node. Visible buttons, not a context
           menu: Read Mode has no right-click and long-press offers only text
           selection. Plain forms, so they work with no JS. #}
        {% if node_actions %}
        <div class="rm-actions" role="group" aria-label="Actions for this view">
          {% if node_actions.confirm_delete_tag %}
          <form method="post" action="/tags/delete" class="rm-action-form">
            <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
            <input type="hidden" name="tag" value="{{ node_actions.tag }}">
            <span class="rm-action-warn">Delete #{{ node_actions.tag }} from every post? This cannot be undone.</span>
            <button type="submit" class="rm-sort-opt rm-action-danger">Yes, delete #{{ node_actions.tag }}</button>
          </form>
          <a class="rm-sort-opt" href="{{ node_actions.cancel_href }}">Cancel</a>
          {% else %}
          <span class="rm-sort-label">Actions</span>
          {% if node_actions.tag %}
          {# First tap only arms it; the confirm above spells out what goes. #}
          <a class="rm-sort-opt rm-action-danger" href="{{ node_actions.confirm_href }}">Delete #{{ node_actions.tag }} everywhere</a>
          {% endif %}
          {% if node_actions.star_count %}
          <form method="post" action="/saved/unstar-scope" class="rm-action-form">
            <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
            {% if node_actions.folder_id is not none %}<input type="hidden" name="folder_id" value="{{ node_actions.folder_id }}">{% endif %}
            {% if node_actions.list_feed_url %}<input type="hidden" name="list_feed_url" value="{{ node_actions.list_feed_url }}">{% endif %}
            {% if node_actions.tag %}<input type="hidden" name="tag" value="{{ node_actions.tag }}">{% endif %}
            <button type="submit" class="rm-sort-opt">Unstar all {{ node_actions.star_count }} here</button>
          </form>
          {% endif %}
          {% endif %}
        </div>
        {% endif %}
      </header>

      {% if list_items %}
      <ul class="rm-items">
        {% for it in list_items %}
        <li class="rm-item{% if it.read %} rm-read{% endif %}">
          <a class="rm-item-link" href="{{ it.href }}">
            <span class="rm-item-title">{% if it.title_html %}{{ it.title_html | safe }}{% else %}{{ it.title }}{% endif %}</span>
            {# Source and date share a line: on a small e-ink screen a third
               line per row costs more than the date is worth. #}
            {% if it.subtitle or it.date %}
            <span class="rm-item-feed">
              {%- if it.subtitle %}{{ it.subtitle }}{% endif -%}
              {%- if it.subtitle and it.date %} · {% endif -%}
              {%- if it.date %}<span class="rm-item-date">{{ it.date }}</span>{% endif -%}
            </span>
            {% endif %}
          </a>
        </li>
        {% endfor %}
      </ul>
      {% elif node_selected %}
      <p class="rm-empty">Nothing here.</p>
      {% else %}
      <p class="rm-empty">Pick a folder, tag, or Archive on the left to start reading.</p>
      {% endif %}
    </main>
  </div>
  {# outbox.js flushes any actions queued while offline on load, and renders the
     queue depth above. It is loaded here, not only in the reader, because the
     list is the page most likely to be open when the connection returns. #}
  <script src="/static/outbox.js?v={{ static_asset_version }}"></script>
  <script src="/static/offline-probe.js?v={{ static_asset_version }}"></script>
</body>
</html>