import 'dart:io'; import 'package:clean/base/base_page.dart'; import 'package:clean/module/contact/backup/controller.dart'; import 'package:clean/resource/assets.gen.dart'; import 'package:clean/utils/expand.dart'; import 'package:clean/utils/file_utils.dart'; import 'package:flutter/Material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'; class ContactBackUpPage extends BasePage { const ContactBackUpPage({super.key}); @override bool immersive() { return true; } @override bool statusBarDarkFont() => false; @override Widget buildBody(BuildContext context) { controller.init(); return Stack( children: [ buildMain(context), IgnorePointer( child: Assets.images.bgHome.image( width: 360.w, ), ), ], ); } Widget buildMain(BuildContext context) { return SafeArea( child: Container( padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w), child: Obx(() { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ !controller.isEdit.value ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { Get.back(); }, child: Assets.images.iconCommonBack .image(width: 28.w, height: 28.w), ), GestureDetector( onTap: () { controller.isEdit.value = true; }, child: Container( width: 71.w, height: 30.h, decoration: BoxDecoration( color: "#1F2D3F".color, borderRadius: BorderRadius.all( Radius.circular(15.h), ), ), child: Center( child: Text( "Select", style: TextStyle( color: Colors.white, fontSize: 14.sp, ), ), ), ), ), ], ) : Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { controller.isEdit.value = false; }, child: Container( width: 71.w, height: 30.h, decoration: BoxDecoration( color: "#1F2D3F".color, borderRadius: BorderRadius.all( Radius.circular(15.h), ), ), child: Center( child: Text( "Cancel", style: TextStyle( color: Colors.white, fontSize: 14.sp, ), ), ), ), ), GestureDetector( onTap: () { controller.toggleSelectAll(); }, child: Text( controller.isAllSelected.value ? "Deselect all" : "Select All", style: TextStyle( color: Colors.white.withOpacity(0.65), fontSize: 14.sp, ), ), ), ], ), SizedBox( height: 12.h, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Backup", style: TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 24.sp, ), ), ], ), SizedBox( height: 26.h, ), Expanded( child: Obx(() { return ListView.builder( itemCount: controller.backupFilesMap.length, itemBuilder: (context, index) { final date = controller.backupFilesMap.keys.toList()[index]; final files = controller.backupFilesMap[date]!; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( date, style: TextStyle( color: Colors.white.withOpacity(0.7), fontSize: 14.sp, fontWeight: FontWeight.w500, ), ), SizedBox( height: 10.h, ), ...files.asMap().entries.map((entry) { final file = entry.value; final fileName = file.path .split('/') .last .split('_') .firstOrNull; final timestamp = file.path .split('/') .last .split('_') .last .split('.') .first; final dateTime = DateTime.fromMillisecondsSinceEpoch( int.parse(timestamp)); final time = _formatTime(dateTime); // final size = _fileSize(file); return FutureBuilder( future: _fileSize(file), builder: (context, snapshot) { final size = snapshot.data ?? 0; return GestureDetector( onTap: () { controller.restoreContacts(file); }, child: Container( margin: EdgeInsets.only(bottom: 10.h), height: 60.h, decoration: BoxDecoration( color: Colors.white.withOpacity(0.12), borderRadius: BorderRadius.all( Radius.circular(10.r)), ), child: Row( children: [ SizedBox( width: 10.w, ), Assets.images.iconContactsFile .image(width: 28.w, height: 28.w), SizedBox( width: 9.w, ), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( fileName ?? "", style: TextStyle( color: Colors.white, fontSize: 14.sp, fontWeight: FontWeight.w500, ), ), Text( "$size | $time", style: TextStyle( color: Colors.white .withOpacity(0.8), fontSize: 12.sp, ), ), ], ), Spacer(), // 删除按钮 Obx(() { return Visibility( visible: controller.isEdit.value, child: GestureDetector( onTap: () { controller .toggleSelectFile(file); // controller.toggleSelectContact( // contact); }, child: Container( child: controller.selectedFiles .contains(file.path) ? Center( child: Assets .images.iconSelected .image( width: 20.w, height: 20.h, ), ) : Center( child: Assets.images .iconUnselected .image( width: 20.w, height: 20.h, ), ), ), ), ); }), SizedBox(width: 20.w,), ], ), ), ); }, ); }), ], ); }, ); }), ), controller.isEdit.value ? GestureDetector( onTap: () { controller.deleteBtnClick(); }, child: Container( width: 328.w, height: 48.h, decoration: BoxDecoration( color: "#0279FB".color, borderRadius: BorderRadius.all( Radius.circular(10.r), ), ), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Delete", style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ], ), ), ), ) : GestureDetector( onTap: () { controller.backupContacts(); }, child: Container( width: 328.w, height: 48.h, decoration: BoxDecoration( color: "#0279FB".color, borderRadius: BorderRadius.all( Radius.circular(10.r), ), ), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Backup Now", style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ], ), ), ), ), ], ); }), ), ); } Future _fileSize(File file) async { return _formatFileSize(await file.length()); } // 格式化文件大小 String _formatFileSize(int bytes) { if (bytes < 1024) { return '$bytes B'; } else if (bytes < 1024 * 1024) { return '${(bytes / 1024).toStringAsFixed(1)} KB'; } else { return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB'; } } // 格式化时间为 "HH:mm" String _formatTime(DateTime dateTime) { return '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}'; } }