|
|
@@ -8,11 +8,13 @@ class ConversationList extends StatelessWidget {
|
|
|
super.key,
|
|
|
required this.items,
|
|
|
this.liveUtterance,
|
|
|
+ this.liveReply,
|
|
|
required this.isRecording,
|
|
|
});
|
|
|
|
|
|
final List<ConversationItem> items;
|
|
|
final String? liveUtterance;
|
|
|
+ final String? liveReply;
|
|
|
final bool isRecording;
|
|
|
|
|
|
@override
|
|
|
@@ -28,6 +30,8 @@ class ConversationList extends StatelessWidget {
|
|
|
),
|
|
|
if (liveUtterance != null && liveUtterance!.trim().isNotEmpty)
|
|
|
_LiveBubble(text: liveUtterance!, isRecording: isRecording),
|
|
|
+ if (liveReply != null && liveReply!.trim().isNotEmpty)
|
|
|
+ _LiveAiBubble(text: liveReply!),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
@@ -172,3 +176,46 @@ class _AiBubble extends StatelessWidget {
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+class _LiveAiBubble extends StatelessWidget {
|
|
|
+ const _LiveAiBubble({required this.text});
|
|
|
+
|
|
|
+ final String text;
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Align(
|
|
|
+ alignment: Alignment.centerLeft,
|
|
|
+ child: ConstrainedBox(
|
|
|
+ constraints: BoxConstraints(
|
|
|
+ maxWidth: MediaQuery.of(context).size.width * 0.78,
|
|
|
+ ),
|
|
|
+ child: Container(
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 9),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: AppColors.card,
|
|
|
+ borderRadius: const BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(4),
|
|
|
+ topRight: Radius.circular(16),
|
|
|
+ bottomRight: Radius.circular(16),
|
|
|
+ ),
|
|
|
+ border: Border.all(color: AppColors.line),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ Flexible(
|
|
|
+ child: Text(
|
|
|
+ text,
|
|
|
+ style: const TextStyle(fontSize: 13.5, color: AppColors.ink, height: 1.4),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 6),
|
|
|
+ const _PulsingDots(),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|