import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; /// Dialog yang menampilkan daftar link transaksi Firefly III dengan tombol /// copy dan open link per baris. Pengganti TransactionLinksScreen. class TransactionLinksDialog extends StatelessWidget { final List urls; final String title; const TransactionLinksDialog({ super.key, required this.urls, this.title = 'Link Transaksi', }); Future _copyLink(BuildContext context, String url) async { await Clipboard.setData(ClipboardData(text: url)); if (!context.mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Link disalin'), duration: Duration(seconds: 1), ), ); } Future _openLink(BuildContext context, String url) async { try { final uri = Uri.parse(url); final launched = await launchUrl(uri, mode: LaunchMode.externalApplication); if (!launched) { throw 'Tidak dapat membuka URL'; } } catch (e) { if (!context.mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Gagal membuka link: $e')), ); } } @override Widget build(BuildContext context) { return AlertDialog( title: Row( children: [ Icon(Icons.link, color: Theme.of(context).colorScheme.primary), const SizedBox(width: 8), Text(title), ], ), content: SizedBox( width: double.maxFinite, child: urls.isEmpty ? const Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.link_off, size: 48, color: Colors.grey), SizedBox(height: 8), Text('Tidak ada link transaksi', style: TextStyle(color: Colors.grey)), ], ) : ListView.builder( shrinkWrap: true, itemCount: urls.length, itemBuilder: (context, index) { final url = urls[index]; return ListTile( dense: true, contentPadding: EdgeInsets.zero, leading: CircleAvatar( radius: 12, backgroundColor: Theme.of(context).colorScheme.primary.withAlpha(30), child: Text( '${index + 1}', style: TextStyle( fontSize: 11, color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.bold, ), ), ), title: Text( url, style: const TextStyle(fontSize: 11), maxLines: 1, overflow: TextOverflow.ellipsis, ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: const Icon(Icons.copy, size: 18), padding: EdgeInsets.zero, constraints: const BoxConstraints(), tooltip: 'Salin link', onPressed: () => _copyLink(context, url), ), const SizedBox(width: 8), IconButton( icon: const Icon(Icons.open_in_new, size: 18), padding: EdgeInsets.zero, constraints: const BoxConstraints(), tooltip: 'Buka di browser', color: Theme.of(context).colorScheme.primary, onPressed: () => _openLink(context, url), ), ], ), ); }, ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Tutup'), ), ], ); } }