- FilesControlsRow (and Photos' own controls row) wrapped its Row in a
SingleChildScrollView, which gives a child unbounded width - silently
breaking the trailing Spacer (a flex child needs bounded width) and
leaving the List/Grid toggle sitting right after the filter chip
instead of pinned to the row's right edge, "not enough controls to
fill the row" or not. Removed the scroll wrapper (two chips and an
icon toggle never need it) and the dead scroll-hint plumbing that
went with it in files_view.dart.
- Photos' All/Photos/Videos chips moved into the filter sheet as a
full-width segmented control (matching Settings' Theme control),
instead of their own row of chips competing for space with the sort
and filter chips.
- Settings' Theme row: the System/Light/Dark segmented control now
sits on its own row below the label instead of squeezed into a
trailing slot beside it, where three icon+label segments were too
cramped to read comfortably - same shape as the sort sheet's
Ascending/Descending control.
- NooBanner (Trash's "Empty trash") and NooSummaryCard (Offline's
"Sync now") both move their action onto its own row below the
description text instead of squeezed onto the same line, where a
longer caption had no room to share with it.
- SharesController now caches each scope (with you / by you, which
also covers links) after its first fetch instead of re-fetching on
every single switch, including switching straight back to a scope
already loaded seconds ago.
- Shares' per-row overflow menu jumped straight to the unshare
confirmation with no menu at all - a link share had no way to copy
its own URL short of opening the full Share sheet. It's a real menu
now: "Copy link" (link shares only) plus remove/unshare.
- Settings gained a trailing jump rail on mobile (one small icon per
section) so a specific section can be reached in one tap instead of
scrolling the whole list by hand; desktop's 2-column grid doesn't
need one.
- The media viewer's PageView now disables its own left/right swipe
while the current photo is zoomed in, so panning around it doesn't
also swipe to the next item.
- The PDF preview no longer sets minScale below 1.0: pdfx's
PdfViewPinch hard-codes an *infinite* pan boundary whenever minScale
< 1 (not an exposed parameter, so there's no way to override it),
which let a page be panned arbitrarily far off-screen without ever
zooming.
Trash and Shares built their mobile lists eagerly via NooGroupedList's
own Column instead of a lazy sliver, so an account with hundreds of
items made those tabs laggy - both now use a SliverList/
SliverChildBuilderDelegate instead, matching Files' own lazy list,
while keeping the same one-continuous-card look via per-row corner
rounding and a 1px divider.
FilesControlsRow's sort/filter sheets also had a live-update bug: since
showNooSheet's children are built once up front, tapping a row inside
the open sheet updated the controller but the already-built
checkmarks/toggles stayed stale until the sheet was closed and
reopened. Wrapping each sheet's content in a ListenableBuilder fixes
that.
Also adds NooSelectionBar to styling.md's widget inventory table.
Replaces the Material 3 screens with the Noo design system: warm
neutrals, one violet accent, pill controls, Schibsted Grotesk/
Instrument Sans, Lucide icons, no gradients/shadows.
- New lib/widgets/noo/ component kit (core, lists, files, media, nav,
overlays) plus lib/theme/design_tokens.dart for the color/type/space/
radius/motion tokens.
- Rebuilt the app shell (top/bottom bars, drawer, desktop sidebar and
toolbar), every tab (Files/Offline, Photos, Favorites, Recent,
Activity, Trash, Shares), Settings, the lock and login screens, the
media viewer, search, the details/share sheets, and the share-upload
and move/copy destination pickers.
- Added a design canvas (linked from DESIGN_SYSTEM.md) covering the
screens the spec didn't already describe, with matching Android and
iOS chrome; wrote up the approved recipes into DESIGN_SYSTEM.md §4.
- Removed now-dead legacy widgets (media_grid_tile, swipeable_item,
sync_status_badge, selectable_thumbnail) and updated
architecture.md/styling.md/standards.md to describe the new
structure and component/testing conventions.
- Added widget tests for the noo/ component kit.
This is a UI-only rework: no provider/model/service behavior changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Consolidates duplicated GET/PUT/notification-channel logic across
DownloadService/ShareUploadService/SyncEngine into shared Kotlin helpers,
gives upload/download real batch queueing instead of dropping a second
concurrent batch, and dedupes repeated Dart channel-argument boilerplate.
Replaces the 2300+ line ServerProvider god object with ten focused
ChangeNotifiers (SessionController, SettingsController, FilesController,
PhotosController, FavoritesController, TrashController, SharesController,
RecentController, SyncStatusController, PickController) plus ItemOperations,
a plain coordinator for cross-domain item mutations - fixing the coupling
where device-sync status, per-tab data, and global UI prefs all lived in
one object. Updates every view/widget call site accordingly and refreshes
the architecture/server/standards/styling docs to match.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Major additions since the initial rebuild:
- New tabs: Trash, Shares, Recent, configurable tab visibility/order/default
- Nextcloud sharing: search users/teams, internal link, email shares,
public links, "others with access" - in its own Share bottom sheet
- Details bottom sheet (Info/Versions/Activity) with a persistent peek
panel in the media viewer, reachable from selection, swipe, and the
media viewer
- Files/Photos: tap-and-hold multi-select with a sticky selection toolbar,
swipe actions (favorite/delete/share), sticky sort/filter controls,
list/grid views, breadcrumb chips, whole-account Photos view
- Media viewer: pinch/double-tap zoom on images, predictive-back support,
fixed PDF zoom-out floor
- Settings: Material You theming incl. AMOLED black, configurable bottom
bar tabs, swipe actions, media seek bar style, and folder-listing cache
policy (never/periodic/manual) to cut down on refetching
- Login flow moved to an in-app Chrome Custom Tab with retry-tolerant
polling
- Replaced ad hoc widgets with native Material 3 equivalents (toggle
IconButtons, SliverAppBar selection toolbar, SearchBar, drag handles)
- Rebrand: app renamed to Noo throughout, package id -> dev.ayushya.noo,
new adaptive launcher icon
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>