Files
iiEsaywebUIapp/lib/shared/widgets/markdown/streaming_markdown_widget.dart

68 lines
1.9 KiB
Dart
Raw Normal View History

2025-08-20 17:01:46 +05:30
import 'package:flutter/material.dart';
2025-10-02 13:52:28 +05:30
import 'package:gpt_markdown/gpt_markdown.dart';
2025-08-20 17:01:46 +05:30
import 'markdown_config.dart';
2025-08-20 17:01:46 +05:30
2025-10-02 13:52:28 +05:30
typedef MarkdownLinkTapCallback = void Function(String url, String title);
class StreamingMarkdownWidget extends StatelessWidget {
2025-08-20 17:01:46 +05:30
const StreamingMarkdownWidget({
super.key,
required this.content,
2025-08-20 17:01:46 +05:30
required this.isStreaming,
this.onTapLink,
2025-08-20 17:01:46 +05:30
});
final String content;
final bool isStreaming;
2025-10-02 13:52:28 +05:30
final MarkdownLinkTapCallback? onTapLink;
2025-08-20 17:01:46 +05:30
@override
Widget build(BuildContext context) {
final markdownTheme = ConduitMarkdownConfig.resolve(context);
2025-08-20 17:01:46 +05:30
if (content.trim().isEmpty) {
return isStreaming ? const SizedBox.shrink() : const SizedBox.shrink();
2025-08-20 17:01:46 +05:30
}
2025-10-02 13:52:28 +05:30
final textScaler = MediaQuery.maybeOf(context)?.textScaler;
return GptMarkdownTheme(
gptThemeData: markdownTheme.themeData,
child: GptMarkdown(
content,
style: markdownTheme.textStyle,
followLinkColor: markdownTheme.followLinkColor,
textDirection: Directionality.of(context),
textScaler: textScaler,
onLinkTap: onTapLink,
codeBuilder: markdownTheme.codeBuilder,
imageBuilder: markdownTheme.imageBuilder,
),
);
2025-08-20 17:01:46 +05:30
}
}
extension StreamingMarkdownExtension on String {
Widget toMarkdown({required BuildContext context, bool isStreaming = false}) {
return StreamingMarkdownWidget(content: this, isStreaming: isStreaming);
2025-08-20 17:01:46 +05:30
}
}
class MarkdownWithLoading extends StatelessWidget {
const MarkdownWithLoading({super.key, this.content, required this.isLoading});
2025-08-20 17:01:46 +05:30
final String? content;
final bool isLoading;
@override
Widget build(BuildContext context) {
final value = content ?? '';
if (isLoading && value.isEmpty) {
return const Center(child: CircularProgressIndicator());
2025-08-20 17:01:46 +05:30
}
return StreamingMarkdownWidget(content: value, isStreaming: isLoading);
2025-08-20 17:01:46 +05:30
}
2025-09-24 12:00:49 +05:30
}