AppFlowy/frontend/appflowy_flutter/lib/ai/widgets/loading_indicator.dart
2025-01-15 19:57:47 +08:00

80 lines
2.5 KiB
Dart

import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
/// An animated generating indicator for an AI response
class AILoadingIndicator extends StatelessWidget {
const AILoadingIndicator({
super.key,
this.text = "",
this.duration = const Duration(seconds: 1),
});
final String text;
final Duration duration;
@override
Widget build(BuildContext context) {
final slice = Duration(milliseconds: duration.inMilliseconds ~/ 5);
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),
child: FlowyText(
text,
color: Theme.of(context).hintColor,
),
),
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),
],
),
),
);
}
Widget buildDot(Color color) {
return SizedBox.square(
dimension: 4,
child: DecoratedBox(
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(2),
),
),
);
}
}