Remove scrollbar thumb and restructure Settings profile card

- Revert the scrollbar-thumb feature entirely (per-view Scrollbar
  wrappers and the ScrollbarThemeData override) - back to plain
  scrollables with no visible thumb
- Settings: move the logout button into the profile card (next to the
  name/email), and move the ONLINE/OFFLINE badge + "Connected to..."
  text out of the top row into a combined line at the bottom of the
  card, instead of split between the AppBar and the top of the screen
- Update architecture.md/styling.md to drop the stale scrollbar-theme
  documentation

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 12:28:11 -04:00
co-authored by Claude Sonnet 5
parent 1fbdc1f8d0
commit 73e05f8d22
11 changed files with 698 additions and 760 deletions
+39 -42
View File
@@ -161,50 +161,47 @@ class _SyncedHeaderScaffoldState extends State<SyncedHeaderScaffold> {
children: [
NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: Scrollbar(
child: CustomScrollView(
controller: widget.scrollController,
child: CustomScrollView(
controller: widget.scrollController,
// Plain BouncingScrollPhysics only bounces/overscrolls
// reliably once content already fills the viewport — with
// too little content (e.g. a single item) the pull gesture
// can fail to register at all. AlwaysScrollableScrollPhysics
// keeps the pull (and therefore the sync header) working
// regardless of content length.
physics: const AlwaysScrollableScrollPhysics(
parent: BouncingScrollPhysics(),
),
slivers: [
SliverAppBar(
pinned: true,
stretch: true,
expandedHeight: _headerLocked ? 190 : kToolbarHeight,
collapsedHeight: kToolbarHeight,
backgroundColor: colorScheme.surfaceContainer,
surfaceTintColor: colorScheme.surfaceContainer,
scrolledUnderElevation: 0,
automaticallyImplyLeading: false,
leadingWidth: _headerLocked ? 56 : 160,
leading: leadingWidget,
actions: widget.actions,
flexibleSpace: FlexibleSpaceBar(
background: _SyncedStretchPanel(
provider: provider,
forceVisible: _headerLocked,
),
),
),
DecoratedSliver(
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(28),
),
),
sliver: SliverMainAxisGroup(slivers: widget.contentSlivers),
),
],
// Plain BouncingScrollPhysics only bounces/overscrolls
// reliably once content already fills the viewport — with
// too little content (e.g. a single item) the pull gesture
// can fail to register at all. AlwaysScrollableScrollPhysics
// keeps the pull (and therefore the sync header) working
// regardless of content length.
physics: const AlwaysScrollableScrollPhysics(
parent: BouncingScrollPhysics(),
),
slivers: [
SliverAppBar(
pinned: true,
stretch: true,
expandedHeight: _headerLocked ? 190 : kToolbarHeight,
collapsedHeight: kToolbarHeight,
backgroundColor: colorScheme.surfaceContainer,
surfaceTintColor: colorScheme.surfaceContainer,
scrolledUnderElevation: 0,
automaticallyImplyLeading: false,
leadingWidth: _headerLocked ? 56 : 160,
leading: leadingWidget,
actions: widget.actions,
flexibleSpace: FlexibleSpaceBar(
background: _SyncedStretchPanel(
provider: provider,
forceVisible: _headerLocked,
),
),
),
DecoratedSliver(
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(28),
),
),
sliver: SliverMainAxisGroup(slivers: widget.contentSlivers),
),
],
),
),
// The classic Material pull-to-refresh "bubble" — a floating