18722 Commits

Author SHA1 Message Date
sictiru
8077f4a109 Merge branch 'sictiru' of github.com:samuelclay/NewsBlur into sictiru 2026-03-12 15:17:07 -07:00
sictiru
f681ab6b8a Android 13.12.3 258 Android_13.12.3 2026-03-02 15:28:31 -08:00
sictiru
78232d99db #1995 Full text classifiers 2026-02-27 14:27:03 -08:00
sictiru
f04fc918a6 Enable predictive back API 34+ 2026-02-20 16:10:22 -08:00
sictiru
4f9029b5ed Android 13.12.2 257 Android_13.12.2 2026-02-18 07:54:54 -08:00
sictiru
c08ac219f8 Update gradle and agp 2026-02-18 07:14:25 -08:00
sictiru
81c90fb8ec #2059 Story Highlights updates 2026-02-17 14:48:53 -08:00
sictiru
36953cd507 #2066 Code block rendering 2026-02-17 14:33:23 -08:00
sictiru
5a6ce383c0 Merge pull request #30 from sictiru/widget-update
Widget Update
2026-02-17 13:46:47 -08:00
sictiru
fa0777c2c4 Prefetch widget images 2026-02-17 13:41:31 -08:00
sictiru
d34fc53378 Embedded videos CSS updates 2026-02-10 15:47:07 -08:00
Samuel Clay
35bd9bfb40 Merge pull request #2054 from samuelclay/android-read-time-tracking
Add active reading time tracking on Android
2026-02-10 11:03:03 -08:00
Samuel Clay
4217f85873 Add active reading time tracking per story on Android
Track how many seconds a user actively reads each story, using a 1-second
coroutine timer with a 2-minute idle threshold (matching iOS/web). Read
times piggyback on mark-as-read API calls and flush standalone when
leaving story view or backgrounding the app. Queued times are restored
on API failure to prevent data loss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 11:01:51 -08:00
Samuel Clay
671ae69250 Merge branch 'main' into sictiru
* main: (214 commits)
  Show "Untitled" for stories with no title, content, or permalink
  Bump daily briefing email font size from 16px to 18px for better readability
  Fix briefing crash by calling secure_image_urls on Feed instead of MStory
  Fix three Daily Briefing bugs: nested folder matching, disabled sections, and custom prompts
  Add clickable story links, favicon tooltips, and fix briefing email icon
  Add descriptive labels to LLM Costs stat panels in Grafana
  Move 3 misplaced table panels into Trending Feeds section in Grafana dashboard
  Fix LLM costs Prometheus scrape timeout by eliminating scan_iter on 150K keys
  Fix LLM Costs panels overlapping Discover Usage in Grafana dashboard
  Fix daily briefing JS errors from missing secure_image_urls and uninitialized views
  Replace abstract thinking icon with recognizable Lucide brain SVG
  Fix Discover panel overlap with LLM Costs and refactor taskbar info to flexbox
  Fix bottom toolbar layout by converting taskbar-info to flex child
  Add discover usage tracking to Prometheus/Grafana
  Redesign daily briefing with inline styles for email-compatible rendering
  Move try feed Subscribe/Follow/Sign up buttons to story titles list
  Fix model dropdown scroll and undefined model on re-ask click
  Add Ask AI thinking mode toggle and fix briefing lock TTL
  Fix triple daily briefing by adding Redis distributed locks
  Fix Manage Training crash when folder-scoped classifiers exist
  ...
2026-02-10 10:27:33 -08:00
sictiru
3a7b085885 Widget favicon and thumbnail image loading tweaks 2026-02-10 09:47:58 -08:00
Samuel Clay
08323cb372 Show "Untitled" for stories with no title, content, or permalink
When a story has no title, the backend already falls back to stripped
content then permalink. This adds a final fallback to display "Untitled"
so the story row renders with proper height instead of collapsing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:26:50 -08:00
Samuel Clay
7f288bce4f Bump daily briefing email font size from 16px to 18px for better readability
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:15:43 -08:00
Samuel Clay
9cdf3cc4d1 Fix briefing crash by calling secure_image_urls on Feed instead of MStory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 08:35:10 -08:00
Samuel Clay
50ae651b15 Fix three Daily Briefing bugs: nested folder matching, disabled sections, and custom prompts
Bug #1: Nested folders returned 0 stories because the frontend sends the
leaf folder name (e.g. "Child") but flatten_folders() produces full-path
keys like "Parent - Child". Added suffix matching to resolve nested folders.

Bug #2: Disabled sections still appeared because the LLM saw CATEGORY
annotations for disabled sections and created them anyway. Two-layer fix:
remap disabled categories to trending_global before sending to LLM, and
post-process output HTML to strip any hallucinated disabled sections.

Bug #3: Custom section prompts generated irrelevant content when switching
folders because prompts were sent to the LLM even when no stories matched
the keywords. Now only include custom prompts that have matching stories.

Fixes #2049

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:51:34 -08:00
Samuel Clay
13648042ff Add clickable story links, favicon tooltips, and fix briefing email icon
Daily briefing stories now have real href links (/briefing?story=HASH) that
work in both email notifications and the web reader. Favicon images show the
feed title on hover. Bumped briefing font size from 15px to 16px. Fixed the
broken Daily Briefing header icon in email by serving briefing.svg for
briefing feeds. On web, navigating to /briefing?story=HASH auto-selects
the referenced story after loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:09:52 -08:00
Samuel Clay
d3836d19a7 Add descriptive labels to LLM Costs stat panels in Grafana
Each panel had a single query returning ~12 series (total + 4 providers +
7 features) all with the same generic legend like "Today". Split into 3
targets per panel with meaningful labels: Total, provider name, feature name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 12:18:20 -08:00
Samuel Clay
07bd242b4c Move 3 misplaced table panels into Trending Feeds section in Grafana dashboard
Top Stories by Read Time, Long Reads, and Top Trending Feeds by Subscriptions
were positioned at incorrect y-coordinates causing them to overlap with the
Discover Usage and LLM Costs sections. Repositioned all three tables into the
Trending Feeds section and shifted all subsequent sections down accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 12:11:55 -08:00
Samuel Clay
5369acdf2c Fix LLM costs Prometheus scrape timeout by eliminating scan_iter on 150K keys
Redis db=3 has ~150K keys (mostly from IPRateTracker/ScannerTracker).
scan_iter with default COUNT=10 required ~15K SCAN round-trips (~13s),
causing Prometheus to timeout with "context deadline exceeded".

Fix: replace scan_iter with a known_models SET populated during record(),
combine 6 separate Redis calls into a single pipeline with 2 round-trips,
and partition 30-day MGET results into daily/weekly/monthly buckets locally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 12:04:11 -08:00
Samuel Clay
d3ce6625c9 Fix LLM Costs panels overlapping Discover Usage in Grafana dashboard
Shift all LLM Costs panel y-positions down by 18 to sit below the
Discover Usage section. The row header was moved but its child panels
were left at old positions, causing them to interleave with Discover
panels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:49:03 -08:00
Samuel Clay
b14fdb1b9a Fix daily briefing JS errors from missing secure_image_urls and uninitialized views
Add secure_image_urls to briefing story serialization so HTTPS image
proxying works, guard image_url() against missing secure_image_urls,
protect toggle_classes from firing before render, and check
story_title_view exists before calling found_largest_image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:47:21 -08:00
Samuel Clay
747b018e1e Replace abstract thinking icon with recognizable Lucide brain SVG
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:18:24 -08:00
Samuel Clay
d44d177505 Fix Discover panel overlap with LLM Costs and refactor taskbar info to flexbox
Move LLM Costs row y-position down in Grafana dashboard so Discover
Usage unique users panels no longer overlap it. Replace absolute
positioning with flexbox for taskbar info centering, simplifying the
layout and overflow logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:58:42 -08:00
Samuel Clay
6cb005118d Fix bottom toolbar layout by converting taskbar-info to flex child
The removal of .NB-modal-submit (which had flex-grow:1) in b05d7302f
caused all toolbar buttons to bunch up on the left. Convert
.NB-taskbar-info from absolute positioning to a flex-grow:1 child
inside .NB-taskbar-flex, so it acts as the center spacer pushing
Style and layout buttons to the right.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:58:34 -08:00
Samuel Clay
36f3d92a78 Add discover usage tracking to Prometheus/Grafana
Track discover feeds and discover stories usage with Redis-based
counters exposed via a new /monitor/discover Prometheus endpoint.
Metrics include request counts and unique users across daily, weekly,
monthly, and all-time periods. Adds a "Discover Usage" section to the
Grafana dashboard with four panels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:38:55 -08:00
Samuel Clay
e13a0cb36c Redesign daily briefing with inline styles for email-compatible rendering
Add inline CSS to briefing HTML so it renders well in both web and email
clients. Favicons now act as bullet points in a table layout with proper
text alignment, classifier pills render as styled green rounded pills
with thumbs-up icons, and section headers get typography styling. Also
refresh the summary story gradient to a cleaner blue tone and hide the
redundant generic globe image preview.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 08:33:38 -08:00
Samuel Clay
b05d7302fd Move try feed Subscribe/Follow/Sign up buttons to story titles list
Replace the small taskbar buttons in the bottom toolbar with prominent
banners at the top of the story titles list, matching the existing
sign-up banner pattern used for unauthenticated users. Each banner
shows a feed icon, title, descriptive subtitle, and action button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 08:26:56 -08:00
Samuel Clay
f63ced6e12 Fix model dropdown scroll and undefined model on re-ask click
Remove max-height/overflow-y from model dropdowns so thinking toggle
doesn't cause scrolling. Fix model selection handlers to use
closest('.NB-model-option') so clicking on provider pill child elements
correctly resolves the data-model attribute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 15:29:21 -08:00
Samuel Clay
d9a63f1250 Add Ask AI thinking mode toggle and fix briefing lock TTL
Ask AI: Add a Fast/Thinking segmented toggle to the model dropdown.
When Thinking is selected, providers use extended reasoning (Anthropic
thinking, OpenAI reasoning_effort, Gemini thinking_budget, xAI reasoning
model). Preference is persisted and switching modes re-asks automatically.

Briefing: Fix distributed locks to not delete on completion — the
GenerateBriefings task completes in ~0.1s, so deleting the lock let
later beat tasks from other servers acquire it. Now uses 14-min TTL
that persists for the full scheduling interval. Per-user lock also
persists for scheduled runs; only on-demand regeneration deletes it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 15:27:41 -08:00
Samuel Clay
952ce0ba00 Fix triple daily briefing by adding Redis distributed locks
3 htask-work servers each run celery with -B (beat scheduler), causing
GenerateBriefings to fire 3x concurrently every 15 minutes. All 3
pass the exists_for_period() dedup check (race condition), dispatch 3
GenerateUserBriefing tasks, and send 3 notifications.

Add Redis SET NX locks at two levels:
- GenerateBriefings: only one instance runs across all servers
- GenerateUserBriefing: per-user lock as safety net against races

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 10:05:44 -08:00
Samuel Clay
21f25aafc4 Fix Manage Training crash when folder-scoped classifiers exist
The callback parameter `_` in _.each(folder_names, ...) shadowed the
Underscore.js global, causing _.each inside the callback to fail with
"_.each is not a function" and leaving the tab stuck on Loading Classifiers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 08:30:29 -08:00
Samuel Clay
1d9aee8393 Fix daily briefing to reload on re-click, matching feed behavior
Top-level briefing clicks and same-section re-clicks now trigger a full
server reload instead of using cached data. Only switching to a different
sub-section uses the fast cached re-render path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 07:49:26 -08:00
Samuel Clay
205fc9f56a Fix sub-feature layout with flexbox and add mobile viewport meta tag
Switch sub-features from float to flexbox to prevent items from appearing on their own line due to varying heights. Add viewport meta tag so mobile Safari renders at device width instead of desktop width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 07:44:30 -08:00
Samuel Clay
656ef1ef78 Refine welcome page sub-features: cover-fit images, remove redundant app entries, swap order
- Change sub-feature images to object-fit: cover with left-top anchoring so all thumbnails are uniform size
- Remove Native iOS/macOS and Android app sub-features (already shown in platforms section)
- Swap YouTube and Dark Mode positions
- Add new sub-feature images (11-16)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 21:28:03 -08:00
Samuel Clay
1da0063522 Fix trainer folder dropdown to include folders with folder-scoped classifiers
The Manage Training tab's folder dropdown only showed folders containing
feeds with feed-scoped classifiers. Folders that only had folder-scoped
classifiers (but no feed-specific ones) were missing from the dropdown,
even though their classifiers rendered correctly in the list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 21:06:51 -08:00
Samuel Clay
91ecc37ded Update welcome page features heading and add 6 new sub-features
Reword features section heading to "Full-featured news reader" and subheading
to "Keep the signal, lose the noise." Add Web Feeds, Ask AI, Daily Briefing,
Notifications, Keyboard Shortcuts, and River of News as new sub-features.
Also adjust DB log timing color from dim to yellow for 1-5s queries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:50:46 -08:00
Samuel Clay
8be308c348 Fix briefing folder filter to include subfolders and prevent silent fallback
The folder source filter in briefing scoring only matched feeds directly in the
selected folder, missing all subfolder feeds. Since flatten_folders() stores
nested folders as separate keys (e.g. "Tech - AI"), a prefix match is needed
to collect feeds from the entire folder tree. Also removed the silent skip
when no feeds matched — the filter now always applies, and missing
UserSubscriptionFolders logs a debug message instead of silently passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:53:32 -08:00
Samuel Clay
f6a3fc0c2a Add call counts, millisecond precision, and dim styling to DB times log
Show query counts per database (e.g. sql: 3/0.002s), cap time display
at millisecond resolution, and gray out zero-count entries for readability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:18:34 -08:00
Samuel Clay
cddd9108bb Inline briefing icons as data URIs, add model/stats debug footer
- Switch from URL-based <img> tags to inline base64 data URIs for both
  feed favicons (from MFeedIcon) and section header SVGs (from disk),
  eliminating network requests and icon pop-in on the web
- Fix regex capture group bug where group(1) captured the full HTML tag
  instead of the extracted hash/key value
- Append italic debug footer showing model name, story count, token
  usage (in/out), and generation time
- Return metadata tuple from generate_briefing_summary for stats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:18:27 -08:00
Samuel Clay
78cc3ae1bf Embed briefing favicons and section icons server-side for email support
Favicons and section header icons were injected via JavaScript after render,
causing them to pop in on the web and be completely missing from email
notifications. Now embeds them as <img> tags with absolute URLs and inline
styles directly in the briefing HTML during generation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 11:56:12 -08:00
Samuel Clay
a4ffeb053a Redesign welcome page hero and platform sections
Center hero branding (logo, title, tagline, try-out button), add cream
text with golden glow shadow for section headings on dark backgrounds,
tighten platform descriptions to two lines each, add "Full-featured"
heading with subtitle to features section, add "synced" to platforms
subheading, normalize heading punctuation (no trailing periods on
titles, periods on subtitles), restyle pricing/stats headings, and
add dark mode overrides for new elements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:48:14 -08:00
Samuel Clay
fcaae19cdc Fix OpenAI reasoning model token limits, add gray briefing icons
OpenAI reasoning models (gpt-5-*) include internal reasoning tokens in
max_completion_tokens, causing empty content when the budget is too low.
Use max_completion_tokens with 5x multiplier (min 16384) for OpenAI/XAI
providers. Add separate gray SVG icons for briefing context so original
colored icons (green rocket, gradient unread) remain unchanged for other
uses. Increase frontend briefing generation timeout from 90s to 120s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:47:50 -08:00
Samuel Clay
76f7d11178 Revert SVG source colors, use CSS grayscale filter for briefing icons
Restore growth-rocket.svg (green) and indicator-unread.svg (gradient)
to their original colors since they're used elsewhere. Apply a simple
grayscale(1) CSS filter in the briefing context instead of modifying
the source SVGs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:19:47 -08:00
Samuel Clay
362fdba8ac Normalize briefing section icon colors to consistent #95968E gray
growth-rocket.svg was green (#5cb85c), indicator-unread.svg used a
brownish gradient, and discover/pulse/stack had a one-digit hex
variation (#95958E vs #95968E). All icons now use the same gray.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:14:57 -08:00
Samuel Clay
2a3a70e82f Fix briefing folder selection, remove Pro gating from model selector
Fix source feed folder not persisting: make_folders() compares against
raw folder titles but we were passing river:-prefixed values that never
matched. Strip the folder: prefix to get just the folder name instead.

Remove Pro gating from the AI model selector since the entire briefing
feature is already gated under Premium Archive. All briefing users can
now choose their preferred model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 10:01:54 -08:00
Samuel Clay
4aa0a99f0b Add configurable AI model selection for daily briefing
Briefing was hardcoded to Anthropic Haiku, blocking self-hosters who
only have OpenAI/Gemini keys (fixes #2048). Now uses the provider system
from Ask AI with a separate cheap-model registry (Haiku, GPT 5 Mini,
Gemini Flash Lite, Grok 4.1 Fast). Default is Haiku via BRIEFING_MODEL
setting. Pro users can pick their model in the briefing preferences
popover; non-pro users see a locked selector with an upgrade link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 07:50:15 -08:00