feat: add copy button to code generation codeblock

This commit is contained in:
Udhay-Adithya
2025-09-26 00:34:33 +05:30
parent e3fc474c07
commit e5ef67ea97

View File

@@ -1,32 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:apidash_design_system/apidash_design_system.dart';
import '../../../../features/chat/models/chat_action.dart';
import '../dashbot_action.dart';
class DashbotGeneratedCodeBlock extends StatelessWidget
with DashbotActionMixin {
class DashbotGeneratedCodeBlock extends StatefulWidget with DashbotActionMixin {
@override
final ChatAction action;
const DashbotGeneratedCodeBlock({super.key, required this.action});
@override
State<DashbotGeneratedCodeBlock> createState() =>
_DashbotGeneratedCodeBlockState();
}
class _DashbotGeneratedCodeBlockState extends State<DashbotGeneratedCodeBlock> {
bool _isCopied = false;
Future<void> _copyCode(String code) async {
await Clipboard.setData(ClipboardData(text: code));
setState(() {
_isCopied = true;
});
// Reset the icon back to copy after 1.5 seconds
Future.delayed(const Duration(milliseconds: 1500), () {
if (mounted) {
setState(() {
_isCopied = false;
});
}
});
}
@override
Widget build(BuildContext context) {
final code = (action.value is String) ? action.value as String : '';
final code =
(widget.action.value is String) ? widget.action.value as String : '';
final isDark = Theme.of(context).brightness == Brightness.dark;
final codeTheme = isDark ? kDarkCodeTheme : kLightCodeTheme;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
color: codeTheme['root']?.backgroundColor ??
Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Theme.of(context).colorScheme.outlineVariant,
),
),
child: SelectableText(
code.isEmpty ? '// No code returned' : code,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontFamily: 'monospace',
child: Stack(
children: [
GestureDetector(
onTap: code.isNotEmpty ? () => _copyCode(code) : null,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
child: Text(
code.isEmpty ? '// No code returned' : code,
style: kCodeStyle.copyWith(
fontSize: Theme.of(context).textTheme.bodySmall?.fontSize,
color: codeTheme['root']?.color ??
Theme.of(context).colorScheme.onSurface,
),
),
),
),
if (code.isNotEmpty)
Positioned(
top: 8,
right: 8,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: ADIconButton(
key: ValueKey(_isCopied),
icon: _isCopied ? Icons.check : Icons.content_copy,
iconSize: 16,
tooltip: _isCopied ? 'Copied!' : 'Copy',
color: _isCopied
? Theme.of(context).colorScheme.primary
: (codeTheme['root']?.color ??
Theme.of(context).colorScheme.onSurface)
.withValues(alpha: 0.6),
visualDensity: VisualDensity.compact,
onPressed: () => _copyCode(code),
),
),
),
],
),
);
}