refactor: Improve chat input UI with enhanced microphone icon handling
- Updated the background color logic in the chat input to use a more consistent alpha value based on brightness. - Simplified the layout of the chat input by removing unnecessary alignment and shadow properties. - Introduced a new inline microphone icon that activates voice input, improving user interaction. - Enhanced the overall structure of the chat input widget for better readability and maintainability.
This commit is contained in:
@@ -802,9 +802,9 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
minHeight: TouchTarget.input,
|
minHeight: TouchTarget.input,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: brightness == Brightness.dark
|
color: composerSurface.withValues(
|
||||||
? composerSurface.withValues(alpha: 0.9)
|
alpha: brightness == Brightness.dark ? 0.9 : 0.2,
|
||||||
: context.conduitTheme.surfaceContainer,
|
),
|
||||||
borderRadius: BorderRadius.circular(AppBorderRadius.round),
|
borderRadius: BorderRadius.circular(AppBorderRadius.round),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: outlineColor.withValues(
|
color: outlineColor.withValues(
|
||||||
@@ -812,37 +812,28 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
),
|
),
|
||||||
width: BorderWidth.micro,
|
width: BorderWidth.micro,
|
||||||
),
|
),
|
||||||
boxShadow: <BoxShadow>[
|
|
||||||
BoxShadow(
|
|
||||||
color: shellShadowColor.withValues(
|
|
||||||
alpha: brightness == Brightness.dark ? 0.4 : 0.22,
|
|
||||||
),
|
|
||||||
blurRadius: 24,
|
|
||||||
spreadRadius: -6,
|
|
||||||
offset: const Offset(0, 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Align(
|
child: Row(
|
||||||
alignment: Alignment.centerLeft,
|
children: [
|
||||||
child: _buildComposerTextField(
|
Expanded(
|
||||||
brightness: brightness,
|
child: _buildComposerTextField(
|
||||||
sendOnEnter: sendOnEnter,
|
brightness: brightness,
|
||||||
placeholderBase: placeholderBase,
|
sendOnEnter: sendOnEnter,
|
||||||
placeholderFocused: placeholderFocused,
|
placeholderBase: placeholderBase,
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
placeholderFocused: placeholderFocused,
|
||||||
vertical: Spacing.xs,
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
vertical: Spacing.xs,
|
||||||
|
),
|
||||||
|
isActive: isActive,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
isActive: isActive,
|
if (!_hasText && voiceAvailable && !isGenerating)
|
||||||
),
|
_buildInlineMicIcon(voiceAvailable),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: Spacing.sm),
|
const SizedBox(width: Spacing.sm),
|
||||||
if (!_hasText && voiceAvailable && !isGenerating)
|
|
||||||
_buildMicButton(voiceAvailable),
|
|
||||||
if (!_hasText && voiceAvailable && !isGenerating)
|
|
||||||
const SizedBox(width: Spacing.sm),
|
|
||||||
_buildPrimaryButton(
|
_buildPrimaryButton(
|
||||||
_hasText,
|
_hasText,
|
||||||
isGenerating,
|
isGenerating,
|
||||||
@@ -1199,7 +1190,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
|
|
||||||
const double iconSize = IconSize.large;
|
const double iconSize = IconSize.large;
|
||||||
const double buttonSize = TouchTarget.minimum;
|
const double buttonSize = TouchTarget.minimum;
|
||||||
final Brightness brightness = Theme.of(context).brightness;
|
|
||||||
final bool isActive = activeColor != null;
|
final bool isActive = activeColor != null;
|
||||||
|
|
||||||
final Color iconColor = !enabled
|
final Color iconColor = !enabled
|
||||||
@@ -1207,9 +1197,9 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
: (activeColor ??
|
: (activeColor ??
|
||||||
context.conduitTheme.textPrimary.withValues(alpha: Alpha.strong));
|
context.conduitTheme.textPrimary.withValues(alpha: Alpha.strong));
|
||||||
|
|
||||||
final Color baseBackground = brightness == Brightness.dark
|
final Brightness brightness = Theme.of(context).brightness;
|
||||||
? context.conduitTheme.surfaceContainerHighest.withValues(alpha: 0.7)
|
final Color baseBackground = context.conduitTheme.inputBackground
|
||||||
: context.conduitTheme.surfaceContainerHighest;
|
.withValues(alpha: brightness == Brightness.dark ? 0.9 : 0.2);
|
||||||
final Color backgroundColor = !enabled
|
final Color backgroundColor = !enabled
|
||||||
? baseBackground.withValues(alpha: Alpha.disabled)
|
? baseBackground.withValues(alpha: Alpha.disabled)
|
||||||
: isActive
|
: isActive
|
||||||
@@ -1218,14 +1208,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
final Color borderColor = isActive
|
final Color borderColor = isActive
|
||||||
? context.conduitTheme.buttonPrimary.withValues(alpha: 0.6)
|
? context.conduitTheme.buttonPrimary.withValues(alpha: 0.6)
|
||||||
: context.conduitTheme.cardBorder.withValues(alpha: 0.45);
|
: context.conduitTheme.cardBorder.withValues(alpha: 0.45);
|
||||||
final BoxShadow buttonShadow = BoxShadow(
|
|
||||||
color: context.conduitTheme.cardShadow.withValues(
|
|
||||||
alpha: brightness == Brightness.dark ? 0.36 : 0.18,
|
|
||||||
),
|
|
||||||
blurRadius: 18,
|
|
||||||
spreadRadius: -6,
|
|
||||||
offset: const Offset(0, 8),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
message: tooltip,
|
message: tooltip,
|
||||||
@@ -1250,7 +1232,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
borderRadius: BorderRadius.circular(AppBorderRadius.round),
|
borderRadius: BorderRadius.circular(AppBorderRadius.round),
|
||||||
border: Border.all(color: borderColor, width: BorderWidth.thin),
|
border: Border.all(color: borderColor, width: BorderWidth.thin),
|
||||||
boxShadow: enabled ? <BoxShadow>[buttonShadow] : const [],
|
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Icon(icon, size: iconSize, color: iconColor),
|
child: Icon(icon, size: iconSize, color: iconColor),
|
||||||
@@ -1301,6 +1282,34 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildInlineMicIcon(bool voiceAvailable) {
|
||||||
|
final bool enabledMic = widget.enabled && voiceAvailable;
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(AppBorderRadius.circular),
|
||||||
|
onTap: enabledMic
|
||||||
|
? () {
|
||||||
|
HapticFeedback.selectionClick();
|
||||||
|
_toggleVoice();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(Spacing.xs),
|
||||||
|
child: Icon(
|
||||||
|
Platform.isIOS ? CupertinoIcons.mic : Icons.mic,
|
||||||
|
size: IconSize.medium,
|
||||||
|
color: _isRecording
|
||||||
|
? context.conduitTheme.buttonPrimary
|
||||||
|
: context.conduitTheme.textSecondary.withValues(
|
||||||
|
alpha: enabledMic ? Alpha.strong : Alpha.disabled,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildPrimaryButton(
|
Widget _buildPrimaryButton(
|
||||||
bool hasText,
|
bool hasText,
|
||||||
bool isGenerating,
|
bool isGenerating,
|
||||||
|
|||||||
Reference in New Issue
Block a user