import 'dart:io'; import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import '/common/constants.dart'; import '/database/box_type.dart'; import '/models/init_get_it.dart'; import '/models/user_model.dart'; class AttachmentContainer extends StatefulWidget { const AttachmentContainer({ super.key, required this.isMyself, required this.filename, required this.onTapImage, }); final bool isMyself; final String filename; final Function(String) onTapImage; @override State createState() => _AttachmentContainerState(); } class _AttachmentContainerState extends State with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { late AnimationController _controller; late Animation _animation; @override bool get wantKeepAlive => true; @override void initState() { super.initState(); _controller = AnimationController(vsync: this); _animation = Tween(begin: 0.0, end: 1.0).animate(_controller); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { super.build(context); return Container( margin: const EdgeInsets.only( bottom: 15, ), constraints: const BoxConstraints( maxHeight: 150, ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10.0), ), child: ValueListenableBuilder( valueListenable: widget.isMyself ? Hive.box('attachment_send') .listenable(keys: [widget.filename]) : Hive.box('attachment_receive') .listenable(keys: [widget.filename]), builder: (context, apBox, _) { double progress = apBox.get(widget.filename)!.progress; String filePath = '${getIt.get().baseImageDir}/${widget.filename}'; bool isFileExists = File(filePath).existsSync(); _controller.animateTo( progress, duration: const Duration(milliseconds: 500), ); return Stack( children: [ GestureDetector( onTap: () { widget.onTapImage(widget.filename); }, child: progress == 1.0 || isFileExists ? Image.file(File(filePath)) : Image.asset('assets/images/loading.gif'), ), if (progress < 1.0) Positioned.fill( child: Stack( alignment: Alignment.center, children: [ Container( alignment: Alignment.center, constraints: const BoxConstraints.expand(), color: const Color.fromARGB(255, 32, 32, 32) .withOpacity(0.3), child: Text( '${(_animation.value * 100).toStringAsFixed(0)}%', style: const TextStyle( fontSize: 20, color: kUnAvailableColor, ), ), ), CircularProgressIndicator( value: _animation.value, color: kSecondaryColor, strokeWidth: 4, ), ], ), ), ], ); }, ), ); } }