Commit 3bd07415 authored by shenyong's avatar shenyong

Merge branch 'develop_0409' into Adv_NewClean

# Conflicts:
#	PhoneManager/Class/Database/TrashDatabase.swift
parents 1a9ff85e ba9a2776
......@@ -7,9 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
04197BE82DD1B9DB009FE068 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915D2D9D68AD00055CEB /* WidgetKit.framework */; };
04197BE92DD1B9DB009FE068 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915F2D9D68AD00055CEB /* SwiftUI.framework */; };
04197BF42DD1B9DC009FE068 /* LockSreenExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 04197BE72DD1B9DB009FE068 /* LockSreenExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
0496DEF32D9E3F58005B2834 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915D2D9D68AD00055CEB /* WidgetKit.framework */; };
0496DEF42D9E3F58005B2834 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04BD915F2D9D68AD00055CEB /* SwiftUI.framework */; };
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0496DEF22D9E3F57005B2834 /* widgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
......@@ -23,13 +20,6 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
04197BF22DD1B9DC009FE068 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = EB388E532D8A61A800629B0D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 04197BE62DD1B9DB009FE068;
remoteInfo = LockSreenExtension;
};
0496DEFD2D9E3F59005B2834 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = EB388E532D8A61A800629B0D /* Project object */;
......@@ -65,7 +55,6 @@
files = (
0496DEFF2D9E3F59005B2834 /* widgetExtension.appex in Embed Foundation Extensions */,
04CF31772DA7E790001C87CA /* ChargeShow.appex in Embed Foundation Extensions */,
04197BF42DD1B9DC009FE068 /* LockSreenExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
......@@ -73,8 +62,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
04197BE72DD1B9DB009FE068 /* LockSreenExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LockSreenExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
04197BF92DD1BA4C009FE068 /* LockSreenExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LockSreenExtension.entitlements; sourceTree = "<group>"; };
0496DEF22D9E3F57005B2834 /* widgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = widgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
0496DF042D9E3FA7005B2834 /* widgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = widgetExtension.entitlements; sourceTree = "<group>"; };
04BBB4E52DC0748F00D7E3AB /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
......@@ -92,13 +79,6 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
04197BF82DD1B9DC009FE068 /* Exceptions for "LockSreen" folder in "LockSreenExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 04197BE62DD1B9DB009FE068 /* LockSreenExtension */;
};
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
......@@ -130,14 +110,6 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
04197BEA2DD1B9DB009FE068 /* LockSreen */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
04197BF82DD1B9DC009FE068 /* Exceptions for "LockSreen" folder in "LockSreenExtension" target */,
);
path = LockSreen;
sourceTree = "<group>";
};
0496DEF52D9E3F58005B2834 /* widget */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
......@@ -166,15 +138,6 @@
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
04197BE42DD1B9DB009FE068 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
04197BE92DD1B9DB009FE068 /* SwiftUI.framework in Frameworks */,
04197BE82DD1B9DB009FE068 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0496DEEF2D9E3F57005B2834 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
......@@ -231,13 +194,11 @@
EB388E522D8A61A800629B0D = {
isa = PBXGroup;
children = (
04197BF92DD1BA4C009FE068 /* LockSreenExtension.entitlements */,
04CF317C2DA7E7BE001C87CA /* Intents.intentdefinition */,
0496DF042D9E3FA7005B2834 /* widgetExtension.entitlements */,
EB388E5D2D8A61A800629B0D /* PhoneManager */,
0496DEF52D9E3F58005B2834 /* widget */,
04CF31712DA7E78F001C87CA /* ChargeShow */,
04197BEA2DD1B9DB009FE068 /* LockSreen */,
EB388E5C2D8A61A800629B0D /* Products */,
CB2ACD1E9442B4500087E831 /* Pods */,
27ECDADD9059AB5043B8E1E9 /* Frameworks */,
......@@ -250,7 +211,6 @@
EB388E5B2D8A61A800629B0D /* PhoneManager.app */,
0496DEF22D9E3F57005B2834 /* widgetExtension.appex */,
04CF316F2DA7E78F001C87CA /* ChargeShow.appex */,
04197BE72DD1B9DB009FE068 /* LockSreenExtension.appex */,
);
name = Products;
sourceTree = "<group>";
......@@ -258,28 +218,6 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
04197BE62DD1B9DB009FE068 /* LockSreenExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 04197BF52DD1B9DC009FE068 /* Build configuration list for PBXNativeTarget "LockSreenExtension" */;
buildPhases = (
04197BE32DD1B9DB009FE068 /* Sources */,
04197BE42DD1B9DB009FE068 /* Frameworks */,
04197BE52DD1B9DB009FE068 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
04197BEA2DD1B9DB009FE068 /* LockSreen */,
);
name = LockSreenExtension;
packageProductDependencies = (
);
productName = LockSreenExtension;
productReference = 04197BE72DD1B9DB009FE068 /* LockSreenExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
0496DEF12D9E3F57005B2834 /* widgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0496DF022D9E3F59005B2834 /* Build configuration list for PBXNativeTarget "widgetExtension" */;
......@@ -338,7 +276,6 @@
dependencies = (
0496DEFE2D9E3F59005B2834 /* PBXTargetDependency */,
04CF31762DA7E78F001C87CA /* PBXTargetDependency */,
04197BF32DD1B9DC009FE068 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
EB388E5D2D8A61A800629B0D /* PhoneManager */,
......@@ -358,9 +295,6 @@
LastSwiftUpdateCheck = 1620;
LastUpgradeCheck = 1620;
TargetAttributes = {
04197BE62DD1B9DB009FE068 = {
CreatedOnToolsVersion = 16.2;
};
0496DEF12D9E3F57005B2834 = {
CreatedOnToolsVersion = 16.2;
};
......@@ -393,19 +327,11 @@
EB388E5A2D8A61A800629B0D /* PhoneManager */,
0496DEF12D9E3F57005B2834 /* widgetExtension */,
04CF316E2DA7E78F001C87CA /* ChargeShow */,
04197BE62DD1B9DB009FE068 /* LockSreenExtension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
04197BE52DD1B9DB009FE068 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
0496DEF02D9E3F57005B2834 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
......@@ -489,13 +415,6 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
04197BE32DD1B9DB009FE068 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
0496DEEE2D9E3F57005B2834 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
......@@ -522,11 +441,6 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
04197BF32DD1B9DC009FE068 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 04197BE62DD1B9DB009FE068 /* LockSreenExtension */;
targetProxy = 04197BF22DD1B9DC009FE068 /* PBXContainerItemProxy */;
};
0496DEFE2D9E3F59005B2834 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 0496DEF12D9E3F57005B2834 /* widgetExtension */;
......@@ -540,72 +454,6 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
04197BF62DD1B9DC009FE068 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = LockSreenExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 6K23946NQ5;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LockSreen/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LockSreen;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.lockSreenWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
04197BF72DD1B9DC009FE068 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = LockSreenExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 6K23946NQ5;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = LockSreen/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = LockSreen;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.app.phonemanager.lockSreenWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
0496DF002D9E3F59005B2834 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
......@@ -951,15 +799,6 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
04197BF52DD1B9DC009FE068 /* Build configuration list for PBXNativeTarget "LockSreenExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
04197BF62DD1B9DC009FE068 /* Debug */,
04197BF72DD1B9DC009FE068 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0496DF022D9E3F59005B2834 /* Build configuration list for PBXNativeTarget "widgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
......
......@@ -50,6 +50,40 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return true
}
func applicationWillTerminate(_ application: UIApplication) {
// 保存单利中所有垃圾桶的数据
saveDataToTrashDB(data: Singleton.shared.trashData)
// 保存单利中所有垃圾桶的数据
saveDataToKeepListhDB(data: Singleton.shared.keepList)
}
func saveDataToTrashDB(data : [TrashTypeEnum : [AssetModel]]){
for (key,value) in data {
for item in value {
let success = TrashDatabase.shared.insert(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: key.dbType)
if !success {
Print("保存单利数据到数据库失败")
}
}
}
Singleton.shared.trashData = [:]
}
func saveDataToKeepListhDB(data : [TrashTypeEnum : [AssetModel]]){
for (key,value) in data {
let uniqueId = UUID().uuidString
for item in value {
let success = GroupDatabase.shared.insert(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: key.dbType,groupId: uniqueId)
if !success {
Print("保存保留列表数据失败")
}
}
}
Singleton.shared.keepList = [:]
}
func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(name: Notification.Name("applicationDidBecomeActive"), object: nil)
......
{
"images" : [
{
"filename" : "Frame.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "Frame.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "Group_1171275102.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1171275102@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1171275102@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -254,7 +254,8 @@ class TrashDatabase {
sqlite3_exec(db, rollbackTransaction, nil, nil, nil)
return false
}
deinit {
sqlite3_close(db)
}
......
......@@ -26,7 +26,7 @@ class ChargeGuideController : BaseViewController,UIScrollViewDelegate,UINavigati
"Scroll the page and select Charger section",
"Select 'ls Connected' and 'Run lmmediately',then tap on Next",
"Tap on New Blank Automation to connect the app",
"Type 'Cleanup' & select Run Charging Animation and tap on Done!"
"Type 'PhoneManager' & select Run Charging Animation and tap on Done!"
]
let numberOfPages = 7
......
......@@ -17,6 +17,8 @@ typealias CompressSelectCellCallback = (AssetModel,Bool)->Void
class CompressSelectCell : UICollectionViewCell {
var indexPath : IndexPath?
var callBack : CompressSelectCellCallback = {model,choose in}
var currentMediaType : CompressType = .compressPhoto {
......@@ -225,23 +227,31 @@ class CompressSelectCell : UICollectionViewCell {
@objc func imageClick(){
if self.currentMediaType == .compressPhoto {
// 点击之后跳转详情页面
if let tempModel = self.model {
let vc = PMShowImgVideoController()
vc.state = .similarPhotos
vc.currentIdx = 0
vc.oldPageIndexPath = indexPath
let dataSource = ImageSeletedCollectionItem()
dataSource.isSeleted = true
dataSource.isSeleted = self.choose
dataSource.id = tempModel
// 获取image
dataSource.image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: tempModel.localIdentifier)
vc.homeDataSource = [dataSource]
vc.backOrgPageCallBack = {[weak self]index,data in
guard let self else {return}
if let data = data{
if let item = data.first{
self.choose = item.isSeleted ?? false
}
}
}
self.responderViewController()?.navigationController?.pushViewController(vc, animated: true)
}
}else{
......@@ -253,12 +263,21 @@ class CompressSelectCell : UICollectionViewCell {
let vc = PMShowImgVideoController()
vc.state = .similarVideos
vc.currentIdx = 0
vc.oldPageIndexPath = self.indexPath
let dataSource = ImageSeletedCollectionItem()
dataSource.isSeleted = true
dataSource.isSeleted = self.choose
dataSource.id = tempModel
dataSource.image = image
// 表示这个是视频
vc.homeDataSource = [dataSource]
vc.backOrgPageCallBack = {[weak self]index,data in
guard let self else {return}
if let data = data{
if let item = data.first{
self.choose = item.isSeleted ?? false
}
}
}
vc.getVideoURLFromLocalIdentifier(localIdentifier: tempModel.localIdentifier) { url, error in
if url != nil{
DispatchQueue.main.async {
......
......@@ -19,8 +19,16 @@ class CompressCompletedViewController : BaseViewController{
var currentMediaType : CompressType = .compressPhoto
lazy var bacView : UIView = {
let view = UIView()
view.layer.cornerRadius = 115
view.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
return view
}()
lazy var animationView : LottieAnimationView = {
let animationView = LottieAnimationView(name: "CompressCompletedLight")
let animationView = LottieAnimationView(name: "iOS压缩完成")
animationView.layer.cornerRadius = 12
animationView.backgroundColor = .clear
animationView.loopMode = .loop
......@@ -153,6 +161,7 @@ class CompressCompletedViewController : BaseViewController{
self.view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1)
self.titleView.isHidden = true
self.view.addSubview(self.bacView)
self.view.addSubview(self.animationView)
self.view.addSubview(self.tipLabel)
self.view.addSubview(self.detailTiplabel)
......@@ -168,7 +177,11 @@ class CompressCompletedViewController : BaseViewController{
self.infoView.addSubview(self.finalTipLabel)
self.view.addSubview(self.completedButton)
self.bacView.snp.makeConstraints { make in
make.top.equalTo(statusBarHeight + 60)
make.width.height.equalTo(230)
make.centerX.equalToSuperview()
}
self.animationView.snp.makeConstraints { make in
make.top.equalTo(statusBarHeight + 60)
make.width.height.equalTo(230)
......@@ -366,7 +379,7 @@ class CompressCompletedViewController : BaseViewController{
override func viewDidLoad() {
super.viewDidLoad()
setUI()
self.animationView.play(fromProgress: 0, toProgress: 1,loopMode: .playOnce)
self.animationView.play(fromProgress: 0, toProgress: 1,loopMode: .loop)
}
......
......@@ -174,6 +174,7 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CompressSelectCell", for: indexPath) as! CompressSelectCell
cell.currentMediaType = self.currentResourceType
cell.model = self.resourceData[indexPath.row]
cell.indexPath = indexPath
if self.selectedModel.count == 0 {
cell.choose = false
}
......
//
// VideoViewController.swift
// PhoneManager
//
// Created by edy on 2025/5/13.
//
import Foundation
import AVKit
import MediaPlayer
class VideoViewController: UIViewController {
var url : URL?
var isAutoPlay : Bool = true
// 系统播放器控制器
let playerViewController = AVPlayerViewController()
override func viewDidLoad() {
super.viewDidLoad()
setupPlayer()
}
func setupPlayer() {
// 1. 创建播放器
if let url = self.url {
let player = AVPlayer(url: url)
// 2. 配置播放器控制器
playerViewController.player = player
playerViewController.delegate = self
playerViewController.showsPlaybackControls = true
// 3. 添加到当前视图
addChild(playerViewController)
view.addSubview(playerViewController.view)
playerViewController.view.frame = view.bounds
playerViewController.didMove(toParent: self)
// 4. 自动播放
if self.isAutoPlay {
player.play()
}
}
}
}
// MARK: - AVPlayerViewControllerDelegate
extension VideoViewController: AVPlayerViewControllerDelegate {
// 处理全屏切换
func playerViewController(_ playerViewController: AVPlayerViewController,
willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
}
func playerViewController(_ playerViewController: AVPlayerViewController,
willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
}
}
......@@ -308,19 +308,15 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
cell.cellCallBack = {[weak self] ident,order in
guard let self else {return}
DispatchQueue.main.async {
// 点击之后跳转详情页面
let vc = PMShowImgVideoController()
vc.state = .similarPhotos
vc.currentIdx = 0
let dataSource = ImageSeletedCollectionItem()
dataSource.isSeleted = true
dataSource.id = ident
// 获取image
dataSource.image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: ident.localIdentifier)
vc.homeDataSource = [dataSource]
self.navigationController?.pushViewController(vc, animated: true)
if self.mediaType == .screenshots {
let vc = PhotoRemoveViewController(data: self.resourceData,currentIndex: indexPath.row,mediaType: .shot)
self.navigationController?.pushViewController(vc, animated: true)
}
if self.mediaType == .Other {
let vc = PhotoRemoveViewController(data: self.resourceData,currentIndex: indexPath.row,mediaType: .other)
self.navigationController?.pushViewController(vc, animated: true)
}
}
}
cell.clickCallBack = {[weak self] click,order in
......
......@@ -253,32 +253,8 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
// 获取视频的图片
PhotoAndVideoMananger.mananger.getVideoImageByIdent(ident: ident) { image in
// 点击之后跳转详情页面
let vc = PMShowImgVideoController()
vc.state = .similarVideos
vc.currentIdx = 0
let dataSource = ImageSeletedCollectionItem()
dataSource.isSeleted = true
dataSource.id = ident
dataSource.image = image
// 表示这个是视频
vc.homeDataSource = [dataSource]
vc.getVideoURLFromLocalIdentifier(localIdentifier: ident.localIdentifier) { url, error in
if url != nil{
DispatchQueue.main.async {
vc.url = url
self.navigationController?.pushViewController(vc, animated: true)
}
}else{
let alert = UIAlertController(title: nil, message: "ICloud video cannot be viewed", preferredStyle: .alert)
self.present(alert, animated: true, completion: nil)
// 2 秒后关闭弹窗
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
alert.dismiss(animated: true, completion: nil)
}
}
}
let vc = PhotoRemoveViewController(data: self.resourceData,currentIndex: indexPath.row,mediaType: .video)
self.navigationController?.pushViewController(vc, animated: true)
} errorHandler: {
DispatchQueue.main.async {
let alert = UIAlertController(title: nil, message: "Get Video image failure", preferredStyle: .alert)
......
//
// PhotoRemoveViewController.swift
// PhoneManager
//
// Created by edy on 2025/5/13.
//
import UIKit
import SnapKit
import Photos
class PhotoRemoveViewController: BaseViewController {
var mediaType : TrashTypeEnum?
private var bottomConstraint: Constraint?
let formatter = DateFormatter()
lazy var navView : PhotoRemoveNavView = {
let view = PhotoRemoveNavView()
return view
}()
// MARK: - 属性
private var photoViews: [PhotosRemoveBaseView] = []
private var currentIndex : Int
private var dataModel: [AssetModel]
// 配置参数
private let rotationStrength: CGFloat = 320
private let rotationMax: CGFloat = .pi/4
private let scaleStrength: CGFloat = -0.5
private let scaleMax: CGFloat = 0.7
private let actionMargin: CGFloat = 120
lazy var trashSubView : TrashSubView = {
let view = TrashSubView()
view.backgroundColor = .white
view.isHidden = true
return view
}()
// MARK: - 初始化
init(data: [AssetModel],currentIndex:Int,mediaType:TrashTypeEnum) {
self.mediaType = mediaType
let tempData = data
// 从currentIndex截断拼接在末尾,设置currentIndex为0
let result = Array(tempData[currentIndex...]) + Array(tempData[..<currentIndex])
self.currentIndex = 0
self.dataModel = result
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - 生命周期
override func viewDidLoad() {
super.viewDidLoad()
formatter.dateStyle = .medium
formatter.timeStyle = .none
if let type = self.mediaType {
self.navView.mediaType = type
}
self.view.addSubview(self.navView)
self.navView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.height.equalTo(statusBarHeight + 44)
}
setupViews()
self.view.addSubview(self.trashSubView)
self.trashSubView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
self.bottomConstraint = make.bottom.equalToSuperview().offset(78).constraint
make.height.equalTo(78)
}
self.trashSubView.clearTashDataCallBack = {[weak self] in
guard let self else {return}
// 清除垃圾桶数据
TrashDataManager.clearTrashData(mediaType: self.mediaType) {[weak self] in
guard let self else {return}
self.showCurrentPageUIWhenTashDataChanged()
}
}
self.trashSubView.presentTashDetailViewClickCallBack = {
// 进入垃圾桶详情页面
DispatchQueue.main.async {
let vc : TrashViewController = TrashViewController()
self.present(vc, animated: true)
}
}
showCurrentPageUIWhenTashDataChanged()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// 视图消失的时候存到数据库
saveDataToKeepListDB()
}
func changeDateToString() -> String{
let model = self.dataModel[self.currentIndex]
return formatter.string(from: model.createDate)
}
func chengeSizeToString()-> String {
let model = self.dataModel[self.currentIndex]
return formatFileSize(model.assetSize)
}
func showTrashView(){
DispatchQueue.main.async {
self.trashSubView.isHidden = false
UIView.animate(withDuration: 0.1) {
// 更新约束
self.bottomConstraint?.update(offset: -safeHeight)
}
}
}
func hideTrashView(){
DispatchQueue.main.async {
UIView.animate(withDuration: 0.1) {
// 更新约束
self.bottomConstraint?.update(offset: -78)
}completion: { finished in
self.trashSubView.isHidden = true
}
}
}
func showCurrentPageUIWhenTashDataChanged(){
if let type = self.mediaType{
// 从数据库拿数据
let dataDB = TrashDatabase.shared.queryByMediaType(type.dbType)
var assetModel : [AssetModel] = []
for item in dataDB {
assetModel.append(AssetModel.init(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: item.mediaType))
}
// 从单利拿数据
DispatchQueue.main.async {
if let type = self.mediaType{
if let dataSg = Singleton.shared.trashData[type]{
assetModel = assetModel + dataSg
// 如果单利中有当前数据,显示撤回按钮
if dataSg.count > 0{
self.navView.resetButton.isHidden = false
}else{
self.navView.resetButton.isHidden = true
}
}else {
self.navView.resetButton.isHidden = true
}
}
if assetModel.count > 0 {
// 显示垃圾桶
self.trashSubView.resourceCountlabel.text = String(assetModel.count)
self.showTrashView()
}else{
self.hideTrashView()
}
}
}
}
// MARK: - 视图设置
private func setupViews() {
// 只创建两个视图
for _ in 0..<2 {
let photoView = PhotosRemoveBaseView()
photoView.mediaType = self.mediaType
photoView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan)))
view.addSubview(photoView)
photoView.frame = CGRectMake(15, statusBarHeight + 44, self.view.width - 30, self.view.height - 78 - safeHeight - statusBarHeight - 44)
photoViews.append(photoView)
}
// 加载初始图片
updateViewContents()
bringCurrentViewToFront()
}
// 存垃圾桶数据到单利
func saveDataToSigtonTrash(){
// 拿到单利数据
if let type = self.mediaType{
if let dataSg = Singleton.shared.trashData[type]{
var tempArray = dataSg
tempArray.append(self.dataModel[currentIndex])
Singleton.shared.trashData[type] = tempArray
}else{
Singleton.shared.trashData[type] = [self.dataModel[currentIndex]]
}
}
self.showCurrentPageUIWhenTashDataChanged()
}
// 存保留数据到单利
func saveDataToSigtonKeepList(){
// 拿到单利数据
if let type = self.mediaType{
if let dataSg = Singleton.shared.keepList[type]{
var tempArray = dataSg
tempArray.append(self.dataModel[currentIndex])
Singleton.shared.keepList[type] = tempArray
}else{
Singleton.shared.keepList[type] = [self.dataModel[currentIndex]]
}
}
}
func saveDataToTrashDB(){
if let type = self.mediaType{
if let dataSg = Singleton.shared.trashData[type]{
for item in dataSg{
let success = TrashDatabase.shared.insert(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: type.dbType)
if success {
Print("保留单利数据到数据库垃圾桶成功")
}
}
Singleton.shared.trashData[type] = []
}
}
showCurrentPageUIWhenTashDataChanged()
}
/// 将保留列表单利数据存到数据库
func saveDataToKeepListDB(){
let uinqueId = UUID().uuidString
if let type = self.mediaType{
if let dataSg = Singleton.shared.keepList[type]{
for item in dataSg{
let success = GroupDatabase.shared.insert(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: type.dbType,groupId: uinqueId)
if success == false {
Print("保留单利数据到数据库保留列表失败")
}
}
Singleton.shared.keepList[type] = []
}
}
}
// MARK: - 手势处理
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
guard let activeView = gesture.view as? PhotosRemoveBaseView else { return }
// 记录初始位置
let initialCenter = activeView.center
let translation = gesture.translation(in: view)
let velocity = gesture.velocity(in: view)
switch gesture.state {
case .began:
activeView.initialCenter = initialCenter
case .changed:
// 使用增量位移更新位置
activeView.center = CGPoint(
x: activeView.initialCenter.x + translation.x,
y: activeView.initialCenter.y + translation.y
)
updateActionButton(for: activeView, translation: translation)
case .ended, .cancelled:
// 计算实际位移(基于最终位置)
let actualTranslation = CGPoint(
x: activeView.center.x - activeView.initialCenter.x,
y: activeView.center.y - activeView.initialCenter.y
)
// 使用实际位移判断
if abs(actualTranslation.x) > actionMargin || abs(velocity.x) > 500 {
removeCurrentView(translation: actualTranslation, velocity: velocity)
if actualTranslation.x > 0 {
// 保存垃圾桶数据到数据库
saveDataToTrashDB()
// 保留操作
saveDataToSigtonKeepList()
}
if actualTranslation.x < 0 {
// 删除操作,先存到单利
saveDataToSigtonTrash()
}
} else {
resetViewPosition(activeView)
}
gesture.setTranslation(.zero, in: view)
default: break
}
}
// MARK: - 视图更新逻辑
private func updateViewContents() {
for (index, view) in photoViews.enumerated() {
let imageIndex = (currentIndex + index) % dataModel.count
if self.mediaType == .video{
self.getVideoURLFromLocalIdentifier(localIdentifier: dataModel[imageIndex].localIdentifier) { url, error in
if url != nil {
view.url = url
view.reload(index: index)
}
}
}else {
view.configure(with: PhotoAndVideoMananger.mananger.getImageFromAssetID(id: dataModel[imageIndex].localIdentifier) ?? UIImage())
}
}
// 设置顶部title
self.navView.titleLbel.text = changeDateToString()
self.navView.sizeLbel.text = chengeSizeToString()
}
private func updateActionButton(for view: PhotosRemoveBaseView, translation: CGPoint) {
if translation.x > 0 {
view.showRightButton()
} else if translation.x < 0 {
view.showLeftButton()
} else {
view.hideButtons()
}
}
private func removeCurrentView(translation: CGPoint, velocity: CGPoint) {
guard let activeView = photoViews.first else { return }
let direction: CGFloat = translation.x > 0 ? 1 : -1
let screenWidth = UIScreen.main.bounds.width
UIView.animate(withDuration: 0.3) {
activeView.center = CGPoint(
x: direction * (screenWidth * 1.5),
y: activeView.center.y + velocity.y * 0.1
)
activeView.alpha = 0
} completion: { _ in
self.recycleView()
}
}
private func resetViewPosition(_ view: PhotosRemoveBaseView) {
UIView.animate(withDuration: 0.3) {
view.transform = .identity
view.frame = CGRectMake(15, statusBarHeight + 44, self.view.width - 30, self.view.height - 78 - safeHeight - statusBarHeight - 44)
view.hideButtons()
}
}
private func recycleView() {
// 移除旧视图
let removedView = photoViews.removeFirst()
removedView.removeFromSuperview()
// 当划到最后一张的时候就不再滑动了
if currentIndex == dataModel.count{
return
}
// 创建新视图并更新内容
let newView = PhotosRemoveBaseView()
newView.frame = CGRectMake(15, statusBarHeight + 44, self.view.width - 30, self.view.height - 78 - safeHeight - statusBarHeight - 44)
newView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan)))
newView.alpha = 0
view.addSubview(newView)
photoViews.append(newView)
// 更新索引并加载新内容
currentIndex = (currentIndex + 1) % dataModel.count
updateViewContents()
// 视图层级处理
bringCurrentViewToFront()
UIView.animate(withDuration: 0.3) {
newView.alpha = 1
}
}
private func bringCurrentViewToFront() {
guard photoViews.count >= 2 else { return }
view.bringSubviewToFront(photoViews[1])
view.bringSubviewToFront(photoViews[0])
}
private func getVideoURLFromLocalIdentifier(localIdentifier: String, completion: @escaping (URL?, Error?) -> Void) {
// 通过 localIdentifier 获取 PHAsset
let fetchOptions = PHFetchOptions()
let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: fetchOptions)
guard let asset = assets.firstObject, asset.mediaType == .video else {
DispatchQueue.main.async {
completion(nil, NSError(domain: "com.example.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "未找到对应视频资源"]))
}
return
}
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true // 允许从网络下载
options.deliveryMode = .automatic // 要求高质量格式
PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { (avAsset, audioMix, info) in
if let error = info?[PHImageErrorKey] as? Error {
DispatchQueue.main.async {
completion(nil, error)
}
return
}
if let urlAsset = avAsset as? AVURLAsset {
DispatchQueue.main.async {
completion(urlAsset.url, nil)
}
} else {
DispatchQueue.main.async {
completion(nil, NSError(domain: "CustomErrorDomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to get video URL"]))
}
}
}
}
}
......@@ -21,13 +21,13 @@ class PhotoSlideViewController: BaseViewController {
private lazy var topView: AnchorRotatableView = {
let view = AnchorRotatableView()
view.configure(anchorPoint: CGPoint(x: 0.5, y: 0.5))
return view
}()
private lazy var bottomView: AnchorRotatableView = {
let view = AnchorRotatableView()
view.configure(anchorPoint: CGPoint(x: 0.5, y: 0.5))
return view
}()
......@@ -119,7 +119,8 @@ class PhotoSlideViewController: BaseViewController {
updateCardTransform(translation: translation)
updateButtons(progress: progress,translation: translation)
case .ended, .cancelled:
endDragAnimation(velocity: velocity)
break
// endDragAnimation(velocity: velocity)
default: break
}
}
......
......@@ -40,10 +40,3 @@ class AnchorRotatableView: UIView {
}
extension AnchorRotatableView {
func configure(anchorPoint: CGPoint) {
layer.anchorPoint = anchorPoint
}
}
......@@ -42,7 +42,7 @@ class HomeInfoView :UIView {
lazy var headerView:HomeInfoTitleView = {
let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84))
sview.titleLabel.text = self.titleText
sview.filterButton.isHidden = self.type != .similar
sview.filterButton.isHidden = self.type != .similar && self.type != .SimilarVideos
tableView.addSubview(sview)
return sview
}()
......@@ -117,7 +117,13 @@ class HomeInfoView :UIView {
// 从源头获取相似数据
PhotoDataManager.manager.loadFromFileSystem(resultModel: {[weak self] model in
guard let self else {return}
let tempData = self.filterDataByDate(orgModels: model.titleModelArray[1].assets, startDate: filterModel.startDate, endDate: filterModel.endDate)
var dataS : [[AssetModel]] = []
if self.type == .SimilarVideos{
dataS = model.otherModelArray[3].assets
}else {
dataS = model.titleModelArray[1].assets
}
let tempData = self.filterDataByDate(orgModels: dataS , startDate: filterModel.startDate, endDate: filterModel.endDate)
// 重新更新下数据源
self.ids = self.sortData(source: tempData, type: filterModel.sortType)
var tempModels : [HomeInfoTableItem] = []
......
//
// PhotoRemoveNavView.swift
// PhoneManager
//
// Created by edy on 2025/5/13.
//
import UIKit
import SnapKit
class PhotoRemoveNavView: UIView {
public var backButton:UIButton!
public var sizeLbel : UILabel!
public var titleLbel : UILabel!
public var resetButton :UIButton!
private var topConstraint: Constraint?
public var mediaType : TrashTypeEnum = .shot {
didSet{
if mediaType == .video {
self.sizeLbel.isHidden = false
self.topConstraint?.update(offset: 22 + statusBarHeight)
}else{
self.sizeLbel.isHidden = true
self.topConstraint?.update(offset: 6 + statusBarHeight)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
backgroundColor = .white
backButton = UIButton()
backButton.setImage(UIImage(named: "nav_back"), for: .normal)
backButton.addTarget(self, action: #selector(backBtnClick), for: .touchUpInside)
self.addSubview(backButton)
backButton.snp.makeConstraints { make in
make.centerY.equalTo(navCenterY)
make.left.equalToSuperview().offset(marginLR)
make.width.height.equalTo(iconWH)
}
sizeLbel = UILabel()
sizeLbel.textColor = UIColor(red: 0.07, green: 0.07, blue: 0.07, alpha: 1)
sizeLbel.font = UIFont.systemFont(ofSize: 12, weight: .medium)
self.addSubview(sizeLbel)
sizeLbel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().offset(statusBarHeight)
make.height.equalTo(22)
}
titleLbel = UILabel()
titleLbel.textColor = UIColor(red: 0.07, green: 0.07, blue: 0.07, alpha: 1)
titleLbel.font = UIFont.systemFont(ofSize: 12, weight: .medium)
self.addSubview(titleLbel)
titleLbel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
self.topConstraint = make.top.equalToSuperview().offset(6 + statusBarHeight).constraint
make.height.equalTo(22)
}
resetButton = UIButton()
resetButton.setImage(UIImage(named: "Frame 3"), for: .normal)
resetButton.addTarget(self, action: #selector(resetButtonAction), for: .touchUpInside)
resetButton.isHidden = true
self.addSubview(resetButton)
resetButton.snp.makeConstraints { make in
make.centerY.equalTo(navCenterY)
make.right.equalToSuperview().offset(-marginLR)
make.width.height.equalTo(iconWH)
}
}
@objc private func backBtnClick() {
self.responderViewController()?.navigationController?.popViewController(animated: true)
}
@objc private func resetButtonAction() {
}
}
//
// AnchorRotatableView.swift
// AIClean
//
// Created by 赵前 on 2025/5/10.
//
import Foundation
import UIKit
class PhotosRemoveBaseView: UIView {
var currentIndex : Int?
var initialCenter: CGPoint = .zero
var url : URL?
var innerVideoController : VideoViewController?
func reload(index:Int) -> Void {
if let url = url {
self.innerVideoController = VideoViewController()
if let vc = self.innerVideoController {
vc.isAutoPlay = index == 0
vc.url = url
self.imageView.removeFromSuperview()
self.addSubview(vc.view)
vc.view.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview()
}
}
}
}
var mediaType : TrashTypeEnum?
lazy var maskTempleteView : UIView = {
let view = UIView(frame: CGRectMake(0, 0, self.width, self.height))
return view
}()
private let imageView = UIImageView()
private let leftButton = UIButton()
private let rightButton = UIButton()
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 20
self.clipsToBounds = true
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
// 配置图片视图
imageView.contentMode = .scaleAspectFit
addSubview(imageView)
leftButton.frame = CGRect(x: self.width / 2 - 45.5, y: self.height / 2 - 21, width: 95, height: 42)
leftButton.setTitle("Delete", for: .normal)
leftButton.backgroundColor = UIColor(red: 0.95, green: 0.21, blue: 0.21, alpha: 1)
leftButton.tintColor = .white
leftButton.layer.cornerRadius = 21
leftButton.clipsToBounds = true
leftButton.alpha = 0
addSubview(leftButton)
rightButton.frame = CGRect(x: self.width / 2 - 45.5, y: self.height / 2 - 21, width: 95, height: 42)
rightButton.setTitle("Retain", for: .normal)
rightButton.backgroundColor = UIColor(red: 0.18, green: 0.76, blue: 0.35, alpha: 1)
rightButton.tintColor = .white
rightButton.layer.cornerRadius = 21
rightButton.clipsToBounds = true
rightButton.alpha = 0
addSubview(rightButton)
}
func configure(with image: UIImage) {
imageView.image = image
imageView.frame = bounds
}
func showLeftButton() {
self.leftButton.center = self.center
UIView.animate(withDuration: 0.2) {
self.leftButton.alpha = 1
self.maskTempleteView.backgroundColor = UIColor(red: 0.95, green: 0.21, blue: 0.21, alpha: 0.4000)
self.addSubview(self.maskTempleteView)
self.rightButton.alpha = 0
}
}
func showRightButton() {
self.rightButton.center = self.center
UIView.animate(withDuration: 0.2) {
self.rightButton.alpha = 1
self.maskTempleteView.backgroundColor = UIColor(red: 0.26, green: 0.78, blue: 0.41, alpha: 0.4000)
self.addSubview(self.maskTempleteView)
self.leftButton.alpha = 0
}
}
func hideButtons() {
UIView.animate(withDuration: 0.2) {
self.leftButton.alpha = 0
self.rightButton.alpha = 0
self.maskTempleteView.removeFromSuperview()
self.leftButton.center = self.center
self.rightButton.center = self.center
}
}
}
//
// TrashSubView.swift
// PhoneManager
//
// Created by edy on 2025/5/13.
//
import UIKit
class TrashSubView: UIView {
var clearTashDataCallBack : ()->Void = {}
var presentTashDetailViewClickCallBack : ()->Void = {}
lazy var resourceCountlabel : UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 24, weight: .semibold)
label.textColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
return label
}()
lazy var tipLabel : UILabel = {
let label = UILabel()
label.text = "The photo in the trash can"
label.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
label.textColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
label.numberOfLines = 0
return label
}()
lazy var emptyButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "ic_delete_duplicates"), for: .normal)
button.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
button.setTitle("Empty the garbage", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
button.layer.cornerRadius = 19
button.clipsToBounds = true
button.addTarget(self, action: #selector(emptyButtonAction), for: .touchUpInside)
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
// 给当前视图添加手势
addTapGestureToSelf()
// 添加UI
addUIViews()
setUILocation()
}
private func addUIViews(){
self.addSubview(self.resourceCountlabel)
self.addSubview(self.tipLabel)
self.addSubview(self.emptyButton)
}
private func setUILocation(){
self.resourceCountlabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
make.centerY.equalToSuperview()
make.height.equalTo(22)
make.width.equalTo(30)
}
self.tipLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(17)
make.bottom.equalToSuperview().offset(-17)
make.left.equalTo(self.resourceCountlabel.snp.right).offset(11)
make.width.equalTo(100)
}
self.emptyButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-9)
make.height.equalTo(38)
make.centerY.equalToSuperview()
make.width.equalTo(145)
}
}
private func addTapGestureToSelf(){
self.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer()
tap.addTarget(self, action: #selector(tapHandle))
self.addGestureRecognizer(tap)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension TrashSubView {
@objc func emptyButtonAction(){
self.clearTashDataCallBack()
}
@objc func tapHandle(){
self.presentTashDetailViewClickCallBack()
}
}
......@@ -217,11 +217,26 @@ extension HomeInfoTableViewCell:UICollectionViewDelegate,UICollectionViewDataSou
// 显示保留按钮或者最佳匹配结果按钮
cell.allKeepButton.isHidden = indexPath.item != 0 || self.type == .duplicates
cell.bestResultButton.isHidden = indexPath.item != 0 || self.type == .duplicates
cell.model = model?.smodels?[indexPath.row]
cell.photsFileType = model?.type
cell.keepAllCallBack = {
//存到保留列表
saveAllDataToKeepList()
}
// 存全部数据到保留列表
func saveAllDataToKeepList(){
let uniqueId = UUID().uuidString
if let tempModel = self.model?.smodels {
for item in tempModel {
if let assetModel = item.id {
let success = GroupDatabase.shared.insert(localIdentifier: assetModel.localIdentifier, assetSize: assetModel.assetSize, createDate: assetModel.createDate, mediaType: self.type == .SimilarVideos ? 2 : 1 , groupId: uniqueId)
if success == false {
Print("存入当前数据到保留列表失败")
}
}
}
}
}
cell.callBack = {[weak self] _ in
guard let self else {return}
......@@ -253,9 +268,22 @@ extension HomeInfoTableViewCell:UICollectionViewDelegate,UICollectionViewDataSou
}else{
vc.state = .similarPhotos
}
vc.oldPageIndexPath = indexPath
vc.currentIdx = indexPath.row
vc.homeDataSource = self.model?.smodels
self.responderViewController()?.navigationController?.pushViewController(vc, animated: true)
vc.backOrgPageCallBack = {[weak self]index,data in
guard let self else {return}
self.model?.smodels = data
DispatchQueue.main.async{
if let view = self.collectionView{
UIView.transition(with: view, duration: 0.3, options: .transitionCrossDissolve, animations: {
view.reloadData()
}, completion: nil)
}
}
}
}
}
......
......@@ -19,6 +19,8 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
var callBack:callBack<Any> = {text in}
var keepAllCallBack : ()->Void = {}
lazy var allKeepButton : UIButton = {
let button = UIButton(type: .custom)
......@@ -37,8 +39,8 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
let button = UIButton(type: .custom)
button.layer.cornerRadius = 8
button.clipsToBounds = true
button.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
button.setTitle( "Best result", for: .normal)
button.backgroundColor = UIColor(red: 1, green: 0.65, blue: 0, alpha: 1)
button.setTitle( "Best", for: .normal)
button.setImage(UIImage(named: "Frame"), for: .normal)
button.setTitleColor(.white, for: .normal)
button.isHidden = true
......@@ -179,7 +181,7 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
self.bestResultButton.snp.makeConstraints { make in
make.left.bottom.equalToSuperview()
make.width.equalTo(81)
make.width.equalTo(52)
make.height.equalTo(16)
}
......@@ -222,6 +224,8 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
extension ImageSeletedCollectionCell {
@objc func allKeepButtonAction(){
Print("点击了全部保留按钮")
self.keepAllCallBack()
}
}
......@@ -28,6 +28,21 @@ class PMShowImgCell: UICollectionViewCell {
scaleImg.icon = icon
}
}
lazy var bestResultButton:UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "Frame"), for: .normal)
button.setTitle("Best", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .semibold)
button.layer.cornerRadius = 10.5
button.clipsToBounds = true
button.backgroundColor = UIColor(red: 1, green: 0.65, blue: 0, alpha: 1)
contentView.addSubview(button)
return button
}()
private lazy var iconView: UIImageView = {
let info = UIImageView()
......@@ -63,6 +78,14 @@ class PMShowImgCell: UICollectionViewCell {
}
private func setup() -> Void {
bestResultButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(34)
make.width.equalTo(63)
make.height.equalTo(21)
}
iconView.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
......@@ -74,5 +97,7 @@ class PMShowImgCell: UICollectionViewCell {
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview().offset(-10)
}
self.contentView.bringSubviewToFront(self.bestResultButton)
}
}
......@@ -17,6 +17,8 @@ class PMShowVideoCell: UICollectionViewCell {
var type : Int = 0
var innerVideoController : VideoViewController?
func reload() -> Void {
var url : URL?
if type == 0 {
......@@ -25,25 +27,39 @@ class PMShowVideoCell: UICollectionViewCell {
url = homeResouceUrl
}
if let url = url {
player.playVideo(from: url)
self.innerVideoController = VideoViewController()
if let vc = self.innerVideoController {
vc.url = url
self.contentView.addSubview(vc.view)
self.contentView.bringSubviewToFront(self.selectBtn)
vc.view.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview()
}
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
self.contentView.addSubview(self.selectBtn)
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview().offset(-10)
}
bestResultButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(34)
make.width.equalTo(63)
make.height.equalTo(21)
}
self.contentView.bringSubviewToFront(self.bestResultButton)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() -> Void {
player.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview()
}
}
var zPlayer : SecretVideoPlayer {
get {
return player
......@@ -57,4 +73,44 @@ class PMShowVideoCell: UICollectionViewCell {
contentView.addSubview(p)
return p
}()
var callblock:(()->Void) = {}
@objc private func selectTap() -> Void {
callblock()
}
var isCurrent:Bool = false {
didSet {
selectBtn.isSelected = isCurrent
}
}
lazy var selectBtn: UIButton = {
let select = UIButton(type: .custom)
select.setImage(UIImage(named: "home_info_norl"), for: .normal)
select.setImage(UIImage(named: "home_info_seleted"), for: .selected)
select.addTarget(self, action: #selector(selectTap), for: .touchUpInside)
contentView.addSubview(select)
return select
}()
lazy var bestResultButton:UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "Frame"), for: .normal)
button.setTitle("Best", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .semibold)
button.layer.cornerRadius = 10.5
button.clipsToBounds = true
button.backgroundColor = UIColor(red: 1, green: 0.65, blue: 0, alpha: 1)
contentView.addSubview(button)
return button
}()
}
......@@ -21,16 +21,32 @@ class PMShowImgVideoController: BaseViewController {
// 资源类型 0-图片 1-视频
var homeMediaType : Int = 0
// 记录原来进来的
var oldPageIndexPath : IndexPath?
var state:ShowState = .secret
var imageVideoPath:[String] = []
// 首页过来的数据
var homeDataSource : [ImageSeletedCollectionItem]?
var homeDataSource : [ImageSeletedCollectionItem]? {
didSet{
if let data = homeDataSource {
for (index,item) in data.enumerated() {
if item.isSeleted == true {
selectSet.add(index)
}
}
}
}
}
var currentIdx = 0
var selectSet = NSMutableSet()
var backOrgPageCallBack : (IndexPath?,[ImageSeletedCollectionItem]?)->Void = {index,data in}
var url : URL?
override func viewDidLoad() {
......@@ -53,6 +69,19 @@ class PMShowImgVideoController: BaseViewController {
self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// 离开返回上一个把选择的数据带过去
for item in self.selectSet {
if let index = item as? Int {
self.homeDataSource?[index].isSeleted = true
}
}
self.backOrgPageCallBack(self.oldPageIndexPath,self.homeDataSource)
}
private lazy var MaxCollection: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout()
flowlayout.sectionInset = UIEdgeInsets()
......@@ -131,8 +160,10 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == bottItems {
if selectSet.contains(indexPath.row) {
self.homeDataSource?[indexPath.row].isSeleted = false
selectSet.remove(indexPath.row)
}else{
self.homeDataSource?[indexPath.row].isSeleted = true
selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
......@@ -158,7 +189,7 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let showName = imageVideoPath[indexPath.row]
if !showName.hasSuffix(".png") {
guard let zCell:PMShowVideoCell = cell as? PMShowVideoCell else { return }
zCell.zPlayer.pause()
zCell.innerVideoController?.playerViewController.player?.pause()
}
}
}
......@@ -172,12 +203,16 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
showName.loadPhotoOrVideo { durs, icon in
cell.icon = icon
}
cell.bestResultButton.isHidden = indexPath.row != 0
cell.isCurrent = selectSet.contains(indexPath.row)
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.homeDataSource?[indexPath.row].isSeleted = false
self.selectSet.remove(indexPath.row)
}else{
self.homeDataSource?[indexPath.row].isSeleted = true
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
......@@ -186,8 +221,21 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowVideoCellID, for: indexPath) as! PMShowVideoCell
cell.isCurrent = selectSet.contains(indexPath.row)
cell.playURL = showName
cell.reload()
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.homeDataSource?[indexPath.row].isSeleted = false
self.selectSet.remove(indexPath.row)
}else{
self.homeDataSource?[indexPath.row].isSeleted = true
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
self.bottItems.reloadData()
}
return cell
}
}else{
......@@ -208,11 +256,14 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isCurrent = selectSet.contains(indexPath.row)
cell.bestResultButton.isHidden = indexPath.row != 0
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.homeDataSource?[indexPath.row].isSeleted = false
self.selectSet.remove(indexPath.row)
}else{
self.homeDataSource?[indexPath.row].isSeleted = true
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
......@@ -247,6 +298,20 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
}
// 表示这个是视频
cell.type = 1
cell.isCurrent = selectSet.contains(indexPath.row)
cell.bestResultButton.isHidden = indexPath.row != 0
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.homeDataSource?[indexPath.row].isSeleted = false
self.selectSet.remove(indexPath.row)
}else{
self.homeDataSource?[indexPath.row].isSeleted = true
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
self.bottItems.reloadData()
}
return cell
}else{
if indexPath.row < self.homeDataSource?.count ?? 0 {
......
......@@ -325,6 +325,16 @@ extension SecretViewController : UICollectionViewDelegate,UICollectionViewDataSo
let play = PMShowImgVideoController()
play.currentIdx = indexPath.row
play.imageVideoPath = dataSource
play.oldPageIndexPath = indexPath
play.backOrgPageCallBack = {[weak self]index,data in
guard let self else {return}
self.selectArray = play.selectSet
DispatchQueue.main.async{
UIView.transition(with: self.secretCollect, duration: 0.3, options: .transitionCrossDissolve, animations: {
self.secretCollect.reloadData()
}, completion: nil)
}
}
self.navigationController?.pushViewController(play, animated: true)
}
......
......@@ -22,6 +22,26 @@ class TrashViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
configUI()
getTrashDataAndRefreshPage()
}
/// 获取垃圾桶数据
private func getTrashDataAndRefreshPage(){
for item in self.source {
let data = TrashDataManager.getCurrentMediaTypeTrashData(mediaType: item)
for view in self.contentScrollView.subviews {
if view.isKind(of: TrashContenView.self){
let tempView = view as! TrashContenView
if tempView.trashType == item{
tempView.dataSource = data
DispatchQueue.main.async {
tempView.collectionView.reloadData()
}
}
}
}
}
}
......
//
// TrashDataManager.swift
// PhoneManager
//
// Created by edy on 2025/5/14.
//
import UIKit
class TrashDataManager {
/// 清除当前垃圾桶的数据
static func clearTrashData(mediaType: TrashTypeEnum?, comlete:@escaping ()->Void){
let trashData = self.getCurrentMediaTypeTrashData(mediaType: mediaType)
if trashData.count > 0 {
PhotoAndVideoMananger.deleteAssets(localIdentifiers: trashData.map({$0.localIdentifier})) {
// 清空单利和数据库的数据
clearCurrentMediaTypeTrashSigtonData()
clearCurrentMediaTypeTrashDBData()
// 删除完成之后重新
comlete()
}
}else{
comlete()
}
func clearCurrentMediaTypeTrashSigtonData(){
if let type = mediaType {
Singleton.shared.trashData[type] = []
Print("删除单利中当前垃圾桶数据成功")
}
}
func clearCurrentMediaTypeTrashDBData(){
if let type = mediaType {
let dataDB = TrashDatabase.shared.queryByMediaType(type.dbType)
let success = TrashDatabase.shared.batchDelete(localIdentifiers: dataDB.map({$0.localIdentifier}))
if success {
Print("删除数据库当前垃圾桶数据成功")
}else {
Print("删除数据库当前垃圾桶数据失败")
}
}
}
}
static func getCurrentMediaTypeTrashData(mediaType: TrashTypeEnum?) -> [AssetModel]{
var assetModel : [AssetModel] = []
if let type = mediaType{
// 从数据库拿数据
let dataDB = TrashDatabase.shared.queryByMediaType(type.dbType)
for item in dataDB {
assetModel.append(AssetModel.init(localIdentifier: item.localIdentifier, assetSize: item.assetSize, createDate: item.createDate, mediaType: item.mediaType))
}
// 从单利拿数据
if let type = mediaType{
if let dataSg = Singleton.shared.trashData[type]{
assetModel = assetModel + dataSg
}
}
}
return assetModel
}
}
......@@ -7,7 +7,7 @@
import Foundation
enum TrashTypeEnum{
enum TrashTypeEnum : CaseIterable{
case video,other,shot,chat
var dbType:Int{
......
{"v":"5.6.3","fr":25,"ip":0,"op":70,"w":600,"h":600,"nm":"图片压缩动画","ddd":0,"assets":[{"id":"image_0","w":72,"h":12,"u":"","p":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAAAMCAYAAADBJPs9AAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAABv0lEQVRIia1WrVIDQQz+0t6VMhj6Bn2EgmAG1BWHAiSC6aMhEMiCQnYGBDMIqEVRjYEXgGB6ZRvys8uw5u42X5Iv2SR7BGVd3nNDHUwANAwMATAAWorb93QPQia/pT4MnFzRvsbLe9fWnIA5E27OD+haCtcUrx54CMIFgMYJJiKYE2xJ4BoGBi5KRoRbgDE+26dFu7ECTR959EWYAdjOdOQF+cu+kOVUlecr8p3j1zqw9w7j8HSP5itDt888/CQ8ARgIhdwTjdoqCszClFZI6hsGDw0jbXx0GbtHO7SoAKDuYVb/JCdVks+ImMRKcqVzyPrWDhDKXpRgq9IGy1EzprsXPukQpg5xuXIwnq5X/jn4v3CJqlraYADEhHG11cfx2tT4n1Yq0feW1gpatUZzJbWj+dYrlTCpNiuMApI5pZ/T81LmtW9qTwbszQ+JkyvnQNNENvT6xuwASgeqpSNtegm1fJRcHJKbxiHCEQBU/brop0o1YjhO7Xk4qyKiJHp6VuVp3Ny9aqPO/pexbqpUFvW2xLYYOSOkvlcxli1NN5qjkgdVve4asISIN5u01ksDSLFSN/rOuYWsts+12e7xNz4FxCSyoDbjAAAAAElFTkSuQmCC","e":1},{"id":"image_1","w":44,"h":77,"u":"","p":"data:image/png;base64,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","e":1},{"id":"image_2","w":258,"h":24,"u":"","p":"data:image/png;base64,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","e":1},{"id":"image_3","w":258,"h":30,"u":"","p":"data:image/png;base64,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","e":1},{"id":"image_4","w":108,"h":108,"u":"","p":"data:image/png;base64,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","e":1},{"id":"image_5","w":450,"h":450,"u":"","p":"data:image/png;base64,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","e":1},{"id":"image_6","w":504,"h":504,"u":"","p":"data:image/png;base64,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","e":1},{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":2,"nm":"小帽子","parent":3,"refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[129,-12,0],"ix":2},"a":{"a":0,"k":[36,6,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"弹簧","parent":3,"refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.45,"y":1},"o":{"x":0.55,"y":0},"t":30,"s":[130.431,-48.53,0],"e":[130.431,-31.53,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.45,"y":0.45},"o":{"x":0.55,"y":0.55},"t":35,"s":[130.431,-31.53,0],"e":[130.431,-31.53,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.45,"y":1},"o":{"x":0.55,"y":0},"t":40,"s":[130.431,-31.53,0],"e":[130.431,-48.53,0],"to":[0,0,0],"ti":[0,0,0]},{"t":45}],"ix":2},"a":{"a":0,"k":[22,38.5,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.45,0.45,0.45],"y":[1,1,1]},"o":{"x":[0.55,0.55,0.55],"y":[0,0,0]},"t":30,"s":[97.471,97.471,100],"e":[97.471,42.926,100]},{"i":{"x":[0.45,0.45,0.45],"y":[1,1,1]},"o":{"x":[0.55,0.55,0.55],"y":[0,0,0]},"t":35,"s":[97.471,42.926,100],"e":[97.471,42.926,100]},{"i":{"x":[0.45,0.45,0.45],"y":[1,1,1]},"o":{"x":[0.55,0.55,0.55],"y":[0,0,0]},"t":40,"s":[97.471,42.926,100],"e":[97.471,97.471,100]},{"t":45}],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":2,"nm":"上压缩盖","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.32,"y":1},"o":{"x":0.68,"y":0},"t":20,"s":[300,246,0],"e":[300,390.09,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":0.3},"o":{"x":0.68,"y":0.68},"t":35,"s":[300,390.09,0],"e":[300,390.09,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.7,"y":0},"t":40,"s":[300,390.09,0],"e":[300,246.09,0],"to":[0,0,0],"ti":[0,0,0]},{"t":55}],"ix":2},"a":{"a":0,"k":[129,12,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":2,"nm":"下压缩盖","refId":"image_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,417,0],"ix":2},"a":{"a":0,"k":[129,15,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":2,"nm":"icon_yasuo_home","refId":"image_4","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[100]},{"t":15}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.35,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[601.689,330,0],"e":[300,330,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.35,"y":0.35},"o":{"x":0.167,"y":0.167},"t":15,"s":[300,330,0],"e":[300,330,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0},"t":20,"s":[300,330,0],"e":[300,409.925,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[54,54,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[100,100,100],"e":[20,20,100]},{"t":35}],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":2,"nm":"白色实心圆-小","refId":"image_5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[225,225,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":2,"nm":"白色边框圆-大","refId":"image_6","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20.625,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":34.375,"s":[100],"e":[0]},{"t":55}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[252,252,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100],"e":[118.254,118.254,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20.625,"s":[118.254,118.254,100],"e":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":34.375,"s":[100,100,100],"e":[118.254,118.254,100]},{"t":55}],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"预合成 1","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":55,"s":[100],"e":[0]},{"t":69}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[300,300,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":600,"h":600,"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
......@@ -19,6 +19,10 @@ class Singleton {
var maxDeleteCount : Int = 25
var trashData : [TrashTypeEnum : [AssetModel]] = [:]
var keepList : [TrashTypeEnum : [AssetModel]] = [:]
var photoPermission : PrivacyType?
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment