Commit graph

7 commits

Author SHA1 Message Date
Austin Schaefer
f0e42e2ad5 Fix article list not scrolling: duplicate <main> broke the scroll area
All checks were successful
CI / check (pull_request) Successful in 4m55s
CI / test (pull_request) Successful in 4m2s
CI / audit (pull_request) Successful in 14s
Articles past the first screenful were unreachable — not clipped by
accident, genuinely inaccessible, since the page itself couldn't
scroll either (the sidebar wrapper is overflow: hidden by design, so
the intended scroll boundary is internal to the main content pane).

Root cause: SidebarInset already renders a <main> (class
dx-sidebar-inset, a properly height-bound flex column — main{
height:900px in a 900px viewport, flex-direction:column}), but I'd
also written an explicit `main { ... }` as ITS child, producing a
`<main><main>...</main></main>` (confirmed via a headless Playwright
probe against the live dev server, not just DevTools guesswork). The
inner <main> is just a plain flex item with the default flex: 0 1 auto,
so it sized to its own content (6500+px) instead of being constrained
by the outer one's box, and the ScrollArea inside it had nothing
bounded to scroll within.

Removed the redundant inner <main> — SidebarInset's children (the
content-header div and ScrollArea) now sit directly in its own <main>,
which is the actual flex column that needs to size them. Also pinned
ScrollArea's direction to Vertical (it defaults to Both, which was
adding an unnecessary horizontal scrollbar) and moved the sizing rule
in app.css off a class ScrollArea silently drops (confirmed via the
same probe — a caller-supplied `class` never reaches ScrollArea's
rendered DOM, only its own internal one does) onto its stable
data-scroll-direction attribute instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 19:17:57 +02:00
Austin Schaefer
44e2fb4d4e Actually fix the Subscribe button overflow (previous fix was inert)
The prior commit's .subscribe-form .dx-input selector never matched
anything: dioxus's #[css_module] macro content-hashes Input's class at
build time (e.g. rendered as class="dx-input-83f82cbc", confirmed by
inspecting the live DOM), so a selector on the unhashed "dx-input"
name was dead CSS from the start — hence the overflow persisting
across rebuilds and hard refreshes.

Select on the raw <input> tag within .subscribe-form instead, which
doesn't depend on the module's per-build hash. Verified against the
running dev server (not just visually): the Subscribe button now
renders flush with the form's own right edge (both at x=247) instead
of spilling to x=314, well inside the sidebar's x=256 boundary.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 19:07:51 +02:00
Austin Schaefer
86863d809d Fix Subscribe button overflowing the sidebar's fixed width
Not an article-row or hot-reload issue after all — the Subscribe
button in the sidebar header was genuinely spilling past the sidebar's
16rem width into the main content column. The sidebar panel is
position: fixed; z-index: 10 (dx-sidebar-container in the vendored
sidebar CSS), so that overflow floated on top of whatever main content
happened to sit at the same height, which was the first article row's
button — hence it only ever looked broken there.

Root cause: .subscribe-form .dx-input had flex: 1 but no min-width: 0,
so flexbox's default min-width: auto stopped it shrinking below its
content-based minimum once the Subscribe button took its share of the
row — a classic flexbox overflow gotcha. Added min-width: 0 to both
the input and the form row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 18:18:49 +02:00
Austin Schaefer
21103b1f25 Fix article row layout: button overlapping title, uneven summary gaps
article-row had no layout structure at all — title link, score badge,
and the dismiss button were plain inline siblings in a block <li>, so a
long title pushed the button flush against (or past) the row's edge.
Group title+score into a header row and make the row itself a flex
column so summary/topics/button always stack on their own line below,
regardless of title length.

Also stopped rendering the summary <p> and topics div at all when
there's no content (many RSS entries have no description), instead of
emitting empty elements — spacing was uneven because those still
reserved a line's worth of height. Left this as an explicit Rust-side
branch rather than CSS :empty: an empty <p> still contains a
zero-length text node, and whether :empty matches that is
inconsistent across engines, whereas the topics div (an empty `for`
loop) has zero children and would be a safe :empty candidate — but
kept both on the same explicit mechanism for consistency.

Swapped the dismiss button from a raw <button> to the dx Button
component, matching the rest of the row and the project's preference
for the component library over raw elements.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 18:08:14 +02:00
Austin Schaefer
6a2bf8c9a8 Add feed sidebar navigation, built from Dioxus's component library
Default view stays the all-feeds joined article list, now with a sidebar
listing every subscribed feed so a reader can pin down to one feed's
articles. Filtering happens server-side (list_ranked_articles now takes
an optional feed_id).

Pulled in the sidebar/badge/scroll_area (plus their sheet/skeleton/
tooltip/separator dependencies) components via `dx components add`
instead of hand-rolling nav/tag/scroll markup, matching this project's
existing pattern of using the Dioxus component library over raw
elements (see button/input).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
2026-09-03 16:28:22 +02:00
Austin Schaefer
d40c90552c Add manual feed subscription
Some checks failed
CI / check (pull_request) Failing after 32s
CI / test (pull_request) Has been skipped
CI / audit (pull_request) Has been skipped
Adds a URL input + Subscribe button (dx-components Input/Button) to the
UI, wired to a new subscribe_feed server function that upserts the feed
row and does an immediate first fetch so the reader isn't empty until
the next scheduled poll. feedsignal_feeds::fetch_feed now also returns
the feed's title, used to replace the URL placeholder once fetched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJJQb2DWZZwQ1yPiaAQQoY
2026-08-21 15:15:50 +02:00
Austin Schaefer
1a4a72fc27 Scaffold feedsignal: Rust workspace for LLM-filtered RSS reader
Some checks failed
CI / check (push) Failing after 26s
Rust workspace with core (topic-affinity learning engine + relevance
scoring), db (sqlite/sqlx schema + repo), feeds (RSS/Atom fetch), llm
(rig + local Ollama embeddings/completion), and web (axum + Dioxus
fullstack UI, no separate JS stack). Two-stage relevance filtering
(embedding shortlist -> LLM judgment) and an engagement/surprise-based
topic affinity engine with daily decay. All crates compile and core's
affinity engine has passing unit tests; server and wasm client targets
of feedsignal-web both check clean.
2026-08-20 17:04:14 +02:00