Commit Graph

40 Commits

Author SHA1 Message Date
Robin Kutesa
ff304d1fda fix: splash screen now loads via JarvisIcon imageset (UIImage named: AppIcon doesn't resolve at runtime)
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Added JarvisIcon.imageset containing the radar PNG so Image("JarvisIcon")
loads reliably. Also switched shadow tint to orange to echo the icon glow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:41:29 +03:00
Robin Kutesa
694880eb4c polish: vivid orange radar icon — brighter ring peaks + dual glow bloom
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- Gamma lift 0.70 pushes ring peaks toward full #FF5C00 saturation
- Faster ring-factor curve (^0.32) keeps more of each band at full brightness
- Tight 9px glow + wide 26px halo screen-blended for the orange fire feel
- Gap darkness stays near-black (^2 × 0.025) for maximum ring contrast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:33:14 +03:00
Robin Kutesa
03a1e45531 revert: restore radar concentric-rings app icon
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Replaces the 3-bar horizontal design with the original radar/signal
icon — concentric orange rings fading to near-black at center and edge,
15 ring bands, warm dark background. Matches the "Signal Intelligence" J icon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:29:48 +03:00
Robin Kutesa
b53a4b8f5d fix: splash screen uses actual app icon in a circle (Wenza style)
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Replaces the custom 3-bar SwiftUI drawing with UIImage(named:"AppIcon")
clipped to a circle, matching the Wenza splash pattern exactly:
- Icon bounces in with spring (scale 0.82→1, opacity 0→1)
- "jarvis" wordmark fades in 320ms later
- Whole screen fades out at 1.6s, onDismiss fires at 1.9s
- Main app renders underneath so it's warm when the splash clears

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:24:07 +03:00
Robin Kutesa
207b1827c7 feat: hero card layout in all pills, cache-while-loading, logo splash screen
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- Every pill (F1, Tech, AI, Cloud, HomeLab…) now shows the same hero card
  layout as "All" — first story is the big featured card, rest follow as rows
- "All" retains its full multi-section front page (US / Tech / AI / Sport…)
- Topic pill headers use the pill name instead of "TOP STORIES"
- filteredStories now falls back to cached SwiftData rows while loading, so
  switching to F1 or Tech shows cached cards instantly instead of a blank list
- Logo splash screen (3 pill bars + jarvis wordmark) shows on launch and fades
  out after setup completes; minimum 1.3 s so it's always readable
- JarvisWordmark moved to Theme.swift so SplashView and feed can share it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:15:23 +03:00
Robin Kutesa
760e6a121c fix: resolve Swift 6 concurrency warnings in WebSocketManager
- listen(): capture `task` as local `t` before the Sendable receive closure
  so the @MainActor-isolated property isn't referenced inside a Sendable context
- startPing(): dispatch to @MainActor inside the timer block before accessing `task`
- scheduleReconnect(): capture `self` weakly in the reconnect Task

XcodeGen regenerated to include BackgroundRefreshManager.swift in the project.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 02:06:01 +03:00
Robin Kutesa
eec610024c feat: read-shelf auto-expand, stripe removal, pull-reshuffle, BG notifications
- Mark-read now immediately expands the READ shelf so the story is visible
- Orange signal stripe is fully removed (not dimmed) when isRead=true
- Pull-to-refresh clears seen snapshot → full reshuffle by signal score
- BackgroundRefreshManager fires a local notification for the top new
  high-signal story after each cache refresh; Tech/AI/HomeLab stories
  get their category in the notification title (≥65 signal threshold)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 01:58:51 +03:00
Robin Kutesa
3b09fa2889 feat(bg): add background feed refresh every ~30 min
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Registers com.kisani.jarvis.feed.refresh as a BGAppRefreshTask.
On each fire it fetches the latest 40 stories and upserts CachedStory
rows so the SwiftData cache is warm before the user opens the app.
Already-cached rows have signalScore / sourceCount refreshed in-place.

Single ModelContainer owned by JarvisApp and shared via
BackgroundRefreshManager.container to avoid multi-container conflicts.
BG task ID registered in AppDelegate and declared in project.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 01:42:20 +03:00
Robin Kutesa
7085a4dd45 feat(reader): redesign ArticleReaderView + global appearance toggle
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Reading experience:
- Body text #CECECE (dark) / #1A1916 (light) — was near-invisible #4A4A4A
- 30pt heavy headline, 17pt body at 8.5pt line-spacing
- Skeleton pulse loading state replaces dark spinner box
- Hero image fades in on load (0.3s ease-in)
- Orange reading progress bar (2pt) below nav bar
- Max reading width 680pt for iPad legibility

Appearance:
- AppearanceMode enum (system/light/dark) in Theme.swift
- @AppStorage("appearanceMode") applied once in JarvisApp root
- Appearance picker (Picker in Menu) in reader toolbar
- Removed .preferredColorScheme(.dark) from all 12 child views

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 01:30:36 +03:00
Robin Kutesa
fb2e0ff9a2 fix(icon): pixel-perfect vertical centering (319px each side)
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Orange glow bleeds 15px upward beyond the bar boundary.
Y_START=(1024-370+15)/2=334 compensates so the visible
content sits with exactly 319px negative space above and below.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:23:21 +03:00
Robin Kutesa
fd327423aa fix(icon): optical vertical centering — shift bars up 22px
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Mathematical centre (512px) reads as low due to orange glow blooming
upward. Shifting the bar group up 22px balances perceived top/bottom
negative space (305px above, 349px below → visually equal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:15:26 +03:00
Robin Kutesa
9cff253e6c fix(icon): centre each bar individually on the 1024px canvas
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Each pill is now positioned at x = (1024 - bar_width) / 2,
giving symmetric left/right margins regardless of bar length.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:11:58 +03:00
Robin Kutesa
568eb82e5e Fix icon bar order: orange short, white longest, grey middle
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 22:08:52 +03:00
Robin Kutesa
576f10f54c Fix icon bar sizes: decreasing widths matching reference logo
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Bars are now left-aligned with decreasing widths (600/440/300px),
matching the reference where the orange top bar is longest and each
gray bar steps down in width like a news feed preview.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 22:04:29 +03:00
Robin Kutesa
a44fcf9749 Replace app icon: three-bar signal feed design
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Orange top bar + two gray bars on dark background. Cleaner and more
legible at small sizes (notification, Settings, Spotlight) than the
previous concentric-rings design.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 21:58:53 +03:00
Robin Kutesa
f5c9f4d9ae Remove orange dot overlay from i in JarvisWordmark
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 21:43:56 +03:00
Robin Kutesa
9129315594 Redesign JarvisWordmark: typewriter font, lowercase j, orange i-dot
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- Switches from .system(.heavy) to Courier New Bold — classic typewriter look
- 'j' is now lowercase (was 'J'), still in KisaniOrange
- 'i' renders in white with an orange Circle overlaid at the tittle position,
  so the dot reads orange against the black background
- Implemented as HStack of individual Text segments so each character can
  be independently coloured; 'i' uses .overlay(alignment: .top) with a
  size-proportional Circle offset to sit at glyph-tittle height

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 21:31:12 +03:00
Robin Kutesa
053e6341ce Add share / save / mark-read toolbar buttons to detail and reader views
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Both StoryDetailView and ArticleReaderView now show three icon buttons in
the navigation bar trailing area:
- Share (square.and.arrow.up) — story headline+summary+URL / article
  headline+sourceUrl, passed to UIActivityViewController via ShareSheet.
- Save (bookmark / bookmark.fill, orange when active) — toggles SavedStory
  in SwiftData; StoryDetailView also ensures a CachedStory exists so the
  Saved tab can display it offline.
- Mark read/unread (checkmark.circle / checkmark.circle.fill, orange when
  read) — toggle mirroring the swipe action already present in the feed.

The read state in StoryDetailView is still auto-marked on open (.task
→ markRead()); the toolbar button lets users undo that without going back
to the feed. ArticleReaderView targets the parent story (route.storyId).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 20:50:22 +03:00
Robin Kutesa
d192815915 Harden icon pipeline: add ASSETCATALOG_COMPILER_APPICON_NAME to project.yml
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Previously the setting only existed in the generated pbxproj (where XcodeGen
placed it implicitly). Now it's explicit in project.yml so re-running
`xcodegen generate` always produces a project that picks up the AppIcon set.
Build verified: actool emits AppIcon60x60@2x.png and AppIcon76x76@2x with
correct pixel content from the concentric-rings source icon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 20:36:40 +03:00
Robin Kutesa
c1bf74e3a5 Add Jarvis app icon — concentric orange signal rings
Dark squircle with 16 concentric rings rising from near-black at the
outer edge and center to KisaniOrange (#FF5C00) at the midpoint, with a
Gaussian screen-blend glow pass. Mimics the sonar/radar ring style of
the reference logo using the Jarvis black-and-orange palette.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 20:27:07 +03:00
Robin Kutesa
3f0d8348b9 Front-page polish: hero lead card + title-cased labels
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Render the #1 Top Story as an Apple-News-style hero card (flat surface, 4pt
stripe, 24pt headline, summary, sources, prominent score). Prettify category
labels (slug -> Title Case, with AI/US/Formula 1 special-cases) across rows,
hero, and detail. Per Emil's framework, no row entrance/press motion on a
constantly-scrolled surface — invest in hierarchy and defaults instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:42:09 +03:00
Robin Kutesa
da43399ead Turn "All" into a sectioned news front page
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Instead of one long firehose, "All" now renders Apple/Google-News-style:
a Top Stories lead block, then category sections (World, Politics, Business,
AI, Technology, Africa, Sport, Science, Entertainment, Health, Lifestyle) with
the top few stories each and a "See all" jump to the matching pill. Sections are
built from backend tags[]; specific pills keep the flat list. "All" preloads up
to ~100 stories to fill sections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:34:14 +03:00
Robin Kutesa
22b859dc7b Fix feed jank: make seen-tracking and caching cheap
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
The "All" feed stuttered because every row appearing ran markSeen, which did a
disk save(), an O(n) contains over a @Query'd SeenStory array, and triggered a
full feed re-render on each insert. Now markSeen does an O(1) insert into a
non-observed reference Set, no per-row save (the container autosaves), and
SeenStory is no longer @Query'd by the view. cacheStories also does one fetch +
an in-memory index instead of a query per story.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:56:29 +03:00
Robin Kutesa
798f46fbb1 Align cache eviction to the backend aging model
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Retention now mirrors the backend: cached stories age out at RECENT_HOURS (72h,
the active feed window), seen/read markers at 96h (window + buffer), and cached
article bodies at 14 days (raw-article retention). Saved bookmarks stay protected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:31:52 +03:00
Robin Kutesa
fd2be632a1 Add cache cleanup: age-based auto-eviction + manual Clear cache
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
CacheMaintenance prunes the SwiftData caches so they don't grow forever:
seen markers >30d, read >90d, cached articles >30d, cached stories >14d —
always protecting saved bookmarks. Runs on launch. Settings gains a
"Clear offline cache" action (keeps saved) with a count + confirmation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:25:39 +03:00
Robin Kutesa
70ca5a0d3a Cache backend tags so offline pill filtering stays accurate
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Add tags[] to CachedStory (defaulted for lightweight migration) and persist
them on upsert; offline StorySummary now carries the cached tags instead of
falling back to topic. Backend stays the source of truth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:14:45 +03:00
Robin Kutesa
7283fd63ed Filter pills by backend tags (slug membership), drop keyword matching
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Replace the keyword/source-majority Interest system with a StoryPill enum that
matches stories by canonical category slugs. StorySummary gains a tolerant
tags[] (optional, decode-safe); effectiveTags uses tags, falling back to topic
during the backend transition. No more headline keyword-searching on the client —
the backend decides classification; the client asks slug membership.

Pills: All, F1, Sport, AI, Cloud, HomeLab, Tech, Uganda, South Africa, Canada, US.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 21:55:57 +03:00
Robin Kutesa
5c0f4afd80 Add Sport/Canada/US/AI/Cloud/HomeLab pills; drop Finance
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- New Sport pill: detect sports by clear headline terms or majority
  sports-outlet sources, and exclude sports (and F1) from All/Tech/regions so
  World Cup/soccer no longer pollutes Finance/Tech.
- New client keyword pills: Canada, US, AI, Cloud, HomeLab (headline-matched).
- Remove the Finance pill; keep Tech (backend topic).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:39:45 +03:00
Robin Kutesa
3d40065ec7 Update backlog statuses; strengthen over-clustering issue with new evidence
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Mark each item open/mitigated/done, fold completed work into Shipped, and
upgrade the clustering bug with the on-device Jackson/airport over-merge proof
and a concrete TF-IDF/embeddings fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:07:39 +03:00
Robin Kutesa
4331621ccc Split save/mark-read swipe; move read stories into a collapsible shelf
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- Left swipe: short reveals Save (tap), full swipe marks read. Right swipe
  still shares.
- Read stories leave the main feed and collapse into a "Read" shelf at the
  bottom (collapsed by default), shown as slim one-line rows; swipe to mark
  unread. An "all caught up" state shows when everything loaded is read.
- StoryRowView gains a compact presentation for the shelf.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:07:58 +03:00
Robin Kutesa
feee58748c Sink seen/read stories, fix F1 matching, drop East Africa pill
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
- Sink already-seen and read stories to the bottom of the feed (new SeenStory
  model + per-load snapshot so order is stable while scrolling and refreshes
  sink what you've seen) so fresh content surfaces.
- F1 matching: clear F1 headline OR a majority of F1-feed sources, replacing the
  broad keyword list that leaked crypto in (fia -> "deFIAnt"). Dropped unused
  matchSources path.
- Remove the East Africa pill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:17:32 +03:00
Robin Kutesa
20dd49a53c Update issue tracker: backend data-quality bugs + full backlog
Some checks failed
CI / Build · macos-14 · Debug (push) Has been cancelled
CI / Build · macos-15 · Debug (push) Has been cancelled
CI / Build · macos-14 · Release (push) Has been cancelled
CI / Build · macos-15 · Release (push) Has been cancelled
Capture the proven backend issues (F1 topic mis-classification, over-clustering
with mismatched headline/summary, missing per-story tags) plus open client/CI
work in docs/BACKLOG.md, and expand scripts/create-issues.sh to file all 14 on
the Gitea repo once it exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 01:15:56 +03:00
Robin Kutesa
3fd5b8f1c7 Add swipe actions: left to save, right to share + mark read
- Swipe left bookmarks a story (toggle) into the Saved tab; swipe right opens
  the iOS share sheet and marks the story read.
- New SavedStory SwiftData model; Saved tab now lists explicit bookmarks
  instead of the whole offline cache.
- Convert the feed to a styled List (native swipeActions require it), keeping
  the flat look, pull-to-refresh, and infinite scroll. Add a ShareSheet wrapper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 01:15:56 +03:00
Robin Kutesa
87bfb234c2 Add feed summary preview and pinned interest filters
- Show a 6-line cross-source summary preview in each feed row.
- Pinned, mutually-exclusive filter pills: All, F1, Uganda, East Africa,
  South Africa, Finance, Tech. "All" is news-only (F1 lives only under F1);
  regions don't overlap (East Africa excludes Uganda & South Africa).
- Categorization correctness: regions match the headline only (the backend's
  summaries/outlets are polluted by over-clustering), and F1 takes precedence
  over every other pill since the backend mis-tags F1 as tech/finance/politics.
- Finance/Tech match the backend topic; sparse filters auto-pull more pages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 01:00:39 +03:00
Robin Kutesa
9662c2abf6 Stabilize feed order with a deterministic signal-score tiebreaker
Equal-score stories reshuffled on every pull-to-refresh because the sort
was unstable. Add StorySummary.feedOrder (signalScore desc, then id desc,
mirroring the backend's signal_score DESC, id DESC) and use it for the feed,
the WebSocket re-sort, and the Saved/Search tabs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:33:22 +03:00
Robin Kutesa
1e582f5120 Feed resilience, clearer empty states, and read/unread
- Don't blank the feed on refresh: keep current stories until new data
  arrives, and ignore benign URLError.cancelled (-999) so a network blip
  no longer wipes the list. Coalesce WebSocket story.created bursts into a
  single debounced refresh.
- Empty state now distinguishes polling, couldn't-reach-server (with the
  error + host + Retry), offline, and genuinely-empty.
- Track read stories in SwiftData (ReadStory); mark a story read when opened
  and drop/dim its signal stripe across the feed and Latest/Saved/Search.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:22:56 +03:00
Robin Kutesa
4e4d109380 Enable device code signing (automatic, team K8BLMMR883)
Replace CODE_SIGNING_ALLOWED=NO with automatic signing + DEVELOPMENT_TEAM so
the app installs on a physical device. Simulator/CI builds still pass
CODE_SIGNING_ALLOWED=NO on the command line and skip signing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:46:39 +03:00
Robin Kutesa
3388eb7944 Add notifications: morning/evening briefings + breaking alerts
- Settings hub (gear → SettingsView) hosting Notifications and Connectivity
  (Connectivity previously had no entry point).
- NotificationsView: permission flow, breaking/new-story alerts with a
  min-signal threshold, morning & evening briefings with time pickers, and a
  weather toggle + location, plus a "send test briefing" action.
- NotificationManager: schedules daily briefings, builds "Jarvis" content
  (weather + top signal stories), fires breaking alerts off WebSocket
  story.created events, and refreshes via a BGAppRefresh task.
- WeatherService: Open-Meteo geocoding + daily forecast (no API key/entitlement).
- AppDelegate registers the background-refresh handler at launch; Info.plist
  gains UIBackgroundModes + BGTaskSchedulerPermittedIdentifiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:17:41 +03:00
Robin Kutesa
e6ab2242f0 Target self-hosted Gitea: Gitea-API issue script + CI runner note
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 18:17:01 +03:00
Robin Kutesa
27d0e22767 Initial commit: Jarvis iOS app
SwiftUI client for a self-hosted RSS news-correlation platform: signal feed,
story detail, article reader, feed manager, and LAN⇄Tailscale connectivity.
Project generated from project.yml via XcodeGen.

Includes CI build matrix (macOS 14/15 × Debug/Release), issue templates,
backlog, and API/backend handoff docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 18:04:59 +03:00