|
|
@@ -1,8 +1,13 @@
|
|
|
+import 'dart:ffi';
|
|
|
+import 'dart:math';
|
|
|
+
|
|
|
import 'package:clean/base/base_controller.dart';
|
|
|
import 'package:clean/model/asset_info.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';
|
|
|
@@ -19,11 +24,36 @@ 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;
|
|
|
|
|
|
- late List<AssetEntity>? imageList;
|
|
|
+ RxList<AssetInfo> imageList = <AssetInfo>[].obs;
|
|
|
|
|
|
// 存储所有图片,按月份分组
|
|
|
final assetsByMonth = <String, List<AssetInfo>>{}.obs;
|
|
|
@@ -35,18 +65,41 @@ class PrivacyController extends BaseController {
|
|
|
int get totalAssetCount =>
|
|
|
assetsByMonth.values.fold(0, (sum, list) => sum + list.length);
|
|
|
|
|
|
+ // 存储选中的图片ID
|
|
|
+ final RxSet<String> selectedAssets = <String>{}.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<void> loadAssets() async {
|
|
|
- final imageList = await FileUtils.getAllAssets();
|
|
|
- if (imageList.isEmpty) return;
|
|
|
+ imageList.value = await FileUtils.getAllAssets();
|
|
|
+ if (imageList.isEmpty) {
|
|
|
+ isEdit.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
// 清空现有数据
|
|
|
assetsByMonth.clear();
|
|
|
@@ -76,18 +129,111 @@ class PrivacyController extends BaseController {
|
|
|
passwordStr.value = passwordStr.value + num;
|
|
|
|
|
|
if (passwordStr.value.length == 4) {
|
|
|
- if (passwordStr.value != "1234") {
|
|
|
- ToastUtil.show("Input Error");
|
|
|
- Future.delayed(const Duration(milliseconds: 100), () {
|
|
|
+ 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 {
|
|
|
- isUnlock.value = true;
|
|
|
+ // 二次输入密码的情况
|
|
|
+ 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 {
|
|
|
+ isUnlock.value = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// 设置公开状态
|
|
|
+ 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!,
|
|
|
@@ -143,7 +289,7 @@ class PrivacyController extends BaseController {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- // 保存并刷新图片列表
|
|
|
+// 保存并刷新图片列表
|
|
|
Future<void> saveAndRefreshAssets(List<AssetEntity> assets) async {
|
|
|
for (var asset in assets) {
|
|
|
await FileUtils.saveAsset(asset);
|
|
|
@@ -152,10 +298,90 @@ class PrivacyController extends BaseController {
|
|
|
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(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<void> openGallery() async {
|
|
|
var status = await Permission.photos.status;
|
|
|
if (status == PermissionStatus.granted) {
|
|
|
+ List<AssetEntity> assets = <AssetEntity>[];
|
|
|
+ for (var asset in imageList) {
|
|
|
+ var newAsset = await asset.toAssetEntity();
|
|
|
+ if (newAsset != null) {
|
|
|
+ assets.add(newAsset);
|
|
|
+ }
|
|
|
+ }
|
|
|
List<AssetEntity>? pickList = await ImagePickAssets.pick();
|
|
|
if (pickList != null && pickList.isNotEmpty) {
|
|
|
await saveAndRefreshAssets(pickList);
|
|
|
@@ -165,7 +391,7 @@ class PrivacyController extends BaseController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 开启相机
|
|
|
+// 开启相机
|
|
|
Future<void> openCamera() async {
|
|
|
final entity = await CameraPicker.pickFromCamera(
|
|
|
Get.context!,
|