import 'dart:ffi'; import 'dart:math'; import 'package:clean/base/base_controller.dart'; import 'package:clean/model/asset_info.dart'; import 'package:clean/module/privacy/privacy_state.dart'; import 'package:clean/utils/expand.dart'; import 'package:clean/utils/file_utils.dart'; import 'package:clean/utils/image_util.dart'; import 'package:clean/utils/mmkv_util.dart'; import 'package:flutter/Material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:wechat_assets_picker/wechat_assets_picker.dart'; import 'package:wechat_camera_picker/wechat_camera_picker.dart'; import '../../dialog/photo_uploading_dialog.dart'; import '../../utils/toast_util.dart'; import '../image_picker/image_picker_assets.dart'; import 'package:intl/intl.dart'; import 'dart:typed_data'; import 'dart:io'; class PrivacyController extends BaseController { final String isExistPasswd = "PRIVACY_EXIST_PASSWD"; final String isPublic = "PRIVACY_PUBLIC"; final String privacyPasswd = "PRIVACY_PASSWD"; // 是否存在密码 RxBool isPrivacyExistPasswd = false.obs; // 是否公开 RxBool isPrivacyPublic = false.obs; RxBool isConfirm = false.obs; // 是否为编辑状态 RxBool isEdit = false.obs; // 是否在重置密码 bool isReset = false; // 设置密码标题 RxString passwordTitle = "Input password".obs; // 密码 late var passwordStr = "".obs; late var newPasswordStr = ""; // 是否为解锁状态 late var isUnlock = false.obs; // 使用共享状态 RxListimageList = PrivacyState.imageList; RxMap> assetsByMonth = PrivacyState.assetsByMonth; // 获取月份数量 int get monthCount => assetsByMonth.length; // 获取总图片数量 int get totalAssetCount => assetsByMonth.values.fold(0, (sum, list) => sum + list.length); // 存储选中的图片ID final RxSet selectedAssets = {}.obs; // 是否全选 RxBool isAllSelected = false.obs; // 选中图片的总容量(字节) final RxInt selectedTotalSize = 0.obs; @override void onInit() { // TODO: implement onInit super.onInit(); isPrivacyExistPasswd.value = KVUtil.getBool(isExistPasswd, false); isPrivacyPublic.value = KVUtil.getBool(isPublic, false); isUnlock.value = isPrivacyPublic.value; if (isPrivacyExistPasswd.value) { passwordTitle.value = "Input password"; } else { passwordTitle.value = "Create New Password"; } loadAssets(); } // 加载并分组图片 Future loadAssets() async { var newImageList = []; newImageList = await FileUtils.getAllAssets(FileType.privacy); PrivacyState.imageList.value = newImageList; PrivacyState.updateMonthlyAssets(); if (newImageList.isEmpty) { isEdit.value = false; return; } // 清空现有数据 assetsByMonth.clear(); // 按月份分组 for (var asset in newImageList) { final monthKey = ImageUtil.getMonthKey(asset.createDateTime); if (!assetsByMonth.containsKey(monthKey)) { assetsByMonth[monthKey] = []; } assetsByMonth[monthKey]!.add(asset); asset.dateTitle = ImageUtil.formatMonthKey(monthKey); } newImageList.sort((a, b) => b.createDateTime.compareTo(a.createDateTime)); PrivacyState.imageList.value = newImageList; PrivacyState.updateMonthlyAssets(); // 对每个月份内的图片按时间排序(新的在前) assetsByMonth.forEach((key, list) { list.sort((a, b) => b.createDateTime.compareTo(a.createDateTime)); }); // 打印分组结果 assetsByMonth.forEach((key, assets) { print('${ImageUtil.formatMonthKey(key)}: ${assets.length} photos'); }); } // 处理输入密码逻辑 void inputPassword(String num) { passwordStr.value = passwordStr.value + num; if (passwordStr.value.length == 4) { if (isReset) { // 二次输入密码的情况 if (isConfirm.value) { // 输入错误 if (passwordStr.value != newPasswordStr) { ToastUtil.show("Input Error"); Future.delayed(const Duration(milliseconds: 100), () { passwordStr.value = ""; }); } else { isUnlock.value = true; KVUtil.putString(privacyPasswd, passwordStr.value); KVUtil.putBool(isExistPasswd, true); KVUtil.putBool(isPublic, false); isPrivacyExistPasswd.value = KVUtil.getBool(isExistPasswd, false); isPrivacyPublic.value = KVUtil.getBool(isPublic, false); isReset = false; passwordStr.value = ""; } } else { // 第一次输入密码 isConfirm.value = true; newPasswordStr = passwordStr.value; passwordTitle.value = "Confirm Password"; Future.delayed(const Duration(milliseconds: 100), () { passwordStr.value = ""; }); } return; } } if (passwordStr.value.length == 4) { // 存在密码的情况 if (isPrivacyExistPasswd.value) { String? password = KVUtil.getString(privacyPasswd, ""); if (passwordStr.value == password) { isUnlock.value = true; passwordStr.value = ""; } else { ToastUtil.show("Input Error"); Future.delayed(const Duration(milliseconds: 100), () { passwordStr.value = ""; }); } } else { // 二次输入密码的情况 if (isConfirm.value) { // 输入错误 if (passwordStr.value != newPasswordStr) { ToastUtil.show("Input Error"); Future.delayed(const Duration(milliseconds: 100), () { passwordStr.value = ""; }); } else { isUnlock.value = true; KVUtil.putString(privacyPasswd, passwordStr.value); KVUtil.putBool(isExistPasswd, true); KVUtil.putBool(isPublic, false); isPrivacyExistPasswd.value = KVUtil.getBool(isExistPasswd, false); isPrivacyPublic.value = KVUtil.getBool(isPublic, false); isReset = false; passwordStr.value = ""; } } else { // 第一次输入密码 isConfirm.value = true; newPasswordStr = passwordStr.value; passwordTitle.value = "Confirm Password"; Future.delayed(const Duration(milliseconds: 100), () { passwordStr.value = ""; }); } return; } } } void dialogSetPassword() { // // 存在密码情况下 // if (isPrivacyExistPasswd.value) { // isConfirm.value = false; // isUnlock.value = false; // passwordTitle.value = "Input password"; // isReset = true; // } else { isConfirm.value = false; isUnlock.value = false; passwordTitle.value = "Create New Password"; isReset = true; // } } // 设置公开状态 void setPublic() { KVUtil.putString("", passwordStr.value); KVUtil.putBool(isExistPasswd, false); KVUtil.putBool(isPublic, true); isPrivacyExistPasswd.value = KVUtil.getBool(isExistPasswd, false); isPrivacyPublic.value = KVUtil.getBool(isPublic, false); } // 上传按钮点击 void uploadBtnClick() { showCupertinoModalPopup( context: Get.context!, builder: (context) { return CupertinoActionSheet( actions: [ //操作按钮集合 CupertinoActionSheetAction( onPressed: () { Navigator.pop(context); openGallery(); }, child: Text( 'Upload from Gallery', style: TextStyle( color: "#007AFF".color, fontWeight: FontWeight.w500, fontSize: 16.sp, ), ), ), CupertinoActionSheetAction( onPressed: () { Navigator.pop(context); openCamera(); }, child: Text( 'Take and Upload', style: TextStyle( color: "#007AFF".color, fontWeight: FontWeight.w500, fontSize: 16.sp, ), ), ), ], cancelButton: CupertinoActionSheetAction( //取消按钮 onPressed: () { Navigator.pop(context); }, child: Text( 'Cancel', style: TextStyle( color: "#007AFF".color, fontWeight: FontWeight.w500, fontSize: 16.sp, ), ), ), ); }, ); } // 保存并刷新图片列表 Future saveAndRefreshAssets(List assets) async { for (var asset in assets) { await FileUtils.saveAsset(FileType.privacy, asset); } showDialog( context: Get.context!, barrierDismissible: false, // 防止点击外部关闭 builder: (context) => UploadingDialog( duration: const Duration(seconds: 3), onComplete: () { loadAssets(); ToastUtil.show("Successful"); // 这里可以添加完成后的操作 }, ), ); // 重新加载图片列表 // loadAssets(); } // 选择/取消选择图片 void toggleSelectAsset(String assetId) { final asset = imageList.firstWhere((asset) => asset.id == assetId); if (selectedAssets.contains(assetId)) { selectedAssets.remove(assetId); if (asset.size != null) { selectedTotalSize.value -= asset.size!; } } else { selectedAssets.add(assetId); if (asset.size != null) { selectedTotalSize.value += asset.size!; } } // 更新全选状态 isAllSelected.value = selectedAssets.length == imageList.length; } // 全选/取消全选 void toggleSelectAll() { if (isAllSelected.value) { selectedAssets.clear(); selectedTotalSize.value = 0; } else { selectedAssets.addAll(imageList.map((asset) => asset.id)); selectedTotalSize.value = imageList.fold( 0, (sum, asset) => sum + (asset.size != null ? asset.size! : 0)); } isAllSelected.value = !isAllSelected.value; } // 退出编辑模式时清空选择 void exitEditMode() { isEdit.value = false; selectedAssets.clear(); isAllSelected.value = false; selectedTotalSize.value = 0; } // 删除文件 void deleteBtnClick() { // 获取要删除的资产 final assetsToDelete = imageList.where( (asset) => selectedAssets.contains(asset.id) ).toList(); for (var asset in assetsToDelete) { FileUtils.deleteAsset(FileType.privacy, asset.id.substring(0, 36)); } selectedTotalSize.value = 0; loadAssets(); } // 格式化文件大小显示 String formatFileSize(int bytes) { if (bytes <= 0) return "Delete"; final units = ['B', 'KB', 'MB', 'GB']; int digitGroups = (log(bytes) / log(1024)).floor(); if (bytes == 0) { return "Delete"; } else { return "Delete(${(bytes / pow(1024, digitGroups)).toStringAsFixed( 1)} ${units[digitGroups]})"; } } // 开启图库 Future openGallery() async { var status = await Permission.photos.status; if (status == PermissionStatus.granted) { List assets = []; for (var asset in imageList) { var newAsset = await asset.toAssetEntity(); if (newAsset != null) { assets.add(newAsset); } } List? pickList = await ImagePickAssets.pick(); if (pickList != null && pickList.isNotEmpty) { await saveAndRefreshAssets(pickList); } } else { ToastUtil.show("请先开启权限"); } } // 开启相机 Future openCamera() async { final entity = await CameraPicker.pickFromCamera( Get.context!, pickerConfig: const CameraPickerConfig(), ); if (entity != null) { await saveAndRefreshAssets([entity]); } } }