adapt workspace shell to dark theme

This commit is contained in:
ngfchl
2026-07-18 19:42:14 +08:00
parent d21625e18d
commit 71042fb1a5
4 changed files with 164 additions and 99 deletions
+21 -6
View File
@@ -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,
),
),
+52 -16
View File
@@ -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: [
+80 -74
View File
@@ -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<BatchRenameRuleKind>(
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<BatchRenameRuleKind>(
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,
),
],
),
),
);
}
+11 -3
View File
@@ -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,