From 71042fb1a5f49005af31a54416bfe440905538cd Mon Sep 17 00:00:00 2001 From: ngfchl Date: Sat, 18 Jul 2026 19:42:14 +0800 Subject: [PATCH] adapt workspace shell to dark theme --- lib/app/app_theme.dart | 27 +++-- lib/pages/workspace_page.dart | 68 +++++++++--- lib/pages/workspace_tools_page.dart | 154 +++++++++++++++------------- lib/widgets/sort_menu.dart | 14 ++- 4 files changed, 164 insertions(+), 99 deletions(-) diff --git a/lib/app/app_theme.dart b/lib/app/app_theme.dart index b7fe914..95aa093 100644 --- a/lib/app/app_theme.dart +++ b/lib/app/app_theme.dart @@ -69,6 +69,8 @@ class GlassCard extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ShadTheme.of(context); + final isDark = theme.brightness == Brightness.dark; return ClipRRect( borderRadius: BorderRadius.circular(borderRadius), child: BackdropFilter( @@ -76,10 +78,14 @@ class GlassCard extends StatelessWidget { child: Container( padding: padding ?? const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.15), + color: isDark + ? theme.colorScheme.card.withValues(alpha: 0.72) + : Colors.white.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(borderRadius), border: Border.all( - color: Colors.white.withValues(alpha: 0.2), + color: isDark + ? theme.colorScheme.border.withValues(alpha: 0.82) + : Colors.white.withValues(alpha: 0.2), width: 1, ), ), @@ -97,12 +103,15 @@ class OS26Surface extends StatelessWidget { @override Widget build(BuildContext context) { + final isDark = ShadTheme.of(context).brightness == Brightness.dark; return DecoratedBox( - decoration: const BoxDecoration( + decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, - colors: [Color(0xFFE9F6F5), Color(0xFFF6FAF6), Color(0xFFF9E6D4)], + colors: isDark + ? const [Color(0xFF0B1220), Color(0xFF111827), Color(0xFF20151A)] + : const [Color(0xFFE9F6F5), Color(0xFFF6FAF6), Color(0xFFF9E6D4)], ), ), child: child, @@ -128,6 +137,8 @@ class OS26Glass extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ShadTheme.of(context); + final isDark = theme.brightness == Brightness.dark; return ClipRRect( borderRadius: BorderRadius.circular(radius), child: BackdropFilter( @@ -135,12 +146,16 @@ class OS26Glass extends StatelessWidget { child: Container( padding: padding, decoration: BoxDecoration( - color: Colors.white.withValues(alpha: opacity), + color: isDark + ? theme.colorScheme.card.withValues(alpha: opacity + 0.18) + : Colors.white.withValues(alpha: opacity), borderRadius: BorderRadius.circular(radius), border: border ?? Border.all( - color: Colors.white.withValues(alpha: 0.58), + color: isDark + ? theme.colorScheme.border.withValues(alpha: 0.9) + : Colors.white.withValues(alpha: 0.58), width: 1, ), ), diff --git a/lib/pages/workspace_page.dart b/lib/pages/workspace_page.dart index 56b288c..2a8b5df 100644 --- a/lib/pages/workspace_page.dart +++ b/lib/pages/workspace_page.dart @@ -404,7 +404,8 @@ class _TopBar extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; return SizedBox( height: 42, child: Row( @@ -522,7 +523,9 @@ class _SegmentButton extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return InkWell( borderRadius: BorderRadius.circular(10), onTap: onTap, @@ -532,13 +535,15 @@ class _SegmentButton extends StatelessWidget { height: 32, decoration: BoxDecoration( color: selected - ? Colors.white.withValues(alpha: 0.74) + ? (isDark ? cs.secondary : Colors.white.withValues(alpha: 0.74)) : Colors.transparent, borderRadius: BorderRadius.circular(10), boxShadow: selected ? [ BoxShadow( - color: Colors.black.withValues(alpha: 0.08), + color: (isDark ? Colors.black : Colors.black).withValues( + alpha: isDark ? 0.28 : 0.08, + ), blurRadius: 10, offset: const Offset(0, 3), ), @@ -1224,7 +1229,9 @@ class _ToolbarButton extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return ShadTooltip( builder: (_) => Text(label), child: Padding( @@ -1243,7 +1250,9 @@ class _ToolbarButton extends StatelessWidget { ? cs.primary.withValues(alpha: 0.14) : grouped ? Colors.transparent - : Colors.white.withValues(alpha: 0.46), + : (isDark + ? cs.secondary.withValues(alpha: 0.88) + : Colors.white.withValues(alpha: 0.46)), borderRadius: BorderRadius.circular(10), border: Border.all( color: primary @@ -1252,7 +1261,9 @@ class _ToolbarButton extends StatelessWidget { ? cs.primary.withValues(alpha: 0.45) : grouped ? Colors.transparent - : Colors.white.withValues(alpha: 0.54), + : (isDark + ? cs.border.withValues(alpha: 0.9) + : Colors.white.withValues(alpha: 0.54)), ), ), child: Row( @@ -1294,13 +1305,22 @@ class _ToolbarControlGroup extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return Container( height: 36, padding: const EdgeInsets.symmetric(horizontal: 2), decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.46), + color: isDark + ? cs.secondary.withValues(alpha: 0.88) + : Colors.white.withValues(alpha: 0.46), borderRadius: BorderRadius.circular(10), - border: Border.all(color: Colors.white.withValues(alpha: 0.54)), + border: Border.all( + color: isDark + ? cs.border.withValues(alpha: 0.9) + : Colors.white.withValues(alpha: 0.54), + ), ), child: Row(mainAxisSize: MainAxisSize.min, children: children), ); @@ -2200,7 +2220,9 @@ class _FinderColumnState extends State<_FinderColumn> { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; final column = widget.column; return FocusableActionDetector( focusNode: _focusNode, @@ -2256,7 +2278,9 @@ class _FinderColumnState extends State<_FinderColumn> { decoration: BoxDecoration( color: _dragActive || candidates.isNotEmpty ? cs.primary.withValues(alpha: 0.10) - : Colors.white.withValues(alpha: 0.22), + : (isDark + ? cs.secondary.withValues(alpha: 0.62) + : Colors.white.withValues(alpha: 0.22)), border: Border( right: BorderSide(color: cs.border.withValues(alpha: 0.70)), left: BorderSide( @@ -2459,7 +2483,9 @@ class _FileGridCard extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return Semantics( button: true, label: @@ -2472,7 +2498,9 @@ class _FileGridCard extends StatelessWidget { decoration: BoxDecoration( color: isSelected ? cs.primary.withValues(alpha: 0.12) - : Colors.white.withValues(alpha: 0.34), + : (isDark + ? cs.secondary.withValues(alpha: 0.78) + : Colors.white.withValues(alpha: 0.34)), borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected @@ -3263,16 +3291,24 @@ class _FilePaneFrame extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return _PaneDropSurface( parentID: dropParentID, onMoveCloudFiles: onMoveCloudFiles, onUploadLocalFiles: onUploadLocalFiles, child: Container( decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.42), + color: isDark + ? cs.card.withValues(alpha: 0.92) + : Colors.white.withValues(alpha: 0.42), borderRadius: BorderRadius.circular(14), - border: Border.all(color: Colors.white.withValues(alpha: 0.62)), + border: Border.all( + color: isDark + ? cs.border.withValues(alpha: 0.92) + : Colors.white.withValues(alpha: 0.62), + ), ), child: Column( children: [ diff --git a/lib/pages/workspace_tools_page.dart b/lib/pages/workspace_tools_page.dart index ca2358e..a69432a 100644 --- a/lib/pages/workspace_tools_page.dart +++ b/lib/pages/workspace_tools_page.dart @@ -1539,85 +1539,91 @@ class _BatchRenameRuleRow extends StatelessWidget { rule.kind == BatchRenameRuleKind.regex; final supportsCase = hasReplacement || rule.kind == BatchRenameRuleKind.remove; - return Container( - margin: const EdgeInsets.only(bottom: 8), - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: cs.muted.withValues(alpha: 0.46), - borderRadius: BorderRadius.circular(8), - border: Border.all(color: cs.border.withValues(alpha: 0.65)), - ), - child: Wrap( - spacing: 8, - runSpacing: 8, - crossAxisAlignment: WrapCrossAlignment.center, - children: [ - ShadCheckbox( - value: rule.enabled, - label: const Text('启用'), - onChanged: (value) => onChanged(rule.copyWith(enabled: value)), - ), - SizedBox( - width: 132, - child: ShadSelect( - key: ValueKey('${rule.id}-${rule.kind}'), - initialValue: rule.kind, - selectedOptionBuilder: (_, value) => Text(_ruleKindLabel(value)), - options: [ - for (final value in BatchRenameRuleKind.values) - ShadOption(value: value, child: Text(_ruleKindLabel(value))), - ], - onChanged: (value) { - if (value != null) onChanged(rule.copyWith(kind: value)); - }, + return IntrinsicWidth( + child: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: cs.muted.withValues(alpha: 0.46), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: cs.border.withValues(alpha: 0.65)), + ), + child: Wrap( + spacing: 8, + runSpacing: 8, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + ShadCheckbox( + value: rule.enabled, + label: const Text('启用'), + onChanged: (value) => onChanged(rule.copyWith(enabled: value)), ), - ), - SizedBox( - width: 190, - child: ShadInput( - initialValue: rule.pattern, - placeholder: Text(_rulePatternPlaceholder(rule.kind)), - onChanged: (value) => onChanged(rule.copyWith(pattern: value)), - ), - ), - if (hasReplacement) ...[ - const Icon(Icons.arrow_right_alt_rounded, size: 18), SizedBox( - width: 160, - child: ShadInput( - initialValue: rule.replacement, - placeholder: const Text('替换为'), - onChanged: (value) => - onChanged(rule.copyWith(replacement: value)), + width: 132, + child: ShadSelect( + key: ValueKey('${rule.id}-${rule.kind}'), + initialValue: rule.kind, + selectedOptionBuilder: (_, value) => + Text(_ruleKindLabel(value)), + options: [ + for (final value in BatchRenameRuleKind.values) + ShadOption( + value: value, + child: Text(_ruleKindLabel(value)), + ), + ], + onChanged: (value) { + if (value != null) onChanged(rule.copyWith(kind: value)); + }, ), ), - ], - if (supportsCase) - ShadCheckbox( - value: rule.ignoreCase, - label: const Text('忽略大小写'), - onChanged: (value) => onChanged(rule.copyWith(ignoreCase: value)), + SizedBox( + width: 190, + child: ShadInput( + initialValue: rule.pattern, + placeholder: Text(_rulePatternPlaceholder(rule.kind)), + onChanged: (value) => onChanged(rule.copyWith(pattern: value)), + ), ), - _RenameRuleIconButton( - icon: Icons.arrow_upward_rounded, - tooltip: '上移规则', - enabled: !isFirst, - onPressed: onMoveUp, - ), - _RenameRuleIconButton( - icon: Icons.arrow_downward_rounded, - tooltip: '下移规则', - enabled: !isLast, - onPressed: onMoveDown, - ), - _RenameRuleIconButton( - icon: Icons.delete_outline_rounded, - tooltip: '删除规则', - enabled: true, - destructive: true, - onPressed: onRemove, - ), - ], + if (hasReplacement) ...[ + const Icon(Icons.arrow_right_alt_rounded, size: 18), + SizedBox( + width: 160, + child: ShadInput( + initialValue: rule.replacement, + placeholder: const Text('替换为'), + onChanged: (value) => + onChanged(rule.copyWith(replacement: value)), + ), + ), + ], + if (supportsCase) + ShadCheckbox( + value: rule.ignoreCase, + label: const Text('忽略大小写'), + onChanged: (value) => + onChanged(rule.copyWith(ignoreCase: value)), + ), + _RenameRuleIconButton( + icon: Icons.arrow_upward_rounded, + tooltip: '上移规则', + enabled: !isFirst, + onPressed: onMoveUp, + ), + _RenameRuleIconButton( + icon: Icons.arrow_downward_rounded, + tooltip: '下移规则', + enabled: !isLast, + onPressed: onMoveDown, + ), + _RenameRuleIconButton( + icon: Icons.delete_outline_rounded, + tooltip: '删除规则', + enabled: true, + destructive: true, + onPressed: onRemove, + ), + ], + ), ), ); } diff --git a/lib/widgets/sort_menu.dart b/lib/widgets/sort_menu.dart index 675cb6f..a0de5aa 100644 --- a/lib/widgets/sort_menu.dart +++ b/lib/widgets/sort_menu.dart @@ -18,13 +18,21 @@ class SortMenu extends StatelessWidget { @override Widget build(BuildContext context) { - final cs = ShadTheme.of(context).colorScheme; + final theme = ShadTheme.of(context); + final cs = theme.colorScheme; + final isDark = theme.brightness == Brightness.dark; return Container( height: 36, decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.46), + color: isDark + ? cs.secondary.withValues(alpha: 0.88) + : Colors.white.withValues(alpha: 0.46), borderRadius: BorderRadius.circular(10), - border: Border.all(color: Colors.white.withValues(alpha: 0.54)), + border: Border.all( + color: isDark + ? cs.border.withValues(alpha: 0.9) + : Colors.white.withValues(alpha: 0.54), + ), ), child: Row( mainAxisSize: MainAxisSize.min,