import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; class MarkdownRenderer extends StatelessWidget { final String content; final int previewLines; const MarkdownRenderer({ super.key, required this.content, this.previewLines = 3, }); @override Widget build(BuildContext context) { final String previewText = content.split('\n').take(previewLines).join('\n'); final bool hasMore = content.split('\n').length > previewLines; return InkWell( onTap: () => _showFullMarkdown(context), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ MarkdownBody( data: previewText, shrinkWrap: true, styleSheet: MarkdownStyleSheet( p: Theme.of(context).textTheme.bodyMedium, h1: Theme.of(context).textTheme.headlineSmall, h2: Theme.of(context).textTheme.titleLarge, ), ), if (hasMore) ...[ const SizedBox(height: 8), Text( 'Tap to read more...', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.primary, ), ), ], ], ), ), ); } void _showFullMarkdown(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (context) => FullMarkdownSheet(content: content), ); } } class FullMarkdownSheet extends StatelessWidget { final String content; const FullMarkdownSheet({ super.key, required this.content, }); @override Widget build(BuildContext context) { return DraggableScrollableSheet( initialChildSize: 0.9, minChildSize: 0.5, maxChildSize: 0.95, builder: (context, scrollController) { return Container( decoration: BoxDecoration( color: Theme.of(context).scaffoldBackgroundColor, borderRadius: const BorderRadius.vertical( top: Radius.circular(16), ), ), child: Column( children: [ // Handle bar Container( margin: const EdgeInsets.symmetric(vertical: 8), width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), // Actions bar Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( icon: const Icon(Icons.close), onPressed: () => Navigator.pop(context), ), Row( children: [ IconButton( icon: const Icon(Icons.copy), onPressed: () { // Copy to clipboard // You might want to add feedback when copied }, ), IconButton( icon: const Icon(Icons.share), onPressed: () { // Implement share functionality }, ), ], ), ], ), ), // Markdown content Expanded( child: Markdown( controller: scrollController, data: content, styleSheet: MarkdownStyleSheet( p: Theme.of(context).textTheme.bodyLarge, h1: Theme.of(context).textTheme.headlineMedium, h2: Theme.of(context).textTheme.headlineSmall, h3: Theme.of(context).textTheme.titleLarge, code: Theme.of(context).textTheme.bodyMedium?.copyWith( fontFamily: 'monospace', backgroundColor: Colors.grey[200], ), codeblockDecoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(8), ), ), selectable: true, padding: const EdgeInsets.all(16), ), ), ], ), ); }, ); } }