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
+91 -98
View File
@@ -299,115 +299,108 @@ class _ShareSheetState extends State<ShareSheet> {
.toList();
final internalLink = internalLinkFor(provider.serverUrl, widget.item.id);
return Scrollbar(
return ListView(
controller: widget.scrollController,
child: ListView(
controller: widget.scrollController,
padding: const EdgeInsets.fromLTRB(20, 12, 20, 24),
children: [
Text(
widget.item.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w700,
),
padding: const EdgeInsets.fromLTRB(20, 12, 20, 24),
children: [
Text(
widget.item.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w700,
),
const SizedBox(height: 16),
_sectionHeader('Internal shares'),
const SizedBox(height: 8),
TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Type names or teams',
prefixIcon: const Icon(Icons.search_rounded),
suffixIcon: _isSearching
? const Padding(
padding: EdgeInsets.all(14),
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
)
: null,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
filled: true,
fillColor: colorScheme.surfaceContainerLow,
),
onChanged: _search,
),
const SizedBox(height: 16),
_sectionHeader('Internal shares'),
const SizedBox(height: 8),
TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Type names or teams',
prefixIcon: const Icon(Icons.search_rounded),
suffixIcon: _isSearching
? const Padding(
padding: EdgeInsets.all(14),
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
)
: null,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(16)),
filled: true,
fillColor: colorScheme.surfaceContainerLow,
),
for (final sharee in _searchResults)
ListTile(
contentPadding: EdgeInsets.zero,
leading: Icon(
sharee.type == ShareeType.group
? Icons.groups_rounded
: Icons.person_rounded,
),
title: Text(sharee.label),
subtitle: sharee.subtitle != null ? Text(sharee.subtitle!) : null,
onTap: () => _addSharee(sharee),
onChanged: _search,
),
for (final sharee in _searchResults)
ListTile(
contentPadding: EdgeInsets.zero,
leading: Icon(
sharee.type == ShareeType.group
? Icons.groups_rounded
: Icons.person_rounded,
),
for (final share in userGroupShares) _shareRow(share),
if (_inherited.isNotEmpty)
ExpansionTile(
tilePadding: EdgeInsets.zero,
leading: const Icon(Icons.more_horiz_rounded),
title: Text('Others with access (${_inherited.length})'),
children: [
for (final share in _inherited)
_shareRow(share, removable: false),
],
),
if (internalLink != null)
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.link_rounded),
title: const Text('Internal link'),
subtitle: const Text('For people who already have access'),
trailing: IconButton(
icon: const Icon(Icons.copy_rounded),
tooltip: 'Copy link',
onPressed: () => _copy(internalLink, 'internal link'),
),
),
const SizedBox(height: 20),
const Divider(),
const SizedBox(height: 12),
_sectionHeader('External shares'),
const SizedBox(height: 8),
TextField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Type an email',
prefixIcon: const Icon(Icons.email_outlined),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
),
filled: true,
fillColor: colorScheme.surfaceContainerLow,
),
onSubmitted: (_) => _addEmailShare(),
title: Text(sharee.label),
subtitle: sharee.subtitle != null ? Text(sharee.subtitle!) : null,
onTap: () => _addSharee(sharee),
),
for (final share in emailShares) _shareRow(share),
const SizedBox(height: 8),
for (final share in publicLinkShares) _shareRow(share, copyUrl: true),
for (final share in userGroupShares) _shareRow(share),
if (_inherited.isNotEmpty)
ExpansionTile(
tilePadding: EdgeInsets.zero,
leading: const Icon(Icons.more_horiz_rounded),
title: Text('Others with access (${_inherited.length})'),
children: [
for (final share in _inherited)
_shareRow(share, removable: false),
],
),
if (internalLink != null)
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.link_rounded),
title: const Text('Create public link'),
title: const Text('Internal link'),
subtitle: const Text('For people who already have access'),
trailing: IconButton(
icon: const Icon(Icons.add_rounded),
tooltip: 'Create public link',
onPressed: _createPublicLink,
icon: const Icon(Icons.copy_rounded),
tooltip: 'Copy link',
onPressed: () => _copy(internalLink, 'internal link'),
),
),
],
),
const SizedBox(height: 20),
const Divider(),
const SizedBox(height: 12),
_sectionHeader('External shares'),
const SizedBox(height: 8),
TextField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Type an email',
prefixIcon: const Icon(Icons.email_outlined),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(16)),
filled: true,
fillColor: colorScheme.surfaceContainerLow,
),
onSubmitted: (_) => _addEmailShare(),
),
for (final share in emailShares) _shareRow(share),
const SizedBox(height: 8),
for (final share in publicLinkShares) _shareRow(share, copyUrl: true),
ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(Icons.link_rounded),
title: const Text('Create public link'),
trailing: IconButton(
icon: const Icon(Icons.add_rounded),
tooltip: 'Create public link',
onPressed: _createPublicLink,
),
),
],
);
}
}