From b307b5c88a434aa6b032fd6b955fdd122f482016 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Thu, 24 Apr 2025 19:26:14 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/chat/views/chat_view.dart | 25 +++- lib/modules/chat/views/cloud_background.dart | 144 +++++++++++++++++++ 2 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 lib/modules/chat/views/cloud_background.dart diff --git a/lib/modules/chat/views/chat_view.dart b/lib/modules/chat/views/chat_view.dart index 9f4864f0e..abc28324d 100644 --- a/lib/modules/chat/views/chat_view.dart +++ b/lib/modules/chat/views/chat_view.dart @@ -8,6 +8,7 @@ import '../../../core/theme/app_colors.dart'; import 'animated_gradient_background.dart'; import 'chat_music_card.dart'; import 'chat_navigation_card.dart'; +import 'cloud_background.dart'; import 'weather_day_card.dart'; class ChatView extends GetView { @@ -549,13 +550,23 @@ class ChatView extends GetView { children: [], ), Expanded( - child: Container( - width: 200.w, - height: 200.w, - decoration: BoxDecoration( - color: - isDarkMode ? Colors.white.withOpacity(0.1) : Colors.white, - shape: BoxShape.circle, + child: Center( + child: Container( + width: 200.w, + height: 200.w, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Colors.blue.withOpacity(0.4), + Colors.purple.withOpacity(0.4) + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + shape: BoxShape.circle, + ), + child: CircularFlowAnimation(), ), ), ), diff --git a/lib/modules/chat/views/cloud_background.dart b/lib/modules/chat/views/cloud_background.dart new file mode 100644 index 000000000..995e6a168 --- /dev/null +++ b/lib/modules/chat/views/cloud_background.dart @@ -0,0 +1,144 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class CircularFlowAnimation extends StatefulWidget { + const CircularFlowAnimation({super.key}); + + @override + State createState() => _CircularFlowAnimationState(); +} + +class _CircularFlowAnimationState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 20), + )..repeat(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return CustomPaint( + painter: CircularFlowPainter(_controller), + size: Size.infinite, + ); + } +} + +class CircularFlowPainter extends CustomPainter { + final Animation animation; + + CircularFlowPainter(this.animation) : super(repaint: animation); + + @override + void paint(Canvas canvas, Size size) { + final center = Offset(size.width / 2, size.height / 2); + const baseRadius = 150.0; + final time = animation.value * 2 * pi; + + // 绘制圆形路径 + _drawCircularPath(canvas, center, baseRadius); + + // 绘制三个围绕圆形运动的渐变云朵 + _drawOrbitingCloud( + canvas: canvas, + center: center, + time: time, + colors: [Colors.blue, Colors.purple], + orbitRadius: baseRadius, + speed: 0.5, + direction: 1, + ); + + _drawOrbitingCloud( + canvas: canvas, + center: center, + time: time, + colors: [Colors.pink, Colors.orange], + orbitRadius: baseRadius * 0.8, + speed: 1.0, + direction: -1, + ); + + _drawOrbitingCloud( + canvas: canvas, + center: center, + time: time, + colors: [Colors.green, Colors.yellow], + orbitRadius: baseRadius * 1.2, + speed: 0.3, + direction: 1, + ); + + _drawOrbitingCloud( + canvas: canvas, + center: center, + time: time, + colors: [Colors.red, Colors.deepOrangeAccent], + orbitRadius: baseRadius * 0.5, + speed: 0.8, + direction: -1, + ); + } + + void _drawCircularPath(Canvas canvas, Offset center, double radius) { + final paint = Paint() + ..color = Colors.red + ..style = PaintingStyle.stroke + ..strokeWidth = 2 + ..maskFilter = MaskFilter.blur(BlurStyle.normal, 4); + + canvas.drawCircle(center, radius, paint); + } + + void _drawOrbitingCloud({ + required Canvas canvas, + required Offset center, + required double time, + required List colors, + required double orbitRadius, + required double speed, + required int direction, + }) { + final angle = time * speed * direction; + final position = Offset( + center.dx + orbitRadius * cos(angle), + center.dy + orbitRadius * sin(angle), + ); + + final gradient = RadialGradient( + colors: colors, + stops: const [0.3, 1.0], + radius: 0.6, + focal: Alignment( + 0.1 + cos(angle * 2) * 0.3, + 0.1 + sin(angle * 2) * 0.3, + ), + ); + + final paint = Paint() + ..shader = gradient.createShader(Rect.fromCircle( + center: position, + radius: 100 + 30 * sin(time * 3), + )) + ..maskFilter = MaskFilter.blur(BlurStyle.normal, 40) + ..blendMode = BlendMode.plus; + + canvas.drawCircle(position, 80 + 20 * cos(time * 2), paint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => true; +} From 0ee1333f733effe72cf19206df355cdccbabb020 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Thu, 24 Apr 2025 21:00:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8C=89=E4=BD=8F?= =?UTF-8?q?=E8=AF=B4=E8=AF=9D=E9=98=B2=E6=8A=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controllers/chat_controller.dart | 60 +++++++++++-------- lib/modules/chat/views/chat_view.dart | 2 +- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 7776de777..5de5f28a7 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -98,7 +98,9 @@ class ChatController extends GetxController { String finalResult = ''; // 按住说话防抖 + bool isDebounce = false; Timer? _talkDebounceTimer; + Timer? _talkStartDebounceTimer; @override Future onInit() async { @@ -295,6 +297,7 @@ class ChatController extends GetxController { _autoStopTimer?.cancel(); _scrollDebounceTimer?.cancel(); // 清理防抖计时器 _talkDebounceTimer?.cancel(); + _talkStartDebounceTimer?.cancel(); _amapFlutter.dispose(); _locationStream?.cancel(); @@ -591,38 +594,46 @@ class ChatController extends GetxController { // 按下开始说话 void talkLongPress() async { + _talkStartDebounceTimer?.cancel(); _talkDebounceTimer?.cancel(); - if (isHoldSpeak.value) return; + isHoldSpeak.value = true; + Haptics.vibrate(HapticsType.success); - _voiceInteractionService.pauseVoiceInteraction(); - // 中断当前响应 - _interruptCurrentResponse("发送新消息,中断当前响应"); - try { - final recognitionStream = await _asrService.startContinuousRecognition(); - - await Future.delayed(const Duration(milliseconds: 150)); + _talkStartDebounceTimer = + Timer(const Duration(milliseconds: 260), () async { + if (isDebounce) return; - isHoldSpeak.value = true; - recognizedText.value = ''; - finalResult = ''; - Haptics.vibrate(HapticsType.success); + _voiceInteractionService.pauseVoiceInteraction(); + // 中断当前响应 + _interruptCurrentResponse("发送新消息,中断当前响应"); + try { + final recognitionStream = + await _asrService.startContinuousRecognition(); + await Future.delayed(const Duration(milliseconds: 260)); + isDebounce = true; + recognizedText.value = ''; + finalResult = ''; - // 监听识别事件 - _recognitionSubscription = recognitionStream.listen( - _handleRecognitionEvent, - onError: _handleRecognitionError, - ); - } catch (e) { - Logger.error('启动语音识别失败', e); - isHoldSpeak.value = false; - } + // 监听识别事件 + _recognitionSubscription = recognitionStream.listen( + _handleRecognitionEvent, + onError: _handleRecognitionError, + ); + } catch (e) { + Logger.error('启动语音识别失败', e); + isHoldSpeak.value = false; + } + }); } // 松开停止说话 void talkLongPressUp() async { + _talkStartDebounceTimer?.cancel(); _talkDebounceTimer?.cancel(); - _talkDebounceTimer = Timer(const Duration(milliseconds: 200), () async { - if (!isHoldSpeak.value) return; + isHoldSpeak.value = false; + + _talkDebounceTimer = Timer(const Duration(milliseconds: 300), () async { + if (!isDebounce) return; try { await _asrService.stopContinuousRecognition(); _recognitionSubscription?.cancel(); @@ -641,7 +652,8 @@ class ChatController extends GetxController { recognizedText.value = ''; finalResult = ''; - isHoldSpeak.value = false; + + isDebounce = false; } catch (e) { Logger.error('停止语音识别失败', e); } diff --git a/lib/modules/chat/views/chat_view.dart b/lib/modules/chat/views/chat_view.dart index abc28324d..46193f830 100644 --- a/lib/modules/chat/views/chat_view.dart +++ b/lib/modules/chat/views/chat_view.dart @@ -438,7 +438,7 @@ class ChatView extends GetView { filled: false, border: InputBorder.none, focusedBorder: InputBorder.none, - contentPadding: EdgeInsets.only(left: 10.w), + contentPadding: EdgeInsets.only(left: 6.w), ), onSubmitted: (value) { if (value.trim().isNotEmpty) {