diff --git a/lib/features/settings/settings_page_core.dart b/lib/features/settings/settings_page_core.dart index cc66dbd1..e002dfc2 100644 --- a/lib/features/settings/settings_page_core.dart +++ b/lib/features/settings/settings_page_core.dart @@ -12,6 +12,8 @@ import '../../models/app_models.dart'; import '../../runtime/gateway_runtime.dart'; import '../../runtime/runtime_controllers.dart'; import '../../runtime/runtime_models.dart'; +import '../../theme/app_palette.dart'; +import '../../theme/app_theme.dart'; import 'codex_integration_card.dart'; import 'skill_directory_authorization_card.dart'; import '../../widgets/settings_page_shell.dart'; @@ -207,6 +209,8 @@ class SettingsPageStateInternal extends State { return AnimatedBuilder( animation: controller, builder: (context, _) { + final theme = Theme.of(context); + final palette = context.palette; final featurePlatform = resolveUiFeaturePlatformFromContext(context); final uiFeatures = controller.featuresFor(featurePlatform); tabInternal = uiFeatures.sanitizeSettingsTab(controller.settingsTab); @@ -220,53 +224,80 @@ class SettingsPageStateInternal extends State { (tabInternal != SettingsTab.gateway || integrationSubTabInternal == GatewayIntegrationSubTabInternal.acp); - return SettingsPageBodyShell( - padding: const EdgeInsets.fromLTRB(32, 32, 32, 8), - breadcrumbs: buildSettingsBreadcrumbs( - controller, - tab: tabInternal, - detail: detailInternal, - navigationContext: navigationContextInternal, - ), - title: appText('设置', 'Settings'), - subtitle: showingDetail - ? appText( - '当前正在编辑详细设置参数,保存后会回写到对应状态页。', - 'You are editing detailed settings. Saved values flow back to the related status page.', - ) - : appText( - '配置 $kProductBrandName 工作区、网关默认项、界面与诊断选项', - 'Configure workspace, gateway defaults, appearance, and diagnostics for $kProductBrandName.', + return Theme( + data: theme.copyWith( + inputDecorationTheme: theme.inputDecorationTheme.copyWith( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppRadius.input), + borderSide: BorderSide( + color: palette.strokeSoft, + width: settingsHairlineBorderWidthInternal, ), - trailing: SizedBox( - width: showingDetail ? 168 : 220, - child: showingDetail - ? OutlinedButton.icon( - onPressed: () { - controller.closeSettingsDetail(); - setState(() { - detailInternal = null; - navigationContextInternal = null; - }); - }, - icon: const Icon(Icons.arrow_back_rounded), - label: Text(appText('返回概览', 'Back to overview')), - ) - : TextField( - decoration: InputDecoration( - hintText: appText('搜索设置', 'Search settings'), - prefixIcon: Icon(Icons.search_rounded), - ), - ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppRadius.input), + borderSide: BorderSide( + color: palette.strokeSoft, + width: settingsHairlineBorderWidthInternal, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppRadius.input), + borderSide: BorderSide( + color: palette.accent.withValues(alpha: 0.32), + width: settingsHairlineBorderWidthInternal, + ), + ), + ), ), - globalApplyBar: showGlobalApplyBar - ? buildGlobalApplyBarInternal(context, controller) - : null, - bodyChildren: buildContentForCurrentStateInternal( - context, - controller, - settings, - uiFeatures, + child: SettingsPageBodyShell( + padding: const EdgeInsets.fromLTRB(32, 32, 32, 8), + breadcrumbs: buildSettingsBreadcrumbs( + controller, + tab: tabInternal, + detail: detailInternal, + navigationContext: navigationContextInternal, + ), + title: appText('设置', 'Settings'), + subtitle: showingDetail + ? appText( + '当前正在编辑详细设置参数,保存后会回写到对应状态页。', + 'You are editing detailed settings. Saved values flow back to the related status page.', + ) + : appText( + '配置 $kProductBrandName 工作区、网关默认项、界面与诊断选项', + 'Configure workspace, gateway defaults, appearance, and diagnostics for $kProductBrandName.', + ), + trailing: SizedBox( + width: showingDetail ? 168 : 220, + child: showingDetail + ? OutlinedButton.icon( + onPressed: () { + controller.closeSettingsDetail(); + setState(() { + detailInternal = null; + navigationContextInternal = null; + }); + }, + icon: const Icon(Icons.arrow_back_rounded), + label: Text(appText('返回概览', 'Back to overview')), + ) + : TextField( + decoration: InputDecoration( + hintText: appText('搜索设置', 'Search settings'), + prefixIcon: Icon(Icons.search_rounded), + ), + ), + ), + globalApplyBar: showGlobalApplyBar + ? buildGlobalApplyBarInternal(context, controller) + : null, + bodyChildren: buildContentForCurrentStateInternal( + context, + controller, + settings, + uiFeatures, + ), ), ); }, diff --git a/lib/features/settings/settings_page_gateway.dart b/lib/features/settings/settings_page_gateway.dart index 3a66472e..b9ff122f 100644 --- a/lib/features/settings/settings_page_gateway.dart +++ b/lib/features/settings/settings_page_gateway.dart @@ -118,6 +118,7 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal { ) else SurfaceCard( + borderWidth: settingsHairlineBorderWidthInternal, child: Text( appText( '当前发布配置未开放 Vault Server 参数。', @@ -195,6 +196,7 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal { ) else SurfaceCard( + borderWidth: settingsHairlineBorderWidthInternal, child: Text( appText( '当前发布配置未开放 Vault Server 参数。', @@ -650,6 +652,7 @@ extension SettingsPageGatewayMixinInternal on SettingsPageStateInternal { }) { final theme = Theme.of(context); return SurfaceCard( + borderWidth: settingsHairlineBorderWidthInternal, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/features/settings/settings_page_gateway_connection.dart b/lib/features/settings/settings_page_gateway_connection.dart index 76c67eda..942e573b 100644 --- a/lib/features/settings/settings_page_gateway_connection.dart +++ b/lib/features/settings/settings_page_gateway_connection.dart @@ -35,6 +35,7 @@ extension SettingsPageGatewayConnectionMixinInternal SettingsSnapshot settings, ) { return SurfaceCard( + borderWidth: settingsHairlineBorderWidthInternal, child: buildOpenClawGatewayCardBodyInternal( context, controller, @@ -352,6 +353,7 @@ extension SettingsPageGatewayConnectionMixinInternal SettingsSnapshot settings, ) { return SurfaceCard( + borderWidth: settingsHairlineBorderWidthInternal, child: buildVaultProviderCardBodyInternal(context, controller, settings), ); } diff --git a/lib/features/settings/settings_page_widgets.dart b/lib/features/settings/settings_page_widgets.dart index 7009ccbe..1c5ecfd0 100644 --- a/lib/features/settings/settings_page_widgets.dart +++ b/lib/features/settings/settings_page_widgets.dart @@ -27,6 +27,8 @@ import 'settings_page_multi_agent.dart'; import 'settings_page_support.dart'; import 'settings_page_device.dart'; +const double settingsHairlineBorderWidthInternal = 0.55; + class EditableFieldInternal extends StatefulWidget { const EditableFieldInternal({ super.key, diff --git a/lib/widgets/surface_card.dart b/lib/widgets/surface_card.dart index 9f31d474..18867e28 100644 --- a/lib/widgets/surface_card.dart +++ b/lib/widgets/surface_card.dart @@ -12,6 +12,7 @@ class SurfaceCard extends StatefulWidget { this.padding = const EdgeInsets.all(AppSpacing.md), this.onTap, this.borderRadius = AppRadius.card, + this.borderWidth = 1, this.color, this.tone = SurfaceCardTone.standard, }); @@ -20,6 +21,7 @@ class SurfaceCard extends StatefulWidget { final EdgeInsetsGeometry padding; final VoidCallback? onTap; final double borderRadius; + final double borderWidth; final Color? color; final SurfaceCardTone tone; @@ -49,7 +51,7 @@ class _SurfaceCardState extends State { SurfaceCardTone.standard => BoxDecoration( color: (_hovered && widget.onTap != null ? hoveredColor : baseColor) .withValues(alpha: 0.98), - border: Border.all(color: borderColor), + border: Border.all(color: borderColor, width: widget.borderWidth), borderRadius: BorderRadius.circular(widget.borderRadius), boxShadow: widget.onTap != null && _hovered ? [palette.chromeShadowAmbient] @@ -58,7 +60,7 @@ class _SurfaceCardState extends State { SurfaceCardTone.chrome => BoxDecoration( color: (_hovered && widget.onTap != null ? hoveredColor : baseColor) .withValues(alpha: 0.98), - border: Border.all(color: borderColor), + border: Border.all(color: borderColor, width: widget.borderWidth), borderRadius: BorderRadius.circular(widget.borderRadius), boxShadow: [ if (_hovered && widget.onTap != null) palette.chromeShadowAmbient,