refactor: fix lints

This commit is contained in:
cogwheel0
2025-09-16 18:15:44 +05:30
parent a5d5f60ed7
commit f80930685c
12 changed files with 277 additions and 266 deletions

View File

@@ -181,10 +181,12 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
final isExpanded = _expandedToolIds.contains(tc.id);
final theme = context.conduitTheme;
String _pretty(dynamic v, {int max = 1200}) {
String pretty(dynamic v, {int max = 1200}) {
try {
final pretty = const JsonEncoder.withIndent(' ').convert(v);
return pretty.length > max ? '${pretty.substring(0, max)}\n' : pretty;
final formatted = const JsonEncoder.withIndent(' ').convert(v);
return formatted.length > max
? '${formatted.substring(0, max)}\n'
: formatted;
} catch (_) {
final s = v?.toString() ?? '';
return s.length > max ? '${s.substring(0, max)}' : s;
@@ -233,7 +235,9 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
),
const SizedBox(width: Spacing.xs),
Icon(
tc.done ? Icons.build_circle_outlined : Icons.play_circle_outline,
tc.done
? Icons.build_circle_outlined
: Icons.play_circle_outline,
size: 14,
color: theme.buttonPrimary,
),
@@ -281,7 +285,7 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
),
const SizedBox(height: Spacing.xxs),
SelectableText(
_pretty(tc.arguments),
pretty(tc.arguments),
style: TextStyle(
fontSize: AppTypography.bodySmall,
color: theme.textSecondary,
@@ -303,7 +307,7 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
),
const SizedBox(height: Spacing.xxs),
SelectableText(
_pretty(tc.result),
pretty(tc.result),
style: TextStyle(
fontSize: AppTypography.bodySmall,
color: theme.textSecondary,
@@ -315,8 +319,9 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
],
),
),
crossFadeState:
isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
crossFadeState: isExpanded
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: const Duration(milliseconds: 200),
),
],
@@ -331,7 +336,7 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
// Determine if media (attachments or generated images) is rendered above.
final hasMediaAbove =
(widget.message.attachmentIds?.isNotEmpty ?? false) ||
(widget.message.files?.isNotEmpty ?? false);
(widget.message.files?.isNotEmpty ?? false);
bool firstToolSpacerAdded = false;
int idx = 0;
for (final seg in _segments) {
@@ -363,7 +368,7 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
}
bool get _hasRenderableSegments {
bool _textRenderable(String t) {
bool textRenderable(String t) {
String cleaned = t;
// Hide tool_calls blocks entirely
cleaned = cleaned.replaceAll(
@@ -398,7 +403,7 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
if (seg.isTool && seg.toolCall != null) return true;
if (seg.isReasoning && seg.reasoning != null) return true;
final text = seg.text ?? '';
if (_textRenderable(text)) return true;
if (textRenderable(text)) return true;
}
return false;
}
@@ -507,7 +512,8 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
),
);
},
child: (widget.isStreaming &&
child:
(widget.isStreaming &&
!_hasRenderableSegments &&
_allowTypingIndicator)
? KeyedSubtree(
@@ -566,8 +572,18 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
);
// Remove raw <think>...</think> or <reasoning>...</reasoning> tags in text
cleaned = cleaned
.replaceAll(RegExp(r'<think>[\s\S]*?<\/think>', multiLine: true, dotAll: true), '')
.replaceAll(RegExp(r'<reasoning>[\s\S]*?<\/reasoning>', multiLine: true, dotAll: true), '');
.replaceAll(
RegExp(r'<think>[\s\S]*?<\/think>', multiLine: true, dotAll: true),
'',
)
.replaceAll(
RegExp(
r'<reasoning>[\s\S]*?<\/reasoning>',
multiLine: true,
dotAll: true,
),
'',
);
// If there's an unclosed <details>, drop the tail to avoid raw tags.
final lastOpen = cleaned.lastIndexOf('<details');
@@ -699,7 +715,8 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
maxWidth: 500,
maxHeight: 400,
),
disableAnimation: false, // Keep animations enabled to prevent black display
disableAnimation:
false, // Keep animations enabled to prevent black display
);
},
),
@@ -722,7 +739,8 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
maxWidth: imageCount == 2 ? 245 : 160,
maxHeight: imageCount == 2 ? 245 : 160,
),
disableAnimation: false, // Keep animations enabled to prevent black display
disableAnimation:
false, // Keep animations enabled to prevent black display
);
}).toList(),
),
@@ -764,13 +782,10 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
Widget dot(Duration delay) {
return Container(
width: dotSize,
height: dotSize,
decoration: BoxDecoration(
color: dotColor,
shape: BoxShape.circle,
),
)
width: dotSize,
height: dotSize,
decoration: BoxDecoration(color: dotColor, shape: BoxShape.circle),
)
.animate(onPlay: (controller) => controller.repeat())
.then(delay: delay)
.scale(
@@ -816,13 +831,10 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
Widget dot(Duration delay) {
return Container(
width: dotSize,
height: dotSize,
decoration: BoxDecoration(
color: dotColor,
shape: BoxShape.circle,
),
)
width: dotSize,
height: dotSize,
decoration: BoxDecoration(color: dotColor, shape: BoxShape.circle),
)
.animate(onPlay: (controller) => controller.repeat())
.then(delay: delay)
.scale(
@@ -859,8 +871,6 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
);
}
Widget _buildActionButtons() {
final isErrorMessage =
widget.message.content.contains('⚠️') ||
@@ -914,7 +924,8 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
String headerText() {
final l10n = AppLocalizations.of(context)!;
final hasSummary = rc.summary.isNotEmpty;
final isThinkingSummary = rc.summary.trim().toLowerCase() == 'thinking…' ||
final isThinkingSummary =
rc.summary.trim().toLowerCase() == 'thinking…' ||
rc.summary.trim().toLowerCase() == 'thinking...';
if (widget.isStreaming) {
return hasSummary ? rc.summary : l10n.thinking;
@@ -1012,8 +1023,9 @@ class _AssistantMessageWidgetState extends ConsumerState<AssistantMessageWidget>
),
),
),
crossFadeState:
isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
crossFadeState: isExpanded
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
duration: const Duration(milliseconds: 200),
),
],

View File

@@ -131,7 +131,9 @@ class _EnhancedAttachmentState extends ConsumerState<EnhancedAttachment> {
if (path == null) return;
final filename = (_fileInfo?['filename'] ?? _fileInfo?['name'] ?? 'file')
.toString();
await Share.shareXFiles([XFile(path, name: filename)]);
await SharePlus.instance.share(
ShareParams(files: [XFile(path, name: filename)]),
);
}
String _fileIconFor(String filename) {

View File

@@ -151,7 +151,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
final FocusNode _focusNode = FocusNode();
bool _isRecording = false;
bool _isExpanded = true; // Start expanded for better UX
// TODO: Implement voice input functionality
// final String _voiceInputText = '';
bool _hasText = false; // track locally without rebuilding on each keystroke
StreamSubscription<String>? _voiceStreamSubscription;
@@ -414,8 +413,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
});
}
final bool showPlaceholder =
!_hasText && !_focusNode.hasFocus && !_isRecording;
final Brightness brightness = Theme.of(context).brightness;
final Color outlineColor = (_focusNode.hasFocus || _hasText)
? context.conduitTheme.inputBorderFocused.withValues(alpha: 0.6)
@@ -425,16 +422,6 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
);
final Color composerSurface = context.conduitTheme.inputBackground;
final Color placeholderColor = context.conduitTheme.inputPlaceholder;
final Color badgeBackground = showPlaceholder
? placeholderColor.withValues(alpha: 0.12)
: composerSurface.withValues(alpha: 0.3);
final Color badgeBorder = showPlaceholder
? Colors.transparent
: outlineColor.withValues(alpha: 0.35);
final Color badgeIconColor = showPlaceholder
? placeholderColor
: context.conduitTheme.textPrimary.withValues(alpha: 0.75);
return Container(
// Transparent wrapper so rounded corners are visible against page background
color: Colors.transparent,
@@ -679,21 +666,21 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
),
),
if (!_isExpanded) ...[
const SizedBox(width: Spacing.sm),
Row(
mainAxisSize: MainAxisSize.min,
children: [
if (voiceAvailable) ...[
_buildVoiceButton(voiceAvailable),
const SizedBox(width: Spacing.xs),
],
_buildPrimaryButton(
_hasText,
isGenerating,
stopGeneration,
),
const SizedBox(width: Spacing.sm),
Row(
mainAxisSize: MainAxisSize.min,
children: [
if (voiceAvailable) ...[
_buildVoiceButton(voiceAvailable),
const SizedBox(width: Spacing.xs),
],
),
_buildPrimaryButton(
_hasText,
isGenerating,
stopGeneration,
),
],
),
],
],
),
@@ -1017,7 +1004,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
// Append tools button at the end (always visible)
rowChildren..add(
rowChildren.add(
_buildIconButton(
icon: Platform.isIOS
? CupertinoIcons.wrench
@@ -1605,6 +1592,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
if (!widget.enabled) return;
try {
final ok = await _voiceService.initialize();
if (!mounted) return;
if (!ok) {
_showVoiceUnavailable(
AppLocalizations.of(context)?.errorMessage ??
@@ -1614,6 +1602,7 @@ class _ModernChatInputState extends ConsumerState<ModernChatInput>
}
// Centralized permission + start
final stream = await _voiceService.beginListening();
if (!mounted) return;
setState(() {
_isRecording = true;
_baseTextAtStart = _controller.text;