← Design Gaps

Document Cache — Design Gap

Work item AB#2578 Originating feature AB#2576 Epic AB#1821 Status Blocked — no design source

The gap

AB#2576 adds CategoryItem.PrefetchCount to the GetDocuments response: when set, the app silently auto-downloads the top N downloadable documents in that category so they're cached on-device ahead of a member ever tapping them. That silent behavior is exactly the problem — nothing in the UI tells the member it happened. A code audit of the whole Presentation layer while scoping AB#2576 found DataManager.IsDocumentDownloaded consumed only as an internal implementation detail:

This is not a native-vs-Blazor parity gap. Every other doc in this hub compares an existing native screen against its undesigned Blazor counterpart. There is no native precedent here — PrefetchCount and the concept of a visible "document cache" are new to this app entirely. The template below is adapted accordingly: there is no side-by-side native screenshot section, because there is no native side to capture.

What exists today

AspectCurrent state
Download indicator None. IsDocumentDownloaded only gates two internal decisions: whether SharedActionsService shows a "you're offline" alert before attempting a download, and which of GetDocumentDownloadFromFileAsync vs. the network download path DataManager.GetDocumentDownloadAsync takes.
Favorites page layout Single flat list (alpa-fav-list) under one static "SAVED ITEMS" section label. No tabbing/pill-switch UI exists on this page today.
Favorites data model Favorite.ItemTypeId (FavoriteItemTypes): MenuItem, Document, NotificationCenterMessage, DocumentSet — all backed by the real Favorites API, all member-initiated ("I saved this"). Auto-downloaded documents are not member-initiated and have no representation in this model.
Pill/segmented-tab precedent Shared, subsystem-neutral alpa-btn-pill-group / alpa-btn-pill (D46), already used on the Notifications page to switch Comms vs. Flight Finder lists — a directly reusable component, independent of any particular page or data model.
Notifications ↔ Favorites precedent for "related but separate" Confirmed by code audit: separate @page routes (/favorites, /notifications), separate Application-layer ports (IFavoritesQueries vs. INotificationsQueries, no shared base beyond the generic scaffold marker-interface pattern every port uses), separate scaffold routers (FavoritesQueriesRouter / NotificationsQueriesRouter in ScaffoldDataSourceRouters.cs), separate domain models, no shared LiteDB collection. The only place they're "affiliated" is the UI entry point: sibling icon buttons (topnav.favoritesButton2, topnav.notificationsButton3) in the same right-hand cluster of TopNav.razor, and a shared component (the pill control) — never a shared page, route, or data model.

Proposed direction

Revised 2026-08-24 — Document Cache is its own mechanism, not a Favorites sub-list

The original direction on this page (a second, pill-switched list living inside the Favorites page/data model) is rejected. Jose's correction: build Document Cache the way Notifications and Favorites relate to each other today — two different mechanisms, affiliated by function, not one mechanism wearing two hats. Favorites' data model is exclusively member-initiated saves; folding a system-initiated cache list into it would be exactly the kind of modeling mismatch flagged in the prior draft's Open Question 1.

Applying the confirmed Notifications/Favorites separation pattern (see table above) to Document Cache:

Two candidate data sources remain open regardless of where the UI lives:

  1. Read the local cache directory directly. Enumerate downloaded files (already the source of truth IsDocumentDownloaded checks) and resolve each back to a DocumentItem via GetDocumentByFileId. Simple, always accurate to what's actually on disk, but not queryable/sortable without a filesystem scan.
  2. Track prefetched documents in LiteDB as they're downloaded. DataManager.PrefetchDocumentAssetsAsync (AB#2576) already knows exactly which documents it downloaded and when — persisting that list gives a proper queryable data source (for sort, "downloaded on" display, eviction later) at the cost of a new store to keep in sync with the filesystem.

Either path needs a new bindable property (e.g. DocumentRowViewModel.IsDownloaded or similar) to actually render a per-row indicator — the existing view-model has no such property (see "What exists today" above).

Open questions

#ForQuestion
1DesignWhere does the Document Cache entry point live? Candidates: a fifth icon in the TopNav cluster (currently a fixed 4-slot layout — avatar, heart, bell, disabled search), a link from Document Center (where these documents actually live), or a link from Favorites (functionally adjacent per Jose's direction, even though it's a separate mechanism). No Figma frame exists for any of these.
2DesignCopy and iconography for "Document Cache" as a page title/nav label and as a per-row indicator (a downloaded document still visible in its normal Document Center location needs some marker too, not just in this new list) — no Figma frame exists for either.
3DesignShould a member be able to remove a document from the cache (free local storage) from this list, or is it read-only / self-managed by whatever eviction policy PrefetchCount ends up needing?
4ProductShould Document Cache show only PrefetchCount auto-downloads, or every downloaded document regardless of how it got there (e.g. a document a member manually opened once, which is also cached per IsDocumentDownloaded)? These are behaviorally identical on disk today — deciding to distinguish them is a product call, not an engineering one.
5EngineeringData source for the list — read the cache directory live vs. a persisted "prefetched" record (see Proposed direction above). Affects whether this needs a new LiteDB collection.

References