refactor: update spacing and styling in authentication and server connection pages

- Adjusted spacing values in the authentication and server connection pages for improved layout consistency.
- Modified container dimensions and padding to enhance visual appeal and maintain a cohesive design.
- Updated text styles to ensure better readability and alignment with the overall theme.
- Streamlined widget structures by removing unnecessary animations, focusing on performance and clarity.
- Enhanced the user interface by refining the design of buttons and form fields for a more polished experience.
This commit is contained in:
cogwheel0
2025-10-05 00:29:27 +05:30
parent 8629e1e039
commit 8cb55edab6
5 changed files with 461 additions and 684 deletions

View File

@@ -160,13 +160,13 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
// Header with progress indicator
_buildHeader(),
const SizedBox(height: Spacing.extraLarge),
const SizedBox(height: Spacing.xl),
// Main content
Expanded(
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
constraints: const BoxConstraints(maxWidth: 480),
child: Form(
key: _formKey,
child: Column(
@@ -175,12 +175,12 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
// Server connection status
_buildServerStatus(),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
// Welcome section
_buildWelcomeSection(),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
// Authentication form
_buildAuthForm(),
@@ -214,8 +214,8 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
Row(
children: [
Container(
width: 32,
height: 6,
width: 24,
height: 4,
decoration: BoxDecoration(
color: context.conduitTheme.buttonPrimary,
borderRadius: BorderRadius.circular(AppBorderRadius.round),
@@ -223,8 +223,8 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
),
const SizedBox(width: Spacing.xs),
Container(
width: 32,
height: 6,
width: 24,
height: 4,
decoration: BoxDecoration(
color: context.conduitTheme.buttonPrimary,
borderRadius: BorderRadius.circular(AppBorderRadius.round),
@@ -251,43 +251,40 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
} catch (_) {}
return 'Server';
}();
return ConduitCard(
isElevated: false,
padding: const EdgeInsets.all(Spacing.lg),
child: Row(
children: [
Container(
width: 40,
height: 40,
return Container(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.sm,
),
decoration: BoxDecoration(
color: context.conduitTheme.successBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.round),
color: context.conduitTheme.success.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: context.conduitTheme.success.withValues(alpha: 0.3),
color: context.conduitTheme.success.withValues(alpha: 0.2),
width: BorderWidth.standard,
),
),
child: Icon(
child: Row(
children: [
Icon(
Platform.isIOS
? CupertinoIcons.checkmark_circle_fill
: Icons.check_circle,
? CupertinoIcons.checkmark_circle
: Icons.check_circle_outline,
color: context.conduitTheme.success,
size: IconSize.medium,
size: IconSize.small,
),
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.connectedToServer,
style: context.conduitTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
style: context.conduitTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w500,
color: context.conduitTheme.success,
),
),
const SizedBox(height: Spacing.xs),
Text(
hostText,
style: context.conduitTheme.bodySmall?.copyWith(
@@ -300,10 +297,6 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
),
],
),
).animate().slideX(
begin: -0.05,
duration: AnimationDuration.messageSlide,
curve: Curves.easeOutCubic,
);
}
@@ -312,46 +305,34 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
children: [
BrandService.createBrandIcon(
size: 48,
useGradient: true,
addShadow: true,
useGradient: false,
addShadow: false,
context: context,
).animate().scale(
duration: AnimationDuration.pageTransition,
curve: Curves.easeOutBack,
),
const SizedBox(height: Spacing.lg),
Text(
AppLocalizations.of(context)!.signIn,
textAlign: TextAlign.center,
style: context.conduitTheme.headingLarge?.copyWith(
fontWeight: FontWeight.w700,
height: 1.2,
fontWeight: FontWeight.w600,
height: 1.3,
),
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.microInteraction,
),
const SizedBox(height: Spacing.sm),
Text(
AppLocalizations.of(context)!.enterCredentials,
textAlign: TextAlign.center,
style: context.conduitTheme.bodyLarge?.copyWith(
style: context.conduitTheme.bodyMedium?.copyWith(
color: context.conduitTheme.textSecondary,
height: 1.5,
height: 1.4,
),
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.fast,
),
],
);
}
Widget _buildAuthForm() {
return ConduitCard(
isElevated: true,
padding: const EdgeInsets.all(Spacing.xl),
child: Column(
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Authentication mode toggle
@@ -367,18 +348,17 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
_buildErrorMessage(_loginError!),
],
],
),
);
}
Widget _buildAuthModeToggle() {
return Container(
padding: const EdgeInsets.all(4),
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: context.conduitTheme.surfaceContainer,
borderRadius: BorderRadius.circular(AppBorderRadius.button),
color: context.conduitTheme.surfaceContainer.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: context.conduitTheme.dividerColor,
color: context.conduitTheme.dividerColor.withValues(alpha: 0.5),
width: BorderWidth.standard,
),
),
@@ -406,9 +386,6 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
),
],
),
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.microInteraction,
);
}
@@ -425,13 +402,13 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
color: isSelected
? context.conduitTheme.buttonPrimary
: Colors.transparent,
borderRadius: BorderRadius.circular(AppBorderRadius.button - 2),
borderRadius: BorderRadius.circular(AppBorderRadius.small - 1),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(AppBorderRadius.button - 2),
borderRadius: BorderRadius.circular(AppBorderRadius.small - 1),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: Spacing.md,
vertical: Spacing.sm,
horizontal: Spacing.sm,
),
child: Row(
@@ -444,10 +421,10 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
? context.conduitTheme.buttonPrimaryText
: context.conduitTheme.iconSecondary,
),
const SizedBox(width: Spacing.sm),
const SizedBox(width: Spacing.xs),
Text(
label,
style: context.conduitTheme.bodyMedium?.copyWith(
style: context.conduitTheme.bodySmall?.copyWith(
color: isSelected
? context.conduitTheme.buttonPrimaryText
: context.conduitTheme.textSecondary,
@@ -590,8 +567,7 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
Widget _buildSignInButton() {
return Padding(
padding: const EdgeInsets.only(top: Spacing.lg),
child:
ConduitButton(
child: ConduitButton(
text: _isSigningIn
? AppLocalizations.of(context)!.signingIn
: _useApiKey
@@ -605,9 +581,6 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
onPressed: _isSigningIn ? null : _signIn,
isLoading: _isSigningIn,
isFullWidth: true,
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.fast,
),
);
}
@@ -619,10 +592,10 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
child: Container(
padding: const EdgeInsets.all(Spacing.md),
decoration: BoxDecoration(
color: context.conduitTheme.errorBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.button),
color: context.conduitTheme.error.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: context.conduitTheme.error.withValues(alpha: 0.3),
color: context.conduitTheme.error.withValues(alpha: 0.2),
width: BorderWidth.standard,
),
),
@@ -630,16 +603,16 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
children: [
Icon(
Platform.isIOS
? CupertinoIcons.exclamationmark_circle_fill
? CupertinoIcons.exclamationmark_circle
: Icons.error_outline,
color: context.conduitTheme.error,
size: IconSize.medium,
size: IconSize.small,
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Text(
message,
style: context.conduitTheme.bodyMedium?.copyWith(
style: context.conduitTheme.bodySmall?.copyWith(
color: context.conduitTheme.error,
),
),
@@ -647,10 +620,6 @@ class _AuthenticationPageState extends ConsumerState<AuthenticationPage> {
],
),
),
).animate().slideX(
begin: 0.05,
duration: AnimationDuration.messageSlide,
curve: Curves.easeOutCubic,
);
}
}

View File

@@ -231,13 +231,13 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
// Header with progress indicator
_buildHeader(),
const SizedBox(height: Spacing.extraLarge),
const SizedBox(height: Spacing.xl),
// Main content
Expanded(
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
constraints: const BoxConstraints(maxWidth: 480),
child: Form(
key: _formKey,
child: Column(
@@ -246,17 +246,17 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
// Brand header
_buildBrandHeader(reviewerMode),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
// Welcome section
_buildWelcomeSection(),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
// Reviewer mode demo (if enabled)
if (reviewerMode) ...[
_buildReviewerModeSection(),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
],
// Server connection form
@@ -286,8 +286,8 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
Row(
children: [
Container(
width: 32,
height: 6,
width: 24,
height: 4,
decoration: BoxDecoration(
color: context.conduitTheme.buttonPrimary,
borderRadius: BorderRadius.circular(AppBorderRadius.round),
@@ -295,10 +295,10 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
),
const SizedBox(width: Spacing.xs),
Container(
width: 32,
height: 6,
width: 24,
height: 4,
decoration: BoxDecoration(
color: context.conduitTheme.dividerColor,
color: context.conduitTheme.dividerColor.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(AppBorderRadius.round),
),
),
@@ -325,43 +325,20 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
),
);
},
child: Column(
children: [
Stack(
child: Stack(
alignment: Alignment.center,
children: [
// Glow effect
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
context.conduitTheme.buttonPrimary.withValues(
alpha: 0.12,
),
context.conduitTheme.buttonPrimary.withValues(
alpha: 0.06,
),
Colors.transparent,
],
stops: const [0.0, 0.7, 1.0],
radius: 0.8,
),
),
),
// Brand logo
BrandService.createBrandIcon(
size: 64,
useGradient: true,
addShadow: true,
size: 56,
useGradient: false,
addShadow: false,
context: context,
),
// Reviewer mode badge
if (reviewerMode)
Positioned(
bottom: 0,
bottom: -4,
child: ConduitBadge(
text: AppLocalizations.of(context)!.demoBadge,
backgroundColor: context.conduitTheme.warning.withValues(
@@ -373,11 +350,6 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
),
],
),
],
),
).animate().scale(
duration: AnimationDuration.pageTransition,
curve: Curves.easeOutBack,
);
}
@@ -388,24 +360,18 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
AppLocalizations.of(context)!.connectToServer,
textAlign: TextAlign.center,
style: context.conduitTheme.headingLarge?.copyWith(
fontWeight: FontWeight.w700,
height: 1.2,
fontWeight: FontWeight.w600,
height: 1.3,
),
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.microInteraction,
),
const SizedBox(height: Spacing.sm),
Text(
AppLocalizations.of(context)!.enterServerAddress,
textAlign: TextAlign.center,
style: context.conduitTheme.bodyLarge?.copyWith(
style: context.conduitTheme.bodyMedium?.copyWith(
color: context.conduitTheme.textSecondary,
height: 1.5,
height: 1.4,
),
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.fast,
),
],
);
@@ -464,10 +430,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
}
Widget _buildServerForm() {
return ConduitCard(
isElevated: true,
padding: const EdgeInsets.all(Spacing.xl),
child: Column(
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AccessibleFormField(
@@ -488,11 +451,6 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
),
autofillHints: const [AutofillHints.url],
isRequired: true,
).animate().slideX(
begin: -0.05,
duration: AnimationDuration.messageSlide,
delay: AnimationDuration.microInteraction,
curve: Curves.easeOutCubic,
),
if (_connectionError != null) ...[
@@ -505,17 +463,11 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
// Advanced settings
_buildAdvancedSettings(),
],
),
);
}
Widget _buildAdvancedSettings() {
return Column(
children: [
ConduitCard(
isElevated: false,
padding: const EdgeInsets.all(Spacing.lg),
child: Column(
children: [
InkWell(
onTap: () => setState(
@@ -523,33 +475,35 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
),
borderRadius: BorderRadius.circular(AppBorderRadius.button),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: Spacing.sm),
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.sm,
),
child: Row(
children: [
Icon(
Platform.isIOS ? CupertinoIcons.gear : Icons.tune,
Platform.isIOS ? CupertinoIcons.gear_alt : Icons.settings,
color: context.conduitTheme.iconSecondary,
size: IconSize.medium,
size: IconSize.small,
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
child: Text(
AppLocalizations.of(context)!.advancedSettings,
style: context.conduitTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
if (_customHeaders.isNotEmpty)
Text(
'${_customHeaders.length} custom header${_customHeaders.length != 1 ? 's' : ''}',
style: context.conduitTheme.bodySmall?.copyWith(
color: context.conduitTheme.textSecondary,
),
),
],
),
if (_customHeaders.isNotEmpty)
Padding(
padding: const EdgeInsets.only(right: Spacing.sm),
child: ConduitBadge(
text: '${_customHeaders.length}',
backgroundColor: context.conduitTheme.buttonPrimary
.withValues(alpha: 0.1),
textColor: context.conduitTheme.buttonPrimary,
isCompact: true,
),
),
AnimatedRotation(
@@ -560,6 +514,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
? CupertinoIcons.chevron_down
: Icons.expand_more,
color: context.conduitTheme.iconSecondary,
size: IconSize.small,
),
),
],
@@ -574,25 +529,22 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
: const SizedBox.shrink(),
),
],
),
),
],
);
}
Widget _buildAdvancedSettingsContent() {
return Column(
return Padding(
padding: const EdgeInsets.all(Spacing.md),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: Spacing.lg),
ConduitDivider(),
const SizedBox(height: Spacing.lg),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
AppLocalizations.of(context)!.customHeaders,
style: context.conduitTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
style: context.conduitTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w500,
),
),
if (_customHeaders.isNotEmpty)
@@ -629,7 +581,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
keyboardType: TextInputType.text,
),
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
flex: 3,
child: AccessibleFormField(
@@ -642,7 +594,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
keyboardType: TextInputType.text,
),
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
ConduitIconButton(
icon: Platform.isIOS ? CupertinoIcons.plus : Icons.add,
onPressed: _customHeaders.length >= 10 ? null : _addCustomHeader,
@@ -659,10 +611,11 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
],
),
if (_customHeaders.isNotEmpty) ...[
const SizedBox(height: Spacing.lg),
const SizedBox(height: Spacing.md),
_buildCustomHeadersList(),
],
],
),
);
}
@@ -670,33 +623,32 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
return Column(
children: _customHeaders.entries.map((entry) {
return Container(
margin: const EdgeInsets.only(bottom: Spacing.sm),
padding: const EdgeInsets.all(Spacing.md),
margin: const EdgeInsets.only(bottom: Spacing.xs),
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.sm,
),
decoration: BoxDecoration(
color: context.conduitTheme.surfaceContainer.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppBorderRadius.button),
color: context.conduitTheme.surfaceContainer.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: context.conduitTheme.dividerColor,
color: context.conduitTheme.dividerColor.withValues(alpha: 0.5),
width: BorderWidth.standard,
),
),
child: Row(
children: [
// Make the header badge flexible and truncate long text
Flexible(
fit: FlexFit.loose,
child: ConduitBadge(
text: entry.key,
backgroundColor: context.conduitTheme.buttonPrimary
.withValues(alpha: 0.1),
textColor: context.conduitTheme.buttonPrimary,
isCompact: true,
maxLines: 1,
child: Text(
entry.key,
style: context.conduitTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w500,
),
overflow: TextOverflow.ellipsis,
softWrap: false,
),
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Text(
entry.value,
@@ -707,20 +659,18 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
ConduitIconButton(
icon: Platform.isIOS ? CupertinoIcons.xmark : Icons.close,
onPressed: () => _removeCustomHeader(entry.key),
tooltip: AppLocalizations.of(context)!.removeHeader,
backgroundColor: context.conduitTheme.error.withValues(
alpha: 0.1,
),
iconColor: context.conduitTheme.error,
backgroundColor: Colors.transparent,
iconColor: context.conduitTheme.textSecondary,
isCompact: true,
),
],
),
).animate().fadeIn(duration: AnimationDuration.microInteraction);
);
}).toList(),
);
}
@@ -728,8 +678,7 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
Widget _buildConnectButton() {
return Padding(
padding: const EdgeInsets.only(top: Spacing.lg),
child:
ConduitButton(
child: ConduitButton(
text: _isConnecting
? AppLocalizations.of(context)!.connecting
: AppLocalizations.of(context)!.connectToServerButton,
@@ -741,9 +690,6 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
onPressed: _isConnecting ? null : _connectToServer,
isLoading: _isConnecting,
isFullWidth: true,
).animate().fadeIn(
duration: AnimationDuration.pageTransition,
delay: AnimationDuration.fast,
),
);
}
@@ -752,14 +698,13 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
return Semantics(
liveRegion: true,
label: message,
child:
Container(
child: Container(
padding: const EdgeInsets.all(Spacing.md),
decoration: BoxDecoration(
color: context.conduitTheme.errorBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.button),
color: context.conduitTheme.error.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: context.conduitTheme.error.withValues(alpha: 0.3),
color: context.conduitTheme.error.withValues(alpha: 0.2),
width: BorderWidth.standard,
),
),
@@ -767,26 +712,22 @@ class _ServerConnectionPageState extends ConsumerState<ServerConnectionPage> {
children: [
Icon(
Platform.isIOS
? CupertinoIcons.exclamationmark_circle_fill
? CupertinoIcons.exclamationmark_circle
: Icons.error_outline,
color: context.conduitTheme.error,
size: IconSize.medium,
size: IconSize.small,
),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Text(
message,
style: context.conduitTheme.bodyMedium?.copyWith(
style: context.conduitTheme.bodySmall?.copyWith(
color: context.conduitTheme.error,
),
),
),
],
),
).animate().slideX(
begin: 0.05,
duration: AnimationDuration.messageSlide,
curve: Curves.easeOutCubic,
),
);
}

View File

@@ -1991,39 +1991,27 @@ class _ModelSelectorSheetState extends ConsumerState<_ModelSelectorSheet> {
final iconUrl = resolveModelIconUrlForModel(api, model);
return PressableScale(
onTap: onTap,
borderRadius: BorderRadius.circular(AppBorderRadius.md),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
child: Container(
margin: const EdgeInsets.only(bottom: Spacing.md),
margin: const EdgeInsets.only(bottom: Spacing.sm),
decoration: BoxDecoration(
gradient: isSelected
? LinearGradient(
colors: [
context.conduitTheme.buttonPrimary.withValues(alpha: 0.2),
context.conduitTheme.buttonPrimary.withValues(alpha: 0.1),
],
)
: null,
color: isSelected
? null
? context.conduitTheme.buttonPrimary.withValues(alpha: 0.1)
: context.conduitTheme.surfaceBackground.withValues(alpha: 0.05),
borderRadius: BorderRadius.circular(AppBorderRadius.md),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: isSelected
? context.conduitTheme.buttonPrimary.withValues(alpha: 0.5)
: context.conduitTheme.dividerColor,
width: BorderWidth.regular,
? context.conduitTheme.buttonPrimary.withValues(alpha: 0.3)
: context.conduitTheme.dividerColor.withValues(alpha: 0.5),
width: BorderWidth.standard,
),
boxShadow: isSelected ? ConduitShadows.card(context) : null,
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.sm,
),
padding: const EdgeInsets.all(Spacing.sm),
child: Row(
children: [
ModelAvatar(size: 32, imageUrl: iconUrl, label: model.name),
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -2038,6 +2026,7 @@ class _ModelSelectorSheetState extends ConsumerState<_ModelSelectorSheet> {
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
if (model.isMultimodal || _modelSupportsReasoning(model)) ...[
const SizedBox(height: Spacing.xs),
Row(
children: [
@@ -2058,45 +2047,21 @@ class _ModelSelectorSheetState extends ConsumerState<_ModelSelectorSheet> {
],
),
],
],
),
),
const SizedBox(width: Spacing.md),
AnimatedOpacity(
opacity: isSelected ? 1 : 0.6,
duration: AnimationDuration.fast,
child: Container(
padding: const EdgeInsets.all(Spacing.xxs),
decoration: BoxDecoration(
color: isSelected
? context.conduitTheme.buttonPrimary
: context.conduitTheme.surfaceBackground,
borderRadius: BorderRadius.circular(AppBorderRadius.md),
border: Border.all(
color: isSelected
? context.conduitTheme.buttonPrimary.withValues(
alpha: 0.6,
)
: context.conduitTheme.dividerColor,
),
),
child: Icon(
isSelected
? (Platform.isIOS
? CupertinoIcons.check_mark
: Icons.check)
: (Platform.isIOS ? CupertinoIcons.add : Icons.add),
color: isSelected
? context.conduitTheme.textInverse
: context.conduitTheme.iconSecondary,
size: 14,
),
),
const SizedBox(width: Spacing.sm),
if (isSelected)
Icon(
Platform.isIOS ? CupertinoIcons.check_mark : Icons.check,
color: context.conduitTheme.buttonPrimary,
size: IconSize.small,
),
],
),
),
),
).animate().fadeIn(duration: AnimationDuration.microInteraction);
);
}
// Intentionally left blank placeholder for nested helper; moved to top-level below

View File

@@ -62,9 +62,9 @@ class AppCustomizationPage extends ConsumerWidget {
settings,
activePalette,
),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
_buildQuickPillsSection(context, ref, settings),
const SizedBox(height: Spacing.sectionGap),
const SizedBox(height: Spacing.xl),
_buildChatSection(context, ref, settings),
],
),
@@ -170,7 +170,7 @@ class AppCustomizationPage extends ConsumerWidget {
final theme = context.conduitTheme;
return ConduitCard(
padding: const EdgeInsets.all(Spacing.cardPadding),
padding: const EdgeInsets.all(Spacing.md),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -192,24 +192,17 @@ class AppCustomizationPage extends ConsumerWidget {
children: [
Text(
AppLocalizations.of(context)!.darkMode,
style:
theme.bodyLarge?.copyWith(
color: theme.textPrimary,
fontWeight: FontWeight.w600,
) ??
TextStyle(
style: theme.bodyMedium?.copyWith(
color: theme.textPrimary,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: Spacing.textSpacing),
const SizedBox(height: Spacing.xs),
Text(
themeDescription,
style:
theme.bodySmall?.copyWith(
style: theme.bodySmall?.copyWith(
color: theme.textSecondary,
) ??
TextStyle(color: theme.textSecondary),
),
),
],
),
@@ -290,7 +283,7 @@ class AppCustomizationPage extends ConsumerWidget {
),
const SizedBox(height: Spacing.sm),
ConduitCard(
padding: const EdgeInsets.all(Spacing.cardPadding),
padding: const EdgeInsets.all(Spacing.md),
child: Column(
children: [
for (final palette in palettes)
@@ -387,7 +380,7 @@ class AppCustomizationPage extends ConsumerWidget {
),
const SizedBox(height: Spacing.sm),
ConduitCard(
padding: const EdgeInsets.all(Spacing.cardPadding),
padding: const EdgeInsets.all(Spacing.md),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -406,11 +399,9 @@ class AppCustomizationPage extends ConsumerWidget {
Expanded(
child: Text(
AppLocalizations.of(context)!.quickActionsDescription,
style:
theme.bodySmall?.copyWith(
style: theme.bodySmall?.copyWith(
color: theme.textSecondary,
) ??
TextStyle(color: theme.textSecondary),
),
),
),
TextButton(
@@ -514,18 +505,18 @@ class AppCustomizationPage extends ConsumerWidget {
required Color color,
}) {
return Container(
width: 48,
height: 48,
width: 40,
height: 40,
decoration: BoxDecoration(
color: color.withValues(alpha: Alpha.highlight),
borderRadius: BorderRadius.circular(AppBorderRadius.medium),
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: color.withValues(alpha: 0.2),
width: BorderWidth.thin,
),
),
alignment: Alignment.center,
child: Icon(icon, color: color, size: IconSize.large),
child: Icon(icon, color: color, size: IconSize.medium),
);
}
@@ -629,14 +620,7 @@ class _PaletteOption extends StatelessWidget {
Expanded(
child: Text(
palette.label,
style:
theme.bodyLarge?.copyWith(
color: theme.textPrimary,
fontWeight: isSelected
? FontWeight.w600
: FontWeight.w500,
) ??
TextStyle(
style: theme.bodyMedium?.copyWith(
color: theme.textPrimary,
fontWeight: isSelected
? FontWeight.w600
@@ -725,10 +709,7 @@ class _CustomizationTile extends StatelessWidget {
Widget build(BuildContext context) {
final theme = context.conduitTheme;
return ConduitCard(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.listItemPadding,
vertical: Spacing.md,
),
padding: const EdgeInsets.all(Spacing.md),
onTap: onTap,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
@@ -741,31 +722,24 @@ class _CustomizationTile extends StatelessWidget {
children: [
Text(
title,
style:
theme.bodyLarge?.copyWith(
color: theme.textPrimary,
fontWeight: FontWeight.w600,
) ??
TextStyle(
style: theme.bodyMedium?.copyWith(
color: theme.textPrimary,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: Spacing.textSpacing),
const SizedBox(height: Spacing.xs),
Text(
subtitle,
style:
theme.bodySmall?.copyWith(color: theme.textSecondary) ??
TextStyle(color: theme.textSecondary),
style: theme.bodySmall?.copyWith(color: theme.textSecondary),
),
],
),
),
if (trailing != null) ...[
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
trailing!,
] else if (showChevron && onTap != null) ...[
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Icon(
UiUtils.platformIcon(
ios: CupertinoIcons.chevron_right,

View File

@@ -144,38 +144,11 @@ class ProfilePage extends ConsumerWidget {
vertical: Spacing.pagePadding,
),
children: [
_buildProfileHeader(context, userData, api)
.animate()
.fadeIn(duration: AnimationDuration.pageTransition)
.slideY(
begin: 0.1,
end: 0,
curve: AnimationCurves.pageTransition,
),
const SizedBox(height: Spacing.sectionGap),
_buildAccountSection(context, ref)
.animate()
.fadeIn(
delay: AnimationDelay.short,
duration: AnimationDuration.pageTransition,
)
.slideY(
begin: 0.08,
end: 0,
curve: AnimationCurves.pageTransition,
),
const SizedBox(height: Spacing.sectionGap),
_buildSupportSection(context)
.animate()
.fadeIn(
delay: AnimationDelay.medium,
duration: AnimationDuration.pageTransition,
)
.slideY(
begin: 0.08,
end: 0,
curve: AnimationCurves.pageTransition,
),
_buildProfileHeader(context, userData, api),
const SizedBox(height: Spacing.xl),
_buildAccountSection(context, ref),
const SizedBox(height: Spacing.xl),
_buildSupportSection(context),
],
),
);
@@ -318,25 +291,14 @@ class ProfilePage extends ConsumerWidget {
final accent = theme.buttonPrimary;
return Container(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.sm,
),
padding: const EdgeInsets.all(Spacing.md),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
accent.withValues(alpha: 0.22),
accent.withValues(alpha: 0.06),
],
),
borderRadius: BorderRadius.circular(AppBorderRadius.extraLarge),
color: accent.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(AppBorderRadius.large),
border: Border.all(
color: accent.withValues(alpha: 0.18),
color: accent.withValues(alpha: 0.15),
width: BorderWidth.thin,
),
boxShadow: ConduitShadows.medium(context),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -344,17 +306,11 @@ class ProfilePage extends ConsumerWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(AppBorderRadius.avatar),
boxShadow: ConduitShadows.high(context),
),
child: UserAvatar(
size: IconSize.avatar,
UserAvatar(
size: 56,
imageUrl: avatarUrl,
fallbackText: initial,
),
),
const SizedBox(width: Spacing.md),
Expanded(
child: Column(
@@ -362,31 +318,13 @@ class ProfilePage extends ConsumerWidget {
children: [
Text(
displayName,
style:
theme.headingMedium?.copyWith(
style: theme.headingMedium?.copyWith(
color: theme.textPrimary,
fontWeight: FontWeight.w700,
) ??
TextStyle(
color: theme.textPrimary,
fontWeight: FontWeight.w700,
fontSize: 22,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: Spacing.sm),
Container(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.sm,
vertical: Spacing.xs,
),
decoration: BoxDecoration(
color: theme.surfaceBackground.withValues(alpha: 0.75),
borderRadius: BorderRadius.circular(
AppBorderRadius.round,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
const SizedBox(height: Spacing.xs),
Row(
children: [
Icon(
UiUtils.platformIcon(
@@ -400,18 +338,15 @@ class ProfilePage extends ConsumerWidget {
Flexible(
child: Text(
email,
style:
theme.bodySmall?.copyWith(
style: theme.bodySmall?.copyWith(
color: theme.textSecondary,
) ??
TextStyle(color: theme.textSecondary),
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
),
],
),
),
@@ -523,11 +458,11 @@ class ProfilePage extends ConsumerWidget {
Widget leading;
if (selectedModelExplicit) {
leading = Container(
width: 48,
height: 48,
width: 40,
height: 40,
decoration: BoxDecoration(
color: theme.surfaceBackground.withValues(alpha: 0.85),
borderRadius: BorderRadius.circular(AppBorderRadius.medium),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: theme.cardBorder,
width: BorderWidth.thin,
@@ -535,7 +470,7 @@ class ProfilePage extends ConsumerWidget {
),
alignment: Alignment.center,
child: ModelAvatar(
size: 32,
size: 28,
imageUrl: modelIconUrl,
label: currentModel.name,
),
@@ -617,18 +552,18 @@ class ProfilePage extends ConsumerWidget {
required Color color,
}) {
return Container(
width: 48,
height: 48,
width: 40,
height: 40,
decoration: BoxDecoration(
color: color.withValues(alpha: Alpha.highlight),
borderRadius: BorderRadius.circular(AppBorderRadius.medium),
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppBorderRadius.small),
border: Border.all(
color: color.withValues(alpha: 0.2),
width: BorderWidth.thin,
),
),
alignment: Alignment.center,
child: Icon(icon, color: color, size: IconSize.large),
child: Icon(icon, color: color, size: IconSize.medium),
);
}
@@ -795,10 +730,7 @@ class _ProfileSettingTile extends StatelessWidget {
: theme.textSecondary;
return ConduitCard(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.listItemPadding,
vertical: Spacing.md,
),
padding: const EdgeInsets.all(Spacing.md),
onTap: onTap,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
@@ -811,28 +743,24 @@ class _ProfileSettingTile extends StatelessWidget {
children: [
Text(
title,
style:
theme.bodyLarge?.copyWith(
style: theme.bodyMedium?.copyWith(
color: textColor,
fontWeight: FontWeight.w600,
) ??
TextStyle(color: textColor, fontWeight: FontWeight.w600),
),
const SizedBox(height: Spacing.textSpacing),
),
const SizedBox(height: Spacing.xs),
Text(
subtitle,
style:
theme.bodySmall?.copyWith(color: subtitleColor) ??
TextStyle(color: subtitleColor),
style: theme.bodySmall?.copyWith(color: subtitleColor),
),
],
),
),
if (trailing != null) ...[
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
trailing!,
] else if (showChevron && onTap != null) ...[
const SizedBox(width: Spacing.md),
const SizedBox(width: Spacing.sm),
Icon(
UiUtils.platformIcon(
ios: CupertinoIcons.chevron_right,
@@ -1331,6 +1259,6 @@ class _DefaultModelBottomSheetState
),
),
),
).animate().fadeIn(duration: AnimationDuration.microInteraction);
);
}
}