Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
P
PhoneManager
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Yang
PhoneManager
Commits
656d7fa9
Commit
656d7fa9
authored
May 16, 2025
by
shenyong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
app内资源删除
parent
d9f0c377
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
253 additions
and
585 deletions
+253
-585
ActorManager.swift
PhoneManager/Class/Manager/PMPhotoManager/ActorManager.swift
+14
-130
PhotoDuplicateManager.swift
.../Class/Manager/PMPhotoManager/PhotoDuplicateManager.swift
+14
-232
PhotoManager.swift
PhoneManager/Class/Manager/PMPhotoManager/PhotoManager.swift
+37
-17
PhotoModel.swift
PhoneManager/Class/Manager/PMPhotoManager/PhotoModel.swift
+72
-5
PhotoSimilarManager.swift
...er/Class/Manager/PMPhotoManager/PhotoSimilarManager.swift
+10
-0
ScreenShotSimilarManager.swift
...ass/Manager/PMPhotoManager/ScreenShotSimilarManager.swift
+11
-0
VideoSimilarManager.swift
...er/Class/Manager/PMPhotoManager/VideoSimilarManager.swift
+11
-1
CompressCompletedViewController.swift
...Compress/Controller/CompressCompletedViewController.swift
+2
-1
HomeInfoViewController.swift
...r/Class/Page/Home/Controller/HomeInfoViewController.swift
+9
-21
HomePhotosDetailViewController.swift
...Page/Home/Controller/HomePhotosDetailViewController.swift
+8
-4
HomeVideoDetailController.swift
...lass/Page/Home/Controller/HomeVideoDetailController.swift
+7
-4
HomeViewController.swift
...nager/Class/Page/Home/Controller/HomeViewController.swift
+0
-2
HomeUIModel.swift
PhoneManager/Class/Page/Home/Model/HomeUIModel.swift
+4
-1
HomeCollectionViewHeader.swift
...nager/Class/Page/Home/View/HomeCollectionViewHeader.swift
+1
-0
HomeView.swift
PhoneManager/Class/Page/Home/View/HomeView.swift
+0
-16
VideocompressionHeadView.swift
...nager/Class/Page/Home/View/VideocompressionHeadView.swift
+18
-0
VideocompressionHeadView.xib
...Manager/Class/Page/Home/View/VideocompressionHeadView.xib
+3
-0
HomeViewModel.swift
PhoneManager/Class/Page/Home/ViewModel/HomeViewModel.swift
+17
-142
MaintainViewListController.swift
...ass/Page/Keep/Controller/MaintainViewListController.swift
+14
-8
PhotoAndVideoMananger.swift
...l/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
+1
-1
No files found.
PhoneManager/Class/Manager/PMPhotoManager/ActorManager.swift
View file @
656d7fa9
...
@@ -69,137 +69,16 @@ actor PhotoSimilarStateManager {
...
@@ -69,137 +69,16 @@ actor PhotoSimilarStateManager {
self
.
timeGroups
=
timeGroups
self
.
timeGroups
=
timeGroups
self
.
similarGroups
=
similarGroups
self
.
similarGroups
=
similarGroups
}
}
}
// 截图状态管理 actor
actor
ScreenshotSimilarStateManager
{
private
var
timeGroups
:
[
TimeGroupModel
]
=
[]
private
var
similarGroups
:
[
SimilarGroupModel
]
=
[]
private
var
pendingSimilarGroups
:
[
SimilarGroupModel
]
=
[]
private
var
processedGroupCount
:
Int
=
0
private
var
assetsImageCache
:
[
String
:
UIImage
]
=
[:]
private
var
hashCache
:
[
String
:
String
]
=
[:]
func
appendTimeGroup
(
_
group
:
TimeGroupModel
)
{
timeGroups
.
append
(
group
)
}
func
appendSimilarGroup
(
_
group
:
SimilarGroupModel
)
{
pendingSimilarGroups
.
append
(
group
)
processedGroupCount
+=
1
}
func
getAllTimeGroups
()
->
[
TimeGroupModel
]
{
return
timeGroups
}
func
getpendingSimilarGroups
()
->
[
SimilarGroupModel
]
{
return
pendingSimilarGroups
}
func
getAllSimilarGroups
()
->
[
SimilarGroupModel
]
{
return
similarGroups
}
func
getCachedImage
(
for
identifier
:
String
)
->
UIImage
?
{
return
assetsImageCache
[
identifier
]
}
func
setCachedImage
(
_
image
:
UIImage
,
for
identifier
:
String
)
{
assetsImageCache
[
identifier
]
=
image
}
func
shouldSavePendingGroups
()
->
Bool
{
return
processedGroupCount
>=
10
}
func
getCachedHash
(
for
identifier
:
String
)
async
->
String
?
{
return
hashCache
[
identifier
]
}
func
setCachedHash
(
_
hash
:
String
,
for
identifier
:
String
)
async
{
hashCache
[
identifier
]
=
hash
}
func
savePendingGroups
()
{
similarGroups
.
append
(
contentsOf
:
pendingSimilarGroups
)
pendingSimilarGroups
.
removeAll
()
processedGroupCount
=
0
}
func
loadStoredData
(
timeGroups
:
[
TimeGroupModel
],
similarGroups
:
[
SimilarGroupModel
])
{
self
.
timeGroups
=
timeGroups
self
.
similarGroups
=
similarGroups
}
}
// 视频状态管理 actor
actor
VideoSimilarStateManager
{
private
var
timeGroups
:
[
TimeGroupModel
]
=
[]
private
var
similarGroups
:
[
SimilarGroupModel
]
=
[]
private
var
pendingSimilarGroups
:
[
SimilarGroupModel
]
=
[]
private
var
processedGroupCount
:
Int
=
0
private
var
assetsImageCache
:
[
String
:
UIImage
]
=
[:]
private
var
hashCache
:
[
String
:
String
]
=
[:]
func
appendTimeGroup
(
_
group
:
TimeGroupModel
)
{
timeGroups
.
append
(
group
)
}
func
appendSimilarGroup
(
_
group
:
SimilarGroupModel
)
{
func
deleteData
(
for
idsToRemove
:[
String
]){
pendingSimilarGroups
.
append
(
group
)
let
updateGroups
=
self
.
similarGroups
.
removingGroupsWithEmptyAssetsWithDetails
(
afterRemovingIDs
:
idsToRemove
)
processedGroupCount
+=
1
self
.
similarGroups
=
updateGroups
.
updatedGroups
}
func
getAllTimeGroups
()
->
[
TimeGroupModel
]
{
return
timeGroups
}
func
getpendingSimilarGroups
()
->
[
SimilarGroupModel
]
{
return
pendingSimilarGroups
}
func
getAllSimilarGroups
()
->
[
SimilarGroupModel
]
{
return
similarGroups
}
func
getCachedImage
(
for
identifier
:
String
)
->
UIImage
?
{
return
assetsImageCache
[
identifier
]
}
func
setCachedImage
(
_
image
:
UIImage
,
for
identifier
:
String
)
{
assetsImageCache
[
identifier
]
=
image
}
func
shouldSavePendingGroups
()
->
Bool
{
return
processedGroupCount
>=
10
}
func
getCachedHash
(
for
identifier
:
String
)
async
->
String
?
{
return
hashCache
[
identifier
]
}
func
setCachedHash
(
_
hash
:
String
,
for
identifier
:
String
)
async
{
hashCache
[
identifier
]
=
hash
}
func
savePendingGroups
()
{
similarGroups
.
append
(
contentsOf
:
pendingSimilarGroups
)
pendingSimilarGroups
.
removeAll
()
processedGroupCount
=
0
}
func
loadStoredData
(
timeGroups
:
[
TimeGroupModel
],
similarGroups
:
[
SimilarGroupModel
])
{
self
.
timeGroups
=
timeGroups
self
.
similarGroups
=
similarGroups
}
}
}
}
actor
PhotoDuplicateStateManager
{
actor
PhotoDuplicateStateManager
{
private
var
duplicateGroups
:
[
Duplicate
GroupModel
]
=
[]
private
var
duplicateGroups
:
[
Similar
GroupModel
]
=
[]
private
var
pendingDuplicateGroups
:
[
Duplicate
GroupModel
]
=
[]
private
var
pendingDuplicateGroups
:
[
Similar
GroupModel
]
=
[]
// 缓存
// 缓存
private
var
imageCache
:
[
String
:
UIImage
]
=
[:]
private
var
imageCache
:
[
String
:
UIImage
]
=
[:]
...
@@ -207,15 +86,15 @@ actor PhotoDuplicateStateManager {
...
@@ -207,15 +86,15 @@ actor PhotoDuplicateStateManager {
// MARK: - 公共方法
// MARK: - 公共方法
func
loadStoredData
(
duplicateGroups
:
[
Duplicate
GroupModel
])
{
func
loadStoredData
(
duplicateGroups
:
[
Similar
GroupModel
])
{
self
.
duplicateGroups
=
duplicateGroups
self
.
duplicateGroups
=
duplicateGroups
}
}
func
getAllDuplicateGroups
()
->
[
Duplicate
GroupModel
]
{
func
getAllDuplicateGroups
()
->
[
Similar
GroupModel
]
{
return
duplicateGroups
return
duplicateGroups
}
}
func
appendDuplicateGroup
(
_
group
:
Duplicate
GroupModel
)
{
func
appendDuplicateGroup
(
_
group
:
Similar
GroupModel
)
{
pendingDuplicateGroups
.
append
(
group
)
pendingDuplicateGroups
.
append
(
group
)
}
}
...
@@ -228,7 +107,7 @@ actor PhotoDuplicateStateManager {
...
@@ -228,7 +107,7 @@ actor PhotoDuplicateStateManager {
pendingDuplicateGroups
.
removeAll
()
pendingDuplicateGroups
.
removeAll
()
}
}
func
getPendingDuplicateGroups
()
->
[
Duplicate
GroupModel
]
{
func
getPendingDuplicateGroups
()
->
[
Similar
GroupModel
]
{
return
pendingDuplicateGroups
return
pendingDuplicateGroups
}
}
...
@@ -253,5 +132,10 @@ actor PhotoDuplicateStateManager {
...
@@ -253,5 +132,10 @@ actor PhotoDuplicateStateManager {
func
setCachedHash
(
_
hash
:
String
,
for
identifier
:
String
)
{
func
setCachedHash
(
_
hash
:
String
,
for
identifier
:
String
)
{
hashCache
[
identifier
]
=
hash
hashCache
[
identifier
]
=
hash
}
}
func
deleteData
(
for
idsToRemove
:[
String
]){
let
updateGroups
=
self
.
duplicateGroups
.
removingGroupsWithEmptyAssetsWithDetails
(
afterRemovingIDs
:
idsToRemove
)
self
.
duplicateGroups
=
updateGroups
.
updatedGroups
}
}
}
PhoneManager/Class/Manager/PMPhotoManager/PhotoDuplicateManager.swift
View file @
656d7fa9
...
@@ -126,7 +126,7 @@ class PhotoDuplicateManager: @unchecked Sendable {
...
@@ -126,7 +126,7 @@ class PhotoDuplicateManager: @unchecked Sendable {
// 保存重复组
// 保存重复组
await
self
.
stateManager
.
appendDuplicateGroup
(
await
self
.
stateManager
.
appendDuplicateGroup
(
Duplicate
GroupModel
(
groupId
:
groupId
,
assets
:
assetModels
)
Similar
GroupModel
(
groupId
:
groupId
,
assets
:
assetModels
)
)
)
if
await
self
.
stateManager
.
shouldSavePendingGroups
()
{
if
await
self
.
stateManager
.
shouldSavePendingGroups
()
{
...
@@ -151,196 +151,7 @@ class PhotoDuplicateManager: @unchecked Sendable {
...
@@ -151,196 +151,7 @@ class PhotoDuplicateManager: @unchecked Sendable {
}
}
}
}
// func findDuplicateAssets(
// in assets: [PHAsset],
// mediaType: MediaType = .photo,
// loacalHandler: @Sendable @escaping ([[AssetModel]]) -> Void,
// progressHandler: @Sendable @escaping ([AssetModel]) -> Void,
// completionHandler: @Sendable @escaping ([[AssetModel]]) -> Void
// ) {
// // 使用后台优先级
// Task.detached(priority: .background) { [weak self] in
// guard let self = self else { return }
//
// do {
// // 批量处理,减少主线程切换
// let batchSize = 100
// var accumulatedProgress: [AssetModel] = []
//
// for i in stride(from: 0, to: assets.count, by: batchSize) {
// let end = min(i + batchSize, assets.count)
// let batchAssets = Array(assets[i..<end])
//
// // 处理一批资源
// let results = try await self.processBatch(batchAssets)
// accumulatedProgress.append(contentsOf: results)
//
// // 每处理一定数量后才更新UI
// if accumulatedProgress.count >= 50 {
// await MainActor.run {
// progressHandler(accumulatedProgress)
// }
// accumulatedProgress.removeAll()
// }
//
// // 给主线程喘息的机会
// try await Task.sleep(nanoseconds: 1_000_000) // 1ms
// }
//
// // 1. 加载本地数据
// await self.loadStoredData()
// print("本地数据加载完成")
//
// // 2. 通知已缓存的结果
// let cachedGroups = await self.stateManager.getAllDuplicateGroups()
// print("通知已缓存的结果", cachedGroups.count)
//
// await MainActor.run {
// let groups = cachedGroups.map { $0.assets }
// loacalHandler(groups)
// }
//
// // 3. 按特征预分组(分辨率、时间、文件大小)
// let featureGroups = try await self.groupAssetsByFeatures(assets)
//
// // 如果没有需要处理的组,直接返回缓存结果
// if featureGroups.isEmpty {
// let total = cachedGroups.map { $0.assets }
// await MainActor.run {
// completionHandler(total)
// }
// return
// }
//
// // 4. 并发处理每组资源
// try await self.processFeatureGroups(featureGroups, progressHandler: progressHandler)
//
// // 5. 完成处理
// if await !self.stateManager.getPendingDuplicateGroups().isEmpty {
// await self.savePendingDuplicateGroups()
// }
//
// let allGroups = await self.stateManager.getAllDuplicateGroups()
// await MainActor.run {
// print("执行完毕")
// completionHandler(allGroups.map { $0.assets })
// }
// } catch {
// print("查找重复资源失败: \(error)")
// await MainActor.run {
// completionHandler([]) // 返回空数组或错误处理
// }
// }
// }
// }
// 按特征分组(分辨率、文件大小等)
// private func groupAssetsByFeatures(_ assets: [PHAsset]) async throws -> [[PHAsset]] {
// var tempGroups: [String: [PHAsset]] = [:]
//
// // 使用串行队列确保线程安全
// let queue = DispatchQueue(label: "com.example.assetGrouping")
//
// // 并发处理所有资源
// await withThrowingTaskGroup(of: Void.self) { group in
// for asset in assets {
// group.addTask {
// // 创建特征键(分辨率+文件大小)
// let resolution = "\(asset.pixelWidth)x\(asset.pixelHeight)"
// let fileSize = await self.getAssetSize(asset: asset)
// let featureKey = "\(resolution)_\(fileSize)"
//
// // 使用同步队列更新共享字典
// queue.sync {
// if tempGroups[featureKey] == nil {
// tempGroups[featureKey] = []
// }
// tempGroups[featureKey]?.append(asset)
// }
// }
// }
// }
//
// // 只保留有多个资源的组
// return tempGroups.values.filter { $0.count > 1 }
// }
// 处理特征分组并查找重复项
// private func processFeatureGroups(
// _ featureGroups: [[PHAsset]],
// progressHandler: (([AssetModel]) -> Void)?
// ) async throws {
// let maxConcurrency = 2 // 最大并发数
// let batchSize = max(1, featureGroups.count / maxConcurrency)
//
// for batchIndex in stride(from: 0, to: featureGroups.count, by: batchSize) {
// let endIndex = min(batchIndex + batchSize, featureGroups.count)
// let batch = Array(featureGroups[batchIndex..<endIndex])
//
// await withThrowingTaskGroup(of: Void.self) { group in
// for assets in batch {
// group.addTask { [weak self] in
// guard let self = self else { return }
//
// // 只需要计算phash值并比较
// var hashGroups: [String: [PHAsset]] = [:]
//
// // 处理单个组内的资源,控制并发
// await withThrowingTaskGroup(of: Void.self) { innerGroup in
// for asset in assets {
// innerGroup.addTask {
// if let hash = await self.getOrCalculateHash(for: asset) {
// // 使用同步队列更新共享字典
// DispatchQueue.global().sync {
// if hashGroups[hash] == nil {
// hashGroups[hash] = []
// }
// hashGroups[hash]?.append(asset)
// }
// }
// }
// }
// }
//
// // 找出phash值相同的组
// let duplicateGroups = hashGroups.values.filter { $0.count > 1 }
//
// // 处理找到的重复组
// for duplicateGroup in duplicateGroups {
// let groupId = UUID().uuidString
// let assetModels = await self.createAssetModels(from: duplicateGroup)
//
// // 通知进度
// await MainActor.run {
// progressHandler?(assetModels)
// }
//
// // 保存重复组
// await self.stateManager.appendDuplicateGroup(
// DuplicateGroupModel(groupId: groupId, assets: assetModels)
// )
//
// if await self.stateManager.shouldSavePendingGroups() {
// await self.savePendingDuplicateGroups()
// }
// }
// }
// }
// }
// }
// }
// MARK: - 辅助方法
// nonisolated private func getAssetSize(_ asset: PHAsset) -> Int64 {
// if let resource = PHAssetResource.assetResources(for: asset).first,
// let size = resource.value(forKey: "fileSize") as? Int64 {
// return size
// }
// return 0
// }
func
getAssetSize
(
asset
:
PHAsset
)
async
->
Int64
{
func
getAssetSize
(
asset
:
PHAsset
)
async
->
Int64
{
// 先尝试从缓存获取
// 先尝试从缓存获取
if
let
cachedSize
=
await
AssetSizeCache
.
shared
.
getSize
(
for
:
asset
)
{
if
let
cachedSize
=
await
AssetSizeCache
.
shared
.
getSize
(
for
:
asset
)
{
...
@@ -386,10 +197,10 @@ class PhotoDuplicateManager: @unchecked Sendable {
...
@@ -386,10 +197,10 @@ class PhotoDuplicateManager: @unchecked Sendable {
extension
PhotoDuplicateManager
{
extension
PhotoDuplicateManager
{
private
func
loadStoredData
()
async
{
private
func
loadStoredData
()
async
{
var
loadedDuplicateGroups
:
[
Duplicate
GroupModel
]
=
[]
var
loadedDuplicateGroups
:
[
Similar
GroupModel
]
=
[]
if
let
data
=
try
?
Data
(
contentsOf
:
URL
(
fileURLWithPath
:
duplicateGroupsPath
)),
if
let
data
=
try
?
Data
(
contentsOf
:
URL
(
fileURLWithPath
:
duplicateGroupsPath
)),
let
groups
=
try
?
JSONDecoder
()
.
decode
([
Duplicate
GroupModel
]
.
self
,
from
:
data
)
{
let
groups
=
try
?
JSONDecoder
()
.
decode
([
Similar
GroupModel
]
.
self
,
from
:
data
)
{
loadedDuplicateGroups
=
groups
loadedDuplicateGroups
=
groups
}
}
...
@@ -401,7 +212,17 @@ extension PhotoDuplicateManager {
...
@@ -401,7 +212,17 @@ extension PhotoDuplicateManager {
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllDuplicateGroups
())
{
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllDuplicateGroups
())
{
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
duplicateGroupsPath
))
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
duplicateGroupsPath
))
}
}
}
}
// 移除本地文件资源
func
removeLocalFileWithIds
(
for
ids
:[
String
])
async
{
await
stateManager
.
deleteData
(
for
:
ids
)
// 保存到文件
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllDuplicateGroups
())
{
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
duplicateGroupsPath
))
}
}
}
}
// MARK: - Hash计算相关方法
// MARK: - Hash计算相关方法
...
@@ -472,45 +293,6 @@ extension PhotoDuplicateManager {
...
@@ -472,45 +293,6 @@ extension PhotoDuplicateManager {
return
pixels
.
map
{
$0
>
average
?
"1"
:
"0"
}
.
joined
()
return
pixels
.
map
{
$0
>
average
?
"1"
:
"0"
}
.
joined
()
}
}
// private func processBatch(_ assets: [PHAsset]) async throws -> [AssetModel] {
// var results: [AssetModel] = []
//
// // 按特征预分组
// let featureGroups = try await self.groupAssetsByFeatures(assets)
//
// // 处理每个特征组
// for assets in featureGroups {
// // 计算hash并分组
// var hashGroups: [String: [PHAsset]] = [:]
//
// for asset in assets {
// if let hash = await self.getOrCalculateHash(for: asset) {
// if hashGroups[hash] == nil {
// hashGroups[hash] = []
// }
// hashGroups[hash]?.append(asset)
// }
// }
//
// // 找出hash值相同的组
// let duplicateGroups = hashGroups.values.filter { $0.count > 1 }
//
// // 处理找到的重复组
// for duplicateGroup in duplicateGroups {
// let assetModels = await self.createAssetModels(from: duplicateGroup)
// results.append(contentsOf: assetModels)
//
// // 保存到状态管理器
// let groupId = UUID().uuidString
// await self.stateManager.appendDuplicateGroup(
// DuplicateGroupModel(groupId: groupId, assets: assetModels)
// )
// }
// }
//
// return results
//
// }
}
}
...
...
PhoneManager/Class/Manager/PMPhotoManager/PhotoManager.swift
View file @
656d7fa9
...
@@ -702,24 +702,44 @@ extension PhotoManager{
...
@@ -702,24 +702,44 @@ extension PhotoManager{
extension
PhotoManager
{
extension
PhotoManager
{
// 处理app图片删除
// 处理app图片删除
func
removeDataWhenDeleteInPage
(
data
:[
AssetModel
]){
func
removeDataWhenDeleteInPage
(
data
:[
AssetModel
]
,
completionHandler
:
(()
->
Void
)?
=
nil
){
let
deletes
=
data
.
compactMap
{
$0
.
localIdentifier
}
Task
.
detached
(
priority
:
.
background
)
{
[
weak
self
]
in
guard
let
self
=
self
else
{
return
}
let
others
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
otherModels
)
let
videos
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
videoModels
)
let
deletes
=
data
.
compactMap
{
$0
.
localIdentifier
}
let
screens
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
screenShotModels
)
// 临时数据更新
otherModels
=
others
let
others
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
otherModels
)
videoModels
=
videos
let
videos
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
videoModels
)
screenShotModels
=
screens
let
screens
=
removeAssets
(
withIdentifiers
:
deletes
,
from
:
screenShotModels
)
// 保存到本地
otherModels
=
others
saveToLocal
(
type
:
"video"
,
models
:
self
.
videoModels
)
videoModels
=
videos
saveToLocal
(
type
:
"other"
,
models
:
self
.
otherModels
)
screenShotModels
=
screens
saveToLocal
(
type
:
"screenshot"
,
models
:
self
.
screenShotModels
)
// 临时数据更新
let
similarPhotos
=
filterGroups
(
similarModels
,
byExcludingIDs
:
deletes
)
let
similarVideos
=
filterGroups
(
similarVideoModels
,
byExcludingIDs
:
deletes
)
let
similarShots
=
filterGroups
(
similarScreenShotModels
,
byExcludingIDs
:
deletes
)
similarModels
=
similarPhotos
similarVideoModels
=
similarVideos
similarScreenShotModels
=
similarShots
// 保存到本地
saveToLocal
(
type
:
"video"
,
models
:
self
.
videoModels
)
saveToLocal
(
type
:
"other"
,
models
:
self
.
otherModels
)
saveToLocal
(
type
:
"screenshot"
,
models
:
self
.
screenShotModels
)
await
PhotoSimilarManager
.
shared
.
removeLocalFileWithIds
(
for
:
deletes
)
await
ScreenshotSimilarJSONManager
.
shared
.
removeLocalFileWithIds
(
for
:
deletes
)
await
VideoSimilarJSONManager
.
shared
.
removeLocalFileWithIds
(
for
:
deletes
)
await
PhotoDuplicateManager
.
shared
.
removeLocalFileWithIds
(
for
:
deletes
)
completionHandler
?()
}
}
}
...
...
PhoneManager/Class/Manager/PMPhotoManager/PhotoModel.swift
View file @
656d7fa9
...
@@ -86,17 +86,18 @@ struct SimilarGroupModel: Codable {
...
@@ -86,17 +86,18 @@ struct SimilarGroupModel: Codable {
var
assets
:
[
AssetModel
]
var
assets
:
[
AssetModel
]
}
}
// 重复图片组模型
struct
DuplicateGroupModel
:
Codable
{
let
groupId
:
String
let
assets
:
[
AssetModel
]
}
struct
Match
{
struct
Match
{
let
groupIndex
:
Int
let
groupIndex
:
Int
let
matchedElements
:
[
AssetModel
]
let
matchedElements
:
[
AssetModel
]
}
}
struct
RemovalResult
{
let
updatedGroups
:
[
SimilarGroupModel
]
let
removedAssets
:
[
AssetModel
]
let
removedGroups
:
[
SimilarGroupModel
]
}
extension
Sequence
where
Element
==
[
AssetModel
]
{
extension
Sequence
where
Element
==
[
AssetModel
]
{
/// 判断二维数组中是否包含某个子数组,其元素的localIdentifier集合与给定数组完全相同(忽略顺序)
/// 判断二维数组中是否包含某个子数组,其元素的localIdentifier集合与给定数组完全相同(忽略顺序)
...
@@ -124,3 +125,69 @@ extension Sequence where Element == [AssetModel] {
...
@@ -124,3 +125,69 @@ extension Sequence where Element == [AssetModel] {
return
matches
return
matches
}
}
}
}
extension
SimilarGroupModel
{
/// 过滤掉assets中包含指定ID的元素
func
removingAssets
(
withIDs
ids
:
Set
<
String
>
)
->
SimilarGroupModel
{
let
filteredAssets
=
self
.
assets
.
filter
{
!
ids
.
contains
(
$0
.
localIdentifier
)
}
return
SimilarGroupModel
(
groupId
:
self
.
groupId
,
assets
:
filteredAssets
)
}
}
extension
Array
where
Element
==
SimilarGroupModel
{
/// 批量过滤所有组中的assets,移除包含指定ID的元素,并移除assets为空的组
func
removingGroupsWithEmptyAssets
(
afterRemovingIDs
ids
:
[
String
])
->
[
SimilarGroupModel
]
{
let
idSet
=
Set
(
ids
)
return
self
.
compactMap
{
group
in
let
filteredGroup
=
group
.
removingAssets
(
withIDs
:
idSet
)
return
filteredGroup
.
assets
.
isEmpty
?
nil
:
filteredGroup
}
}
/// 原地修改:直接在原数组上移除包含指定ID的元素,并移除assets为空的组
mutating
func
removeGroupsWithEmptyAssetsInPlace
(
afterRemovingIDs
ids
:
[
String
])
{
self
=
self
.
removingGroupsWithEmptyAssets
(
afterRemovingIDs
:
ids
)
}
/// 删除日志,拿到执行删除后的更新数据,删除数据,移除的组
func
removingGroupsWithEmptyAssetsWithDetails
(
afterRemovingIDs
ids
:
[
String
])
->
RemovalResult
{
let
idSet
=
Set
(
ids
)
var
removedAssets
=
[
AssetModel
]()
var
removedGroups
=
[
SimilarGroupModel
]()
let
updated
=
self
.
compactMap
{
(
group
:
SimilarGroupModel
)
->
SimilarGroupModel
?
in
let
filteredAssets
=
group
.
assets
.
filter
{
!
idSet
.
contains
(
$0
.
localIdentifier
)
}
let
removedInGroup
=
group
.
assets
.
filter
{
idSet
.
contains
(
$0
.
localIdentifier
)
}
removedAssets
.
append
(
contentsOf
:
removedInGroup
)
// 修改判断条件:当assets数量小于2时移除整个组
if
filteredAssets
.
count
<
2
{
removedGroups
.
append
(
group
)
return
nil
}
else
{
return
SimilarGroupModel
(
groupId
:
group
.
groupId
,
assets
:
filteredAssets
)
}
}
return
RemovalResult
(
updatedGroups
:
updated
,
removedAssets
:
removedAssets
,
removedGroups
:
removedGroups
)
}
}
extension
Sequence
where
Element
==
[
AssetModel
]
{
/// 删除二维数组中包含指定ID的元素,并移除所有元素数量少于2的子数组
func
removingElementsAndSmallGroups
(
ids
:
[
String
])
->
[[
AssetModel
]]
{
let
idSet
=
Set
(
ids
)
return
self
.
compactMap
{
group
in
let
filtered
=
group
.
filter
{
!
idSet
.
contains
(
$0
.
localIdentifier
)
}
return
filtered
.
count
<
2
?
nil
:
filtered
// 修改判断条件
}
}
}
PhoneManager/Class/Manager/PMPhotoManager/PhotoSimilarManager.swift
View file @
656d7fa9
...
@@ -349,6 +349,16 @@ extension PhotoSimilarManager{
...
@@ -349,6 +349,16 @@ extension PhotoSimilarManager{
return
SimilarGroupModel
(
groupId
:
group
.
groupId
,
assets
:
validAssets
)
return
SimilarGroupModel
(
groupId
:
group
.
groupId
,
assets
:
validAssets
)
}
.
filter
{
!
$0
.
assets
.
isEmpty
}
}
.
filter
{
!
$0
.
assets
.
isEmpty
}
}
}
// 移除本地文件资源
func
removeLocalFileWithIds
(
for
ids
:[
String
])
async
{
await
stateManager
.
deleteData
(
for
:
ids
)
// 保存到文件
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllSimilarGroups
())
{
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
similarGroupsPath
))
}
}
}
}
// MARK: - pHash获取
// MARK: - pHash获取
...
...
PhoneManager/Class/Manager/PMPhotoManager/ScreenShotSimilarManager.swift
View file @
656d7fa9
...
@@ -382,6 +382,17 @@ extension ScreenshotSimilarJSONManager{
...
@@ -382,6 +382,17 @@ extension ScreenshotSimilarJSONManager{
return
SimilarGroupModel
(
groupId
:
group
.
groupId
,
assets
:
validAssets
)
return
SimilarGroupModel
(
groupId
:
group
.
groupId
,
assets
:
validAssets
)
}
.
filter
{
!
$0
.
assets
.
isEmpty
}
}
.
filter
{
!
$0
.
assets
.
isEmpty
}
}
}
// 移除本地文件资源
func
removeLocalFileWithIds
(
for
ids
:[
String
])
async
{
await
stateManager
.
deleteData
(
for
:
ids
)
// 保存到文件
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllSimilarGroups
())
{
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
similarGroupsPath
))
}
}
}
}
// MARK: - pHash获取
// MARK: - pHash获取
...
...
PhoneManager/Class/Manager/PMPhotoManager/VideoSimilarManager.swift
View file @
656d7fa9
...
@@ -47,7 +47,7 @@ private actor VideoAssetCacheManager {
...
@@ -47,7 +47,7 @@ private actor VideoAssetCacheManager {
class
VideoSimilarJSONManager
:
@unchecked
Sendable
{
class
VideoSimilarJSONManager
:
@unchecked
Sendable
{
static
let
shared
=
VideoSimilarJSONManager
()
static
let
shared
=
VideoSimilarJSONManager
()
private
let
stateManager
=
Vide
oSimilarStateManager
()
private
let
stateManager
=
Phot
oSimilarStateManager
()
private
init
()
{}
private
init
()
{}
// 类中添加缓存管理器实例
// 类中添加缓存管理器实例
...
@@ -633,6 +633,16 @@ extension VideoSimilarJSONManager {
...
@@ -633,6 +633,16 @@ extension VideoSimilarJSONManager {
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
similarGroupsPath
))
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
similarGroupsPath
))
}
}
}
}
// 移除本地文件资源
func
removeLocalFileWithIds
(
for
ids
:[
String
])
async
{
await
stateManager
.
deleteData
(
for
:
ids
)
// 保存到文件
if
let
data
=
try
?
JSONEncoder
()
.
encode
(
await
stateManager
.
getAllSimilarGroups
())
{
try
?
data
.
write
(
to
:
URL
(
fileURLWithPath
:
similarGroupsPath
))
}
}
}
}
...
...
PhoneManager/Class/Page/Compress/Controller/CompressCompletedViewController.swift
View file @
656d7fa9
...
@@ -328,7 +328,8 @@ class CompressCompletedViewController : BaseViewController{
...
@@ -328,7 +328,8 @@ class CompressCompletedViewController : BaseViewController{
models
.
append
(
deleteModel
)
models
.
append
(
deleteModel
)
}
}
if
(
success
){
if
(
success
){
PhotoDataManager
.
manager
.
removeDataWhenDeleteInPage
(
data
:
models
)
// PhotoDataManager.manager.removeDataWhenDeleteInPage(data: models)
PhotoManager
.
shared
.
removeDataWhenDeleteInPage
(
data
:
models
)
print
(
"删除文件成功"
)
print
(
"删除文件成功"
)
self
.
showDeleteSuccess
(
fileCount
:
count
,
fileSize
:
fileSize
)
self
.
showDeleteSuccess
(
fileCount
:
count
,
fileSize
:
fileSize
)
}
else
{
}
else
{
...
...
PhoneManager/Class/Page/Home/Controller/HomeInfoViewController.swift
View file @
656d7fa9
...
@@ -94,29 +94,17 @@ class HomeInfoViewController:BaseViewController {
...
@@ -94,29 +94,17 @@ class HomeInfoViewController:BaseViewController {
}
}
self
.
showDeleteSuccess
(
fileCount
:
tempStringArray
.
count
,
fileSize
:
fileSize
)
self
.
showDeleteSuccess
(
fileCount
:
tempStringArray
.
count
,
fileSize
:
fileSize
)
// 删除缓存数据
PhotoManager
.
shared
.
removeDataWhenDeleteInPage
(
data
:
imgs
)
PhotoDataManager
.
manager
.
removeDataWhenDeleteInPage
(
data
:
imgs
)
// 更新下ids
let
new
=
self
.
ids
?
.
removingElementsAndSmallGroups
(
ids
:
imgs
.
compactMap
{
$0
.
localIdentifier
})
PhotoDataManager
.
manager
.
loadFromFileSystem
(
resultModel
:
{[
weak
self
]
model
in
DispatchQueue
.
main
.
async
{
self
.
ids
=
new
if
self
?
.
type
==
.
duplicates
{
self
?
.
ids
=
model
.
titleModelArray
[
0
]
.
assets
self
.
tablewView
.
ids
=
self
.
ids
}
self
.
tablewView
.
deleteModel
(
array
:
imgs
)
if
self
?
.
type
==
.
similar
{
self
?
.
ids
=
model
.
titleModelArray
[
1
]
.
assets
}
if
self
?
.
type
==
.
SimilarVideos
{
self
?
.
ids
=
model
.
otherModelArray
[
3
]
.
assets
}
if
self
?
.
type
==
.
similarScreenshots
{
self
?
.
ids
=
model
.
otherModelArray
[
1
]
.
assets
}
self
?
.
tablewView
.
ids
=
self
?
.
ids
self
?
.
tablewView
.
deleteModel
(
array
:
imgs
)
}
})
self
.
setDefaultPage
()
self
.
setDefaultPage
()
}
}
...
...
PhoneManager/Class/Page/Home/Controller/HomePhotosDetailViewController.swift
View file @
656d7fa9
...
@@ -36,7 +36,7 @@ class HomePhotosDetailViewController : BaseViewController {
...
@@ -36,7 +36,7 @@ class HomePhotosDetailViewController : BaseViewController {
func
dealData
(){
func
dealData
(){
var
dataArray
:
[
AssetModel
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
self
.
model
.
a
ssets
{
for
item
in
self
.
model
.
originalA
ssets
{
dataArray
=
dataArray
+
item
dataArray
=
dataArray
+
item
}
}
self
.
resourceData
=
self
.
filterTrashData
(
array
:
dataArray
)
self
.
resourceData
=
self
.
filterTrashData
(
array
:
dataArray
)
...
@@ -245,6 +245,8 @@ class HomePhotosDetailViewController : BaseViewController {
...
@@ -245,6 +245,8 @@ class HomePhotosDetailViewController : BaseViewController {
showTipsVC
()
showTipsVC
()
}
}
func
showTipsVC
(){
func
showTipsVC
(){
guard
let
mediaType
=
mediaType
else
{
guard
let
mediaType
=
mediaType
else
{
...
@@ -271,7 +273,7 @@ class HomePhotosDetailViewController : BaseViewController {
...
@@ -271,7 +273,7 @@ class HomePhotosDetailViewController : BaseViewController {
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
super
.
viewWillAppear
(
animated
)
super
.
viewWillAppear
(
animated
)
dealData
()
// 目的是为了消除cell 的选择按钮状态
// 目的是为了消除cell 的选择按钮状态
if
self
.
selectedModel
.
count
==
0
{
if
self
.
selectedModel
.
count
==
0
{
self
.
collectionView
.
reloadData
()
self
.
collectionView
.
reloadData
()
...
@@ -692,8 +694,10 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
...
@@ -692,8 +694,10 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
}
}
// 清理下缓存数据
// 清理下缓存数据
PhotoDataManager
.
manager
.
removeDataWhenDeleteInPage
(
data
:
self
.
selectedModel
)
// PhotoDataManager.manager.removeDataWhenDeleteInPage(data: self.selectedModel)
PhotoManager
.
shared
.
removeDataWhenDeleteInPage
(
data
:
self
.
selectedModel
)
{
//删除完成刷新数据
}
// 更新页面
// 更新页面
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
// 删除完成之后,移除下当前选择的数据
// 删除完成之后,移除下当前选择的数据
...
...
PhoneManager/Class/Page/Home/Controller/HomeVideoDetailController.swift
View file @
656d7fa9
...
@@ -29,7 +29,7 @@ class HomeVideoDetailController :BaseViewController {
...
@@ -29,7 +29,7 @@ class HomeVideoDetailController :BaseViewController {
func
dealData
(){
func
dealData
(){
var
dataArray
:
[
AssetModel
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
self
.
model
.
a
ssets
{
for
item
in
self
.
model
.
originalA
ssets
{
dataArray
=
dataArray
+
item
dataArray
=
dataArray
+
item
}
}
self
.
resourceData
=
self
.
filterTrashData
(
array
:
dataArray
)
self
.
resourceData
=
self
.
filterTrashData
(
array
:
dataArray
)
...
@@ -209,7 +209,7 @@ class HomeVideoDetailController :BaseViewController {
...
@@ -209,7 +209,7 @@ class HomeVideoDetailController :BaseViewController {
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
super
.
viewWillAppear
(
animated
)
super
.
viewWillAppear
(
animated
)
dealData
()
// 目的是为了消除cell 的选择按钮状态
// 目的是为了消除cell 的选择按钮状态
if
self
.
selectedModel
.
count
==
0
{
if
self
.
selectedModel
.
count
==
0
{
self
.
collectionView
.
reloadData
()
self
.
collectionView
.
reloadData
()
...
@@ -345,6 +345,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
...
@@ -345,6 +345,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
let
header
=
collectionView
.
dequeueReusableSupplementaryView
(
ofKind
:
kind
,
withReuseIdentifier
:
"HomeVideoDetailCustomHeaderView"
,
for
:
indexPath
)
as!
HomeVideoDetailCustomHeaderView
let
header
=
collectionView
.
dequeueReusableSupplementaryView
(
ofKind
:
kind
,
withReuseIdentifier
:
"HomeVideoDetailCustomHeaderView"
,
for
:
indexPath
)
as!
HomeVideoDetailCustomHeaderView
// 记录当前的 headerView
// 记录当前的 headerView
currentHeaderView
=
header
currentHeaderView
=
header
header
.
compressionTipView
.
reloadData
()
header
.
sizeLabel
.
text
=
"
\(
self
.
resourceData
.
count
)
Videos"
header
.
sizeLabel
.
text
=
"
\(
self
.
resourceData
.
count
)
Videos"
header
.
sortCallback
=
{[
weak
self
]
in
header
.
sortCallback
=
{[
weak
self
]
in
guard
let
self
else
{
return
}
guard
let
self
else
{
return
}
...
@@ -582,9 +583,11 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
...
@@ -582,9 +583,11 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
// 清理下缓存数据
// 清理下缓存数据
PhotoDataManager
.
manager
.
removeDataWhenDeleteInPage
(
data
:
self
.
selectedModel
)
//PhotoDataManager.manager.removeDataWhenDeleteInPage(data: self.selectedModel)
PhotoManager
.
shared
.
removeDataWhenDeleteInPage
(
data
:
self
.
selectedModel
)
{
// 删除完成刷新数据
}
// 更新页面
// 更新页面
...
...
PhoneManager/Class/Page/Home/Controller/HomeViewController.swift
View file @
656d7fa9
...
@@ -131,7 +131,6 @@ class HomeViewController:BaseViewController {
...
@@ -131,7 +131,6 @@ class HomeViewController:BaseViewController {
if
otherItemRow
==
0
{
if
otherItemRow
==
0
{
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
let
vc
:
HomeVideoDetailController
=
HomeVideoDetailController
(
model
:
model
)
let
vc
:
HomeVideoDetailController
=
HomeVideoDetailController
(
model
:
model
)
vc
.
dealData
()
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
}
}
...
@@ -158,7 +157,6 @@ class HomeViewController:BaseViewController {
...
@@ -158,7 +157,6 @@ class HomeViewController:BaseViewController {
}
else
{
}
else
{
vc
.
mediaType
=
.
Other
vc
.
mediaType
=
.
Other
}
}
vc
.
dealData
()
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
}
}
...
...
PhoneManager/Class/Page/Home/Model/HomeUIModel.swift
View file @
656d7fa9
...
@@ -35,11 +35,14 @@ class HomePhotosModel:Codable {
...
@@ -35,11 +35,14 @@ class HomePhotosModel:Codable {
var
folderName
:
String
var
folderName
:
String
var
allFileSize
:
Double
var
allFileSize
:
Double
var
assets
:[[
AssetModel
]]
var
assets
:[[
AssetModel
]]
var
originalAssets
:[[
AssetModel
]]
init
(
folderName
:
String
,
allFileSize
:
Double
,
assets
:
[[
AssetModel
]])
{
init
(
folderName
:
String
,
allFileSize
:
Double
,
assets
:
[[
AssetModel
]]
,
originalAssets
:[[
AssetModel
]]
=
[]
)
{
self
.
folderName
=
folderName
self
.
folderName
=
folderName
self
.
allFileSize
=
allFileSize
self
.
allFileSize
=
allFileSize
self
.
assets
=
assets
self
.
assets
=
assets
self
.
originalAssets
=
originalAssets
}
}
}
}
...
...
PhoneManager/Class/Page/Home/View/HomeCollectionViewHeader.swift
View file @
656d7fa9
...
@@ -30,6 +30,7 @@ class HomeCollectionViewHeader : UICollectionReusableView {
...
@@ -30,6 +30,7 @@ class HomeCollectionViewHeader : UICollectionReusableView {
lazy
var
permissionView
:
PMPermissionView
=
{
lazy
var
permissionView
:
PMPermissionView
=
{
let
view
=
Bundle
.
main
.
loadNibNamed
(
"PMPermissionView"
,
owner
:
nil
,
options
:
nil
)?
.
last
as!
PMPermissionView
let
view
=
Bundle
.
main
.
loadNibNamed
(
"PMPermissionView"
,
owner
:
nil
,
options
:
nil
)?
.
last
as!
PMPermissionView
view
.
isHidden
=
true
return
view
return
view
}()
}()
...
...
PhoneManager/Class/Page/Home/View/HomeView.swift
View file @
656d7fa9
...
@@ -261,7 +261,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
...
@@ -261,7 +261,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
HomeTitleCollectionCell
.
identifiers
,
for
:
indexPath
)
as!
HomeTitleCollectionCell
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
HomeTitleCollectionCell
.
identifiers
,
for
:
indexPath
)
as!
HomeTitleCollectionCell
let
model
=
viewModel
.
headerGroup
[
indexPath
.
row
]
let
model
=
viewModel
.
headerGroup
[
indexPath
.
row
]
cell
.
reloadUIWithModel
(
model
:
model
)
cell
.
reloadUIWithModel
(
model
:
model
)
// cell.reloadCoverData()
cell
.
homeTititlAction
=
{[
weak
self
]
idx
in
cell
.
homeTititlAction
=
{[
weak
self
]
idx
in
guard
let
self
=
self
else
{
return
}
guard
let
self
=
self
else
{
return
}
if
indexPath
.
row
==
0
{
if
indexPath
.
row
==
0
{
...
@@ -270,14 +269,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
...
@@ -270,14 +269,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
self
.
titleCallBack
(
model
,
.
similar
)
self
.
titleCallBack
(
model
,
.
similar
)
}
}
}
}
// cell.reloadCoverData(viewModel.headCoverImages[indexPath.row] ?? [])
// if indexPath.row == 0 {
// self.dupHeadCell = cell
// // cell.reloadCoverData(viewModel.dupCoverImage ?? [])
// }else{
// // cell.reloadCoverData(viewModel.similarCoverImage ?? [])
// self.similarHeadCell = cell
// }
if
cell
.
model
?
.
assets
.
count
??
0
>
0
{
if
cell
.
model
?
.
assets
.
count
??
0
>
0
{
cell
.
fileLabel
?
.
isHidden
=
false
cell
.
fileLabel
?
.
isHidden
=
false
...
@@ -291,13 +282,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
...
@@ -291,13 +282,6 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
cell
.
dealMediaType
(
indexPath
.
row
)
cell
.
dealMediaType
(
indexPath
.
row
)
let
model
=
viewModel
.
cardGroup
[
indexPath
.
row
]
let
model
=
viewModel
.
cardGroup
[
indexPath
.
row
]
cell
.
reloadUIWithModel
(
model
:
model
)
cell
.
reloadUIWithModel
(
model
:
model
)
// Task {
// if let image = await viewModel.coverCache.getImage(index: indexPath.row) {
// await MainActor.run {
// cell.setCoverImageOrVideo(image: image)
// }
// }
// }
return
cell
return
cell
default
:
default
:
return
UICollectionViewCell
()
return
UICollectionViewCell
()
...
...
PhoneManager/Class/Page/Home/View/VideocompressionHeadView.swift
View file @
656d7fa9
...
@@ -9,10 +9,28 @@ import UIKit
...
@@ -9,10 +9,28 @@ import UIKit
class
VideocompressionHeadView
:
UIView
{
class
VideocompressionHeadView
:
UIView
{
@IBOutlet
weak
var
sizeL
:
UILabel
!
override
func
awakeFromNib
()
{
override
func
awakeFromNib
()
{
super
.
awakeFromNib
()
super
.
awakeFromNib
()
layer
.
cornerRadius
=
8
layer
.
cornerRadius
=
8
layer
.
masksToBounds
=
true
layer
.
masksToBounds
=
true
}
}
func
reloadData
(){
let
totall
=
PhotoManager
.
shared
.
getTotalSize
(
source
:
[
PhotoManager
.
shared
.
videoModels
])
let
sizeKB
:
Double
=
totall
/
2
if
sizeKB
<
1000
{
self
.
sizeL
.
text
=
String
(
format
:
"(%.2lf) KB"
,
sizeKB
)
}
else
if
sizeKB
<
(
1000
*
1000
)
&&
sizeKB
>
1000
{
self
.
sizeL
.
text
=
String
(
format
:
"(%.2lf) MB"
,
sizeKB
/
1000
)
}
else
{
self
.
sizeL
.
text
=
String
(
format
:
"(%.2lf) GB"
,
sizeKB
/
(
1000
*
1000
))
}
}
}
}
PhoneManager/Class/Page/Home/View/VideocompressionHeadView.xib
View file @
656d7fa9
...
@@ -58,6 +58,9 @@
...
@@ -58,6 +58,9 @@
<constraint
firstItem=
"vvL-sB-aRX"
firstAttribute=
"centerX"
secondItem=
"Qxg-Hm-QKr"
secondAttribute=
"centerX"
id=
"uEJ-q5-lB3"
/>
<constraint
firstItem=
"vvL-sB-aRX"
firstAttribute=
"centerX"
secondItem=
"Qxg-Hm-QKr"
secondAttribute=
"centerX"
id=
"uEJ-q5-lB3"
/>
</constraints>
</constraints>
<freeformSimulatedSizeMetrics
key=
"simulatedDestinationMetrics"
/>
<freeformSimulatedSizeMetrics
key=
"simulatedDestinationMetrics"
/>
<connections>
<outlet
property=
"sizeL"
destination=
"rDm-i5-MN1"
id=
"AYR-5C-uKV"
/>
</connections>
<point
key=
"canvasLocation"
x=
"187.78625954198472"
y=
"250"
/>
<point
key=
"canvasLocation"
x=
"187.78625954198472"
y=
"250"
/>
</view>
</view>
</objects>
</objects>
...
...
PhoneManager/Class/Page/Home/ViewModel/HomeViewModel.swift
View file @
656d7fa9
...
@@ -50,17 +50,10 @@ class HomeViewModel {
...
@@ -50,17 +50,10 @@ class HomeViewModel {
// }
// }
private
var
photoManager
=
PhotoManager
.
shared
private
var
photoManager
=
PhotoManager
.
shared
// let coverCache = CoverCacheActor()
// 相册资源总大小
// 相册资源总大小
var
totalSize
:
Int64
{
var
totalSize
:
Int64
{
return
photoManager
.
videoTotalSize
+
photoManager
.
otherTotalSize
+
photoManager
.
screenShotTotalSize
//videoSize + otherSize + screentSize
return
photoManager
.
videoTotalSize
+
photoManager
.
otherTotalSize
+
photoManager
.
screenShotTotalSize
//videoSize + otherSize + screentSize
}
}
// var videoSize:Int64 = 0
// var otherSize:Int64 = 0
// var screentSize:Int64 = 0
var
totalFilesCount
:
Int
=
0
var
totalFilesCount
:
Int
=
0
// 首页UI数据结构
// 首页UI数据结构
...
@@ -84,7 +77,9 @@ class HomeViewModel {
...
@@ -84,7 +77,9 @@ class HomeViewModel {
HomePhotosModel
.
init
(
HomePhotosModel
.
init
(
folderName
:
HomeUIEnum
.
Videos
.
title
,
folderName
:
HomeUIEnum
.
Videos
.
title
,
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterVideoModels
]),
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterVideoModels
]),
assets
:
[
photoManager
.
filterVideoModels
]),
assets
:
[
photoManager
.
filterVideoModels
],
originalAssets
:
[
photoManager
.
videoModels
]
),
HomePhotosModel
.
init
(
HomePhotosModel
.
init
(
folderName
:
HomeUIEnum
.
SimilarScreenshots
.
title
,
folderName
:
HomeUIEnum
.
SimilarScreenshots
.
title
,
allFileSize
:
getTotalSize
(
source
:
photoManager
.
filterSimilarScreenShotModels
),
allFileSize
:
getTotalSize
(
source
:
photoManager
.
filterSimilarScreenShotModels
),
...
@@ -92,7 +87,9 @@ class HomeViewModel {
...
@@ -92,7 +87,9 @@ class HomeViewModel {
HomePhotosModel
.
init
(
HomePhotosModel
.
init
(
folderName
:
HomeUIEnum
.
Screensshots
.
title
,
folderName
:
HomeUIEnum
.
Screensshots
.
title
,
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterScreenShotModels
]),
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterScreenShotModels
]),
assets
:[
photoManager
.
filterScreenShotModels
]),
assets
:[
photoManager
.
filterScreenShotModels
],
originalAssets
:
[
photoManager
.
screenShotModels
]
),
HomePhotosModel
.
init
(
HomePhotosModel
.
init
(
folderName
:
HomeUIEnum
.
SimilarVideos
.
title
,
folderName
:
HomeUIEnum
.
SimilarVideos
.
title
,
allFileSize
:
getTotalSize
(
source
:
photoManager
.
filterSimilarVideoModels
),
allFileSize
:
getTotalSize
(
source
:
photoManager
.
filterSimilarVideoModels
),
...
@@ -100,7 +97,9 @@ class HomeViewModel {
...
@@ -100,7 +97,9 @@ class HomeViewModel {
HomePhotosModel
.
init
(
HomePhotosModel
.
init
(
folderName
:
HomeUIEnum
.
Other
.
title
,
folderName
:
HomeUIEnum
.
Other
.
title
,
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterOtherModels
]),
allFileSize
:
getTotalSize
(
source
:
[
photoManager
.
filterOtherModels
]),
assets
:
[
photoManager
.
filterOtherModels
]),
assets
:
[
photoManager
.
filterOtherModels
],
originalAssets
:
[
photoManager
.
otherModels
]
)
]
]
}
}
...
@@ -151,10 +150,6 @@ class HomeViewModel {
...
@@ -151,10 +150,6 @@ class HomeViewModel {
photoManager
.
convertScreenShotModels
{[
weak
self
]
screens
,
size
in
photoManager
.
convertScreenShotModels
{[
weak
self
]
screens
,
size
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
let
type
=
HomeUIEnum
.
Screensshots
let
type
=
HomeUIEnum
.
Screensshots
// weakSelf.cardGroup[type.index] = HomePhotosModel.init(folderName: type.title, allFileSize: Double(size), assets: [screens])
// weakSelf.getCoverImage(type: type, identifier: screens.first?.localIdentifier)
//weakSelf.screentSize = size
weakSelf
.
filterResource
()
weakSelf
.
filterResource
()
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
}
}
...
@@ -163,9 +158,6 @@ class HomeViewModel {
...
@@ -163,9 +158,6 @@ class HomeViewModel {
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
let
type
=
HomeUIEnum
.
Other
let
type
=
HomeUIEnum
.
Other
// weakSelf.cardGroup[type.index] = HomePhotosModel.init(folderName: type.title, allFileSize: Double(size), assets: [others])
// weakSelf.getCoverImage(type: type, identifier: others.first?.localIdentifier)
// weakSelf.otherSize = size
weakSelf
.
filterResource
()
weakSelf
.
filterResource
()
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
}
}
...
@@ -174,9 +166,6 @@ class HomeViewModel {
...
@@ -174,9 +166,6 @@ class HomeViewModel {
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
let
type
=
HomeUIEnum
.
Videos
let
type
=
HomeUIEnum
.
Videos
// weakSelf.cardGroup[type.index] = HomePhotosModel.init(folderName: type.title, allFileSize: Double(size), assets: [videos])
// weakSelf.getCoverImage(type: type, identifier: videos.first?.localIdentifier)
// weakSelf.videoSize = size
weakSelf
.
filterResource
()
weakSelf
.
filterResource
()
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
}
}
...
@@ -189,43 +178,20 @@ class HomeViewModel {
...
@@ -189,43 +178,20 @@ class HomeViewModel {
getSimilarScreenOptimizer
()
getSimilarScreenOptimizer
()
getSimilarVideoOptimizer
()
getSimilarVideoOptimizer
()
getGroupDuplicateImages
()
getGroupDuplicateImages
()
// DispatchQueue.main.async {[weak self] in
// guard let weakSelf = self else { return }
// weakSelf.getSimilarOptimizer()
// weakSelf.getSimilarScreenOptimizer()
// weakSelf.getSimilarVideoOptimizer()
// //weakSelf.getGroupDuplicateImages()
// }
}
}
// 获取相似图片
// 获取相似图片
func
getSimilarOptimizer
(){
func
getSimilarOptimizer
(){
let
type
=
HomeUIEnum
.
Similar
let
type
=
HomeUIEnum
.
Similar
// var currentGorup:[[AssetModel]] = []
// var currentSize:Double = 0
// var firstId:String?
var
hadblock
=
false
var
hadblock
=
false
PhotoSimilarManager
.
shared
.
findSimilarAssets
(
in
:
photoManager
.
otherAssets
)
{[
weak
self
]
group
in
PhotoSimilarManager
.
shared
.
findSimilarAssets
(
in
:
photoManager
.
otherAssets
)
{[
weak
self
]
group
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
// currentGorup.append(group)
// currentSize += group.reduce(0){$0+$1.assetSize}
// weakSelf.totalSize += Int64(currentSize)
// weakSelf.headerGroup[type.index].assets = currentGorup
// weakSelf.headerGroup[type.index].allFileSize = currentSize
weakSelf
.
photoManager
.
similarModels
.
append
(
group
)
weakSelf
.
photoManager
.
similarModels
.
append
(
group
)
// if let id = weakSelf.photoManager.similarModels.first?.first?.localIdentifier{
// if firstId != id{
// firstId = id
// weakSelf.similarCoverImage = group
// weakSelf.coverHadChange?()
// }
// }
if
!
hadblock
{
if
!
hadblock
{
weakSelf
.
reloadCellHeight
?()
weakSelf
.
reloadCellHeight
?()
hadblock
=
true
hadblock
=
true
...
@@ -246,25 +212,10 @@ class HomeViewModel {
...
@@ -246,25 +212,10 @@ class HomeViewModel {
func
getSimilarScreenOptimizer
(){
func
getSimilarScreenOptimizer
(){
let
type
=
HomeUIEnum
.
SimilarScreenshots
let
type
=
HomeUIEnum
.
SimilarScreenshots
// var currentGorup:[[AssetModel]] = []
// var currentSize:Double = 0
// var firstId:String?
ScreenshotSimilarJSONManager
.
shared
.
findSimilarAssets
(
in
:
photoManager
.
screenShotAssets
)
{[
weak
self
]
group
in
ScreenshotSimilarJSONManager
.
shared
.
findSimilarAssets
(
in
:
photoManager
.
screenShotAssets
)
{[
weak
self
]
group
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
// currentGorup.append(group)
// currentSize += group.reduce(0){$0+$1.assetSize}
// weakSelf.totalSize += Int64(currentSize)
// weakSelf.cardGroup[type.index].assets = currentGorup
// weakSelf.cardGroup[type.index].allFileSize = currentSize
//
// if let id = currentGorup.first?.first?.localIdentifier{
// if firstId != id{
// firstId = id
// weakSelf.getCoverImage(type: type, identifier: firstId)
// }
// }
weakSelf
.
photoManager
.
similarScreenShotModels
.
append
(
group
)
weakSelf
.
photoManager
.
similarScreenShotModels
.
append
(
group
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
...
@@ -280,23 +231,9 @@ class HomeViewModel {
...
@@ -280,23 +231,9 @@ class HomeViewModel {
func
getSimilarVideoOptimizer
(){
func
getSimilarVideoOptimizer
(){
let
type
=
HomeUIEnum
.
SimilarVideos
let
type
=
HomeUIEnum
.
SimilarVideos
// var currentGorup:[[AssetModel]] = []
// var currentSize:Double = 0
// var firstId:String?
VideoSimilarJSONManager
.
shared
.
findSimilarVideos
(
in
:
photoManager
.
videoAssets
)
{[
weak
self
]
group
in
VideoSimilarJSONManager
.
shared
.
findSimilarVideos
(
in
:
photoManager
.
videoAssets
)
{[
weak
self
]
group
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
// currentGorup.append(group)
// currentSize += group.reduce(0){$0+$1.assetSize}
//
// weakSelf.cardGroup[type.index].assets = currentGorup
// weakSelf.cardGroup[type.index].allFileSize = currentSize
//
// if let id = currentGorup.first?.first?.localIdentifier{
// if firstId != id{
// firstId = id
// weakSelf.getCoverImage(type: type, identifier: firstId)
// }
// }
weakSelf
.
photoManager
.
similarVideoModels
.
append
(
group
)
weakSelf
.
photoManager
.
similarVideoModels
.
append
(
group
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
1
,
type
.
index
)
...
@@ -313,25 +250,12 @@ class HomeViewModel {
...
@@ -313,25 +250,12 @@ class HomeViewModel {
func
getGroupDuplicateImages
(){
func
getGroupDuplicateImages
(){
let
type
=
HomeUIEnum
.
Dublicates
let
type
=
HomeUIEnum
.
Dublicates
// var currentGorup:[[AssetModel]] = []
// var currentSize:Double = 0
// var firstId:String?
PhotoDuplicateManager
.
shared
.
findDuplicateAssets
(
in
:
photoManager
.
otherAssets
,
mediaType
:
.
photo
)
{[
weak
self
]
groups
in
PhotoDuplicateManager
.
shared
.
findDuplicateAssets
(
in
:
photoManager
.
otherAssets
,
mediaType
:
.
photo
)
{[
weak
self
]
groups
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
// let size = groups.map{$0}.reduce(into: 0){$0+$1.assetSize}
// weakSelf.headerGroup[type.index].assets = groups
// weakSelf.headerGroup[type.index].allFileSize = currentSize
weakSelf
.
photoManager
.
duplicateModels
=
groups
weakSelf
.
photoManager
.
duplicateModels
=
groups
// if let id = groups.first?.first?.localIdentifier{
// if firstId != id{
// firstId = id
// weakSelf.dupCoverImage = groups.first ?? []
// weakSelf.coverHadChange?()
// }
// }
let
currentThread
=
Thread
.
current
let
currentThread
=
Thread
.
current
if
currentThread
.
isMainThread
{
if
currentThread
.
isMainThread
{
print
(
"在主线程执行"
)
print
(
"在主线程执行"
)
...
@@ -342,31 +266,7 @@ class HomeViewModel {
...
@@ -342,31 +266,7 @@ class HomeViewModel {
weakSelf
.
homeDataChanged
?(
0
,
type
.
index
)
weakSelf
.
homeDataChanged
?(
0
,
type
.
index
)
}
progressHandler
:
{
group
in
}
progressHandler
:
{
group
in
// guard let weakSelf = self else { return }
// currentGorup.append(group)
// currentSize += group.reduce(0){$0+$1.assetSize}
//
// weakSelf.headerGroup[type.index].assets = currentGorup
// weakSelf.headerGroup[type.index].allFileSize = currentSize
// weakSelf.photoManager.duplicateModels = groups
// 从 group 中过滤掉存在于 duplicateModels 中的元素
// let filteredGroup = group.filter { item in
// !weakSelf.photoManager.duplicateModels.flatMap { $0 }.contains(item)
// }
//
//
// if let id = currentGorup.first?.first?.localIdentifier{
// if firstId != id{
// firstId = id
// weakSelf.dupCoverImage = group
// weakSelf.coverHadChange?()
// }
// }
//
// weakSelf.homeDataChanged?(0,type.index)
}
completionHandler
:
{[
weak
self
]
totalGroup
in
}
completionHandler
:
{[
weak
self
]
totalGroup
in
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
...
@@ -383,31 +283,6 @@ class HomeViewModel {
...
@@ -383,31 +283,6 @@ class HomeViewModel {
}
}
}
}
// func getCoverImage(type:HomeUIEnum,identifier:String?){
// guard let identifier = identifier else{
// return
// }
// print("执行一次\(type.title)获取封面,id=\(identifier)")
// Task {
// PhotoManager.shared.getImage(localIdentifier:identifier,completion: { [weak self] image in
// guard let self = self else { return }
// Task {
// switch type {
// case .Dublicates:
// break
// case .Similar:
// break
// default:
// await self.coverCache.setImage(index: type.index, image: image)
// await MainActor.run {
// self.coverHadChange?()
// }
// }
// }
// })
// }
// }
}
}
extension
HomeViewModel
{
extension
HomeViewModel
{
...
...
PhoneManager/Class/Page/Keep/Controller/MaintainViewListController.swift
View file @
656d7fa9
...
@@ -103,6 +103,18 @@ class MaintainViewListController: BaseViewController {
...
@@ -103,6 +103,18 @@ class MaintainViewListController: BaseViewController {
maintaiEmptyView
.
frame
=
CGRectMake
(
0
,
140
,
ScreenW
,
330
)
maintaiEmptyView
.
frame
=
CGRectMake
(
0
,
140
,
ScreenW
,
330
)
return
maintaiEmptyView
return
maintaiEmptyView
}()
}()
func
dealBottomView
(){
if
selectAsset
.
count
>
0
{
let
count
=
selectAsset
.
flatMap
{
$0
}
.
count
maintaiBottomView
.
numberL
.
text
=
"
\(
count
)
"
view
.
addSubview
(
maintaiBottomView
)
maintaiBottomView
.
show
()
}
else
{
maintaiBottomView
.
disMiss
()
}
}
}
}
...
@@ -133,6 +145,7 @@ extension MaintainViewListController:UICollectionViewDataSource,UICollectionView
...
@@ -133,6 +145,7 @@ extension MaintainViewListController:UICollectionViewDataSource,UICollectionView
guard
let
weakSelf
=
self
else
{
return
}
guard
let
weakSelf
=
self
else
{
return
}
weakSelf
.
selectAsset
=
selects
weakSelf
.
selectAsset
=
selects
weakSelf
.
getData
()
weakSelf
.
getData
()
weakSelf
.
dealBottomView
()
}
}
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
...
@@ -153,14 +166,7 @@ extension MaintainViewListController:UICollectionViewDataSource,UICollectionView
...
@@ -153,14 +166,7 @@ extension MaintainViewListController:UICollectionViewDataSource,UICollectionView
}
}
if
selectAsset
.
count
>
0
{
dealBottomView
()
let
count
=
selectAsset
.
flatMap
{
$0
}
.
count
maintaiBottomView
.
numberL
.
text
=
"
\(
count
)
"
view
.
addSubview
(
maintaiBottomView
)
maintaiBottomView
.
show
()
}
else
{
maintaiBottomView
.
disMiss
()
}
}
}
}
}
PhoneManager/Class/Tool/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
View file @
656d7fa9
...
@@ -659,10 +659,10 @@ class PhotoAndVideoMananger {
...
@@ -659,10 +659,10 @@ class PhotoAndVideoMananger {
static
func
deleteAssets
(
localIdentifiers
:
[
String
],
suc
:
@escaping
()
->
())
{
static
func
deleteAssets
(
localIdentifiers
:
[
String
],
suc
:
@escaping
()
->
())
{
// 获取要删除的 PHAsset
// 获取要删除的 PHAsset
PMLoadingHUD
.
share
.
show
()
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
localIdentifiers
,
options
:
nil
)
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
localIdentifiers
,
options
:
nil
)
// 开始删除操作
// 开始删除操作
PMLoadingHUD
.
share
.
show
()
PHPhotoLibrary
.
shared
()
.
performChanges
({
PHPhotoLibrary
.
shared
()
.
performChanges
({
// 创建删除请求
// 创建删除请求
PHAssetChangeRequest
.
deleteAssets
(
fetchResult
)
PHAssetChangeRequest
.
deleteAssets
(
fetchResult
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment