💫 Add tool call calling hint animation

This commit is contained in:
2025-11-15 23:22:07 +08:00
parent d201182bd2
commit f14da0d3a2
3 changed files with 76 additions and 35 deletions

View File

@@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@@ -34,7 +35,7 @@ class FunctionCallsSection extends HookWidget {
} }
if (functionCallName.isEmpty) functionCallName = 'unknown'.tr(); if (functionCallName.isEmpty) functionCallName = 'unknown'.tr();
final showSpinner = isStreaming && !isFinish; final showSpinner = !(isStreaming && !isFinish);
final isExpanded = useState(false); final isExpanded = useState(false);
@@ -51,11 +52,6 @@ class FunctionCallsSection extends HookWidget {
collapsedShape: RoundedRectangleBorder( collapsedShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
leading: Icon(
Symbols.hardware,
size: 16,
color: Theme.of(context).colorScheme.tertiary,
),
trailing: SizedBox( trailing: SizedBox(
width: 30, // Specify desired width width: 30, // Specify desired width
height: 30, // Specify desired height height: 30, // Specify desired height
@@ -70,8 +66,15 @@ class FunctionCallsSection extends HookWidget {
: Theme.of(context).colorScheme.tertiaryFixedDim, : Theme.of(context).colorScheme.tertiaryFixedDim,
), ),
), ),
showTrailingIcon: !showSpinner,
title: Row( title: Row(
spacing: 8,
children: [ children: [
Icon(
Symbols.hardware,
size: 16,
color: Theme.of(context).colorScheme.tertiary,
),
Expanded( Expanded(
child: Text( child: Text(
'thoughtFunctionCall'.tr(args: [functionCallName]), 'thoughtFunctionCall'.tr(args: [functionCallName]),
@@ -81,12 +84,29 @@ class FunctionCallsSection extends HookWidget {
), ),
), ),
), ),
if (showSpinner) if (showSpinner) ...[
AnimateWidgetExtensions(
Text(
'Calling',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: Theme.of(context).colorScheme.primary,
),
),
)
.animate(
autoPlay: true,
onPlay: (c) => c.repeat(reverse: true),
)
.fade(duration: 1000.ms, begin: 0, end: 1),
const SizedBox( const SizedBox(
height: 14, height: 16,
width: 14, width: 16,
child: CircularProgressIndicator(strokeWidth: 2), child: CircularProgressIndicator(
), strokeWidth: 2,
padding: EdgeInsets.all(3),
),
).padding(right: 8),
],
], ],
), ),
childrenPadding: const EdgeInsets.symmetric( childrenPadding: const EdgeInsets.symmetric(
@@ -137,34 +157,38 @@ class FunctionCallsSection extends HookWidget {
), ),
const Gap(4), const Gap(4),
if (isResult) if (isResult)
Row( Opacity(
spacing: 8, opacity: 0.8,
children: [ child: Row(
Icon(Symbols.update, size: 16), spacing: 8,
Expanded( children: [
child: Text( Icon(Symbols.update, size: 16),
'Generated ${utf8.encode(data).length} bytes', Expanded(
style: Theme.of(context).textTheme.bodySmall!.copyWith( child: Text(
fontWeight: FontWeight.w500, 'Generated ${utf8.encode(data).length} bytes',
color: Theme.of(context).colorScheme.onSurface, style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
), ),
), ),
), SizedBox(
SizedBox( height: 16,
height: 16, child: IconButton(
child: IconButton( iconSize: 16,
iconSize: 16, icon: const Icon(Symbols.content_copy),
icon: const Icon(Symbols.content_copy), onPressed:
onPressed: () => Clipboard.setData(ClipboardData(text: data)), () => Clipboard.setData(ClipboardData(text: data)),
tooltip: 'Copy response', tooltip: 'Copy response',
visualDensity: const VisualDensity( visualDensity: const VisualDensity(
horizontal: -4, horizontal: -4,
vertical: -4, vertical: -4,
),
), ),
), ),
), ],
], ),
).opacity(0.8) )
else else
Container( Container(
width: double.infinity, width: double.infinity,

View File

@@ -726,6 +726,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_animate:
dependency: "direct main"
description:
name: flutter_animate
sha256: "7befe2d3252728afb77aecaaea1dec88a89d35b9b1d2eea6d04479e8af9117b5"
url: "https://pub.dev"
source: hosted
version: "4.5.2"
flutter_app_update: flutter_app_update:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1075,6 +1083,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
flutter_shaders:
dependency: transitive
description:
name: flutter_shaders
sha256: "34794acadd8275d971e02df03afee3dee0f98dbfb8c4837082ad0034f612a3e2"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
flutter_staggered_grid_view: flutter_staggered_grid_view:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -168,6 +168,7 @@ dependencies:
event_bus: ^2.0.1 event_bus: ^2.0.1
convert: ^3.1.2 convert: ^3.1.2
desktop_drop: ^0.7.0 desktop_drop: ^0.7.0
flutter_animate: ^4.5.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: