2024-11-14 19:26:37 +03:00
|
|
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
2024-06-03 14:27:28 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2024-11-14 19:26:37 +03:00
|
|
|
import 'package:flutter_animate/flutter_animate.dart';
|
2024-06-03 14:27:28 +08:00
|
|
|
|
2024-11-14 19:26:37 +03:00
|
|
|
/// An animated generating indicator for an AI response
|
2025-01-15 19:57:47 +08:00
|
|
|
class AILoadingIndicator extends StatelessWidget {
|
|
|
|
const AILoadingIndicator({
|
2024-11-14 19:26:37 +03:00
|
|
|
super.key,
|
2024-12-03 22:20:14 +08:00
|
|
|
this.text = "",
|
2024-11-14 19:26:37 +03:00
|
|
|
this.duration = const Duration(seconds: 1),
|
|
|
|
});
|
2024-06-03 14:27:28 +08:00
|
|
|
|
2024-12-03 22:20:14 +08:00
|
|
|
final String text;
|
2024-11-14 19:26:37 +03:00
|
|
|
final Duration duration;
|
2024-06-03 14:27:28 +08:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-11-14 19:26:37 +03:00
|
|
|
final slice = Duration(milliseconds: duration.inMilliseconds ~/ 5);
|
2024-11-25 10:43:08 +08:00
|
|
|
return Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 8.0),
|
|
|
|
child: SizedBox(
|
|
|
|
height: 20,
|
|
|
|
child: SeparatedRow(
|
|
|
|
separatorBuilder: () => const HSpace(4),
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsetsDirectional.only(end: 4.0),
|
2024-12-03 22:20:14 +08:00
|
|
|
child: FlowyText(
|
|
|
|
text,
|
|
|
|
color: Theme.of(context).hintColor,
|
2024-11-25 10:43:08 +08:00
|
|
|
),
|
2024-11-14 19:26:37 +03:00
|
|
|
),
|
2024-11-25 10:43:08 +08:00
|
|
|
buildDot(const Color(0xFF9327FF))
|
|
|
|
.animate(onPlay: (controller) => controller.repeat())
|
|
|
|
.slideY(duration: slice, begin: 0, end: -1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: -1, end: 1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: 1, end: 0)
|
|
|
|
.then()
|
|
|
|
.slideY(duration: slice * 2, begin: 0, end: 0),
|
|
|
|
buildDot(const Color(0xFFFB006D))
|
|
|
|
.animate(onPlay: (controller) => controller.repeat())
|
|
|
|
.slideY(duration: slice, begin: 0, end: 0)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: 0, end: -1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: -1, end: 1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: 1, end: 0)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: 0, end: 0),
|
|
|
|
buildDot(const Color(0xFFFFCE00))
|
|
|
|
.animate(onPlay: (controller) => controller.repeat())
|
|
|
|
.slideY(duration: slice * 2, begin: 0, end: 0)
|
|
|
|
.then()
|
|
|
|
.slideY(duration: slice, begin: 0, end: -1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: -1, end: 1)
|
|
|
|
.then()
|
|
|
|
.slideY(begin: 1, end: 0),
|
|
|
|
],
|
|
|
|
),
|
2024-06-03 14:27:28 +08:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2024-11-14 19:26:37 +03:00
|
|
|
|
|
|
|
Widget buildDot(Color color) {
|
|
|
|
return SizedBox.square(
|
|
|
|
dimension: 4,
|
|
|
|
child: DecoratedBox(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: color,
|
|
|
|
borderRadius: BorderRadius.circular(2),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2024-06-03 14:27:28 +08:00
|
|
|
}
|