mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 10:49:49 +08:00
feat: add copy button to code generation codeblock
This commit is contained in:
@@ -1,32 +1,95 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 '../../../../features/chat/models/chat_action.dart';
|
||||||
import '../dashbot_action.dart';
|
import '../dashbot_action.dart';
|
||||||
|
|
||||||
class DashbotGeneratedCodeBlock extends StatelessWidget
|
class DashbotGeneratedCodeBlock extends StatefulWidget with DashbotActionMixin {
|
||||||
with DashbotActionMixin {
|
|
||||||
@override
|
@override
|
||||||
final ChatAction action;
|
final ChatAction action;
|
||||||
const DashbotGeneratedCodeBlock({super.key, required this.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
|
@override
|
||||||
Widget build(BuildContext context) {
|
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(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: codeTheme['root']?.backgroundColor ??
|
||||||
|
Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Theme.of(context).colorScheme.outlineVariant,
|
color: Theme.of(context).colorScheme.outlineVariant,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SelectableText(
|
child: Stack(
|
||||||
code.isEmpty ? '// No code returned' : code,
|
children: [
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
GestureDetector(
|
||||||
fontFamily: 'monospace',
|
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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user