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
f1791fbd
Commit
f1791fbd
authored
May 15, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【新增】垃圾桶详情以及部分优化
parent
b50a247c
Show whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
898 additions
and
61 deletions
+898
-61
AppDelegate.swift
PhoneManager/AppDelegate.swift
+1
-1
Contents.json
...ets.xcassets/Compress/icon_dingyue.imageset/Contents.json
+23
-0
icon_dingyue.png
....xcassets/Compress/icon_dingyue.imageset/icon_dingyue.png
+0
-0
icon_dingyue@2x.png
...assets/Compress/icon_dingyue.imageset/icon_dingyue@2x.png
+0
-0
icon_dingyue@3x.png
...assets/Compress/icon_dingyue.imageset/icon_dingyue@3x.png
+0
-0
Contents.json
...Assets.xcassets/Compress/playImage.imageset/Contents.json
+23
-0
Frame.png
...ger/Assets.xcassets/Compress/playImage.imageset/Frame.png
+0
-0
Frame@2x.png
.../Assets.xcassets/Compress/playImage.imageset/Frame@2x.png
+0
-0
Frame@3x.png
.../Assets.xcassets/Compress/playImage.imageset/Frame@3x.png
+0
-0
Contents.json
...nager/Assets.xcassets/Home/Frame 4.imageset/Contents.json
+23
-0
Frame.png
PhoneManager/Assets.xcassets/Home/Frame 4.imageset/Frame.png
+0
-0
Frame@2x.png
...anager/Assets.xcassets/Home/Frame 4.imageset/Frame@2x.png
+0
-0
Frame@3x.png
...anager/Assets.xcassets/Home/Frame 4.imageset/Frame@3x.png
+0
-0
CompressSelectCell.swift
...Manager/Class/Page/Compress/Cell/CompressSelectCell.swift
+16
-11
CompressController.swift
...r/Class/Page/Compress/Controller/CompressController.swift
+7
-2
CompressQualityController.swift
.../Page/Compress/Controller/CompressQualityController.swift
+111
-8
CompressNavView.swift
PhoneManager/Class/Page/Compress/View/CompressNavView.swift
+17
-2
QualityView.swift
PhoneManager/Class/Page/Compress/View/QualityView.swift
+10
-0
VideoPlayView.swift
PhoneManager/Class/Page/Compress/View/VideoPlayView.swift
+93
-0
HomePhotosDetailViewController.swift
...Page/Home/Controller/HomePhotosDetailViewController.swift
+1
-0
HomeVideoDetailController.swift
...lass/Page/Home/Controller/HomeVideoDetailController.swift
+1
-0
PhotoRemoveViewController.swift
...lass/Page/Home/Controller/PhotoRemoveViewController.swift
+78
-3
HomeVideoDetailCell.swift
...nager/Class/Page/Home/View/cell/HomeVideoDetailCell.swift
+0
-2
SecretVideoPlayer.swift
PhoneManager/Class/Page/Secret/View/SecretVideoPlayer.swift
+46
-3
TrashViewController.swift
...ger/Class/Page/Trash/Controller/TrashViewController.swift
+86
-6
TrashDataManager.swift
...nager/Class/Page/Trash/DataManager/TrashDataManager.swift
+32
-14
TrashUIModel.swift
PhoneManager/Class/Page/Trash/Model/TrashUIModel.swift
+5
-2
TrashContenAssetCell.swift
...eManager/Class/Page/Trash/View/TrashContenAssetCell.swift
+22
-5
TrashContenView.swift
PhoneManager/Class/Page/Trash/View/TrashContenView.swift
+95
-1
TrashDefaultView.swift
PhoneManager/Class/Page/Trash/View/TrashDefaultView.swift
+132
-0
PhotoAndVideoMananger.swift
...l/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
+68
-1
UIView+Extension.swift
...anager/Class/Tool/Extension.swift/ UIView+Extension.swift
+8
-0
No files found.
PhoneManager/AppDelegate.swift
View file @
f1791fbd
...
...
@@ -76,7 +76,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
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
)
let
success
=
GroupDatabase
.
shared
.
insert
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
item
.
assetSize
,
createDate
:
item
.
createDate
,
mediaType
:
key
==
TrashTypeEnum
.
video
?
2
:
1
,
groupId
:
uniqueId
)
if
!
success
{
Print
(
"保存保留列表数据失败"
)
}
...
...
PhoneManager/Assets.xcassets/Compress/icon_dingyue.imageset/Contents.json
0 → 100644
View file @
f1791fbd
{
"images"
:
[
{
"filename"
:
"icon_dingyue.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"icon_dingyue@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"icon_dingyue@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
PhoneManager/Assets.xcassets/Compress/icon_dingyue.imageset/icon_dingyue.png
0 → 100644
View file @
f1791fbd
1.11 KB
PhoneManager/Assets.xcassets/Compress/icon_dingyue.imageset/icon_dingyue@2x.png
0 → 100644
View file @
f1791fbd
2.98 KB
PhoneManager/Assets.xcassets/Compress/icon_dingyue.imageset/icon_dingyue@3x.png
0 → 100644
View file @
f1791fbd
5.3 KB
PhoneManager/Assets.xcassets/Compress/playImage.imageset/Contents.json
0 → 100644
View file @
f1791fbd
{
"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
}
}
PhoneManager/Assets.xcassets/Compress/playImage.imageset/Frame.png
0 → 100644
View file @
f1791fbd
516 Bytes
PhoneManager/Assets.xcassets/Compress/playImage.imageset/Frame@2x.png
0 → 100644
View file @
f1791fbd
990 Bytes
PhoneManager/Assets.xcassets/Compress/playImage.imageset/Frame@3x.png
0 → 100644
View file @
f1791fbd
1.45 KB
PhoneManager/Assets.xcassets/Home/Frame 4.imageset/Contents.json
0 → 100644
View file @
f1791fbd
{
"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
}
}
PhoneManager/Assets.xcassets/Home/Frame 4.imageset/Frame.png
0 → 100644
View file @
f1791fbd
20.4 KB
PhoneManager/Assets.xcassets/Home/Frame 4.imageset/Frame@2x.png
0 → 100644
View file @
f1791fbd
58.7 KB
PhoneManager/Assets.xcassets/Home/Frame 4.imageset/Frame@3x.png
0 → 100644
View file @
f1791fbd
97 KB
PhoneManager/Class/Page/Compress/Cell/CompressSelectCell.swift
View file @
f1791fbd
...
...
@@ -148,6 +148,10 @@ class CompressSelectCell : UICollectionViewCell {
@objc
func
selectClick
(){
// 判断是图片还是视频
if
self
.
currentMediaType
==
.
compressPhoto
{
self
.
choose
=
!
self
.
choose
}
else
{
let
vc
=
PMShowImgVideoController
()
vc
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
self
.
model
?
.
localIdentifier
??
""
)
{[
weak
self
]
url
,
error
in
guard
let
self
else
{
return
}
...
...
@@ -163,6 +167,7 @@ class CompressSelectCell : UICollectionViewCell {
}
}
}
}
override
init
(
frame
:
CGRect
)
{
...
...
PhoneManager/Class/Page/Compress/Controller/CompressController.swift
View file @
f1791fbd
...
...
@@ -256,6 +256,7 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo
if
self
.
currentResourceType
!=
flag
{
self
.
currentResourceType
=
flag
// 先移除下,防止点到
self
.
selectedModel
.
removeAll
()
self
.
resourceData
.
removeAll
()
// 如果是图片,直接从缓存中加载
if
self
.
currentResourceType
==
.
compressPhoto
{
...
...
@@ -367,9 +368,13 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo
func
jumpToNextPage
(){
// 先将值传到下一个页面
let
vc
:
CompressQualityController
=
CompressQualityController
()
vc
.
model
=
self
.
selectedModel
vc
.
currentMediaType
=
self
.
currentResourceType
vc
.
detailTiplabel
.
text
=
"You've selected
\(
self
.
selectedModel
.
count
)
out of
\(
self
.
resourceData
.
count
)
photos to compress."
vc
.
model
=
self
.
selectedModel
if
self
.
currentResourceType
==
.
compressPhoto
{
vc
.
detailTiplabel
.
text
=
"You've selected
\(
self
.
selectedModel
.
count
)
photos(A total of
\(
self
.
resourceData
.
count
)
) to compress."
}
else
{
vc
.
detailTiplabel
.
text
=
"You've selected
\(
self
.
selectedModel
.
count
)
videos(A total of
\(
self
.
resourceData
.
count
)
) to compress."
}
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
// 然后清理下当前页面的值
...
...
PhoneManager/Class/Page/Compress/Controller/CompressQualityController.swift
View file @
f1791fbd
...
...
@@ -7,29 +7,70 @@
import
Foundation
/// 压缩多少枚举
enum
CompressQualityType
{
// 压缩少量
case
low
// 压缩中等
case
mid
// 压缩较多
case
high
}
class
CompressQualityController
:
BaseViewController
{
var
model
:
[
AssetModel
]?
{
didSet
{
let
ident
=
model
!.
first
!.
localIdentifier
if
let
model
=
model
{
if
let
modelFirst
=
model
.
first
{
if
self
.
currentMediaType
==
.
compressPhoto
{
let
ident
=
modelFirst
.
localIdentifier
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
ident
)
self
.
imageView
.
image
=
image
}
else
{
// 获取视频的URL
PhotoAndVideoMananger
.
mananger
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
modelFirst
.
localIdentifier
)
{
url
,
error
in
if
let
url
=
url
{
self
.
videoView
.
videoUrl
=
url
}
}
}
}
}
}
}
var
currentQulityType
:
Int
=
0
var
currentMediaType
:
CompressType
=
.
compressPhoto
var
currentMediaType
:
CompressType
=
.
compressPhoto
{
didSet
{
self
.
imageView
.
isHidden
=
currentMediaType
==
.
compressVideo
self
.
videoView
.
isHidden
=
currentMediaType
==
.
compressPhoto
}
}
private
var
compressNav
:
CompressNavView
?
lazy
var
videoView
:
VideoPlayView
=
{
let
view
=
VideoPlayView
()
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
12
view
.
backgroundColor
=
UIColor
(
red
:
0.95
,
green
:
0.96
,
blue
:
0.99
,
alpha
:
1
)
return
view
}()
lazy
var
imageView
:
UIImageView
=
{
let
imageView
=
UIImageView
()
imageView
.
clipsToBounds
=
true
imageView
.
layer
.
cornerRadius
=
12
imageView
.
contentMode
=
.
scaleAspectFi
t
imageView
.
contentMode
=
.
scaleAspectFi
ll
imageView
.
backgroundColor
=
UIColor
(
red
:
0.95
,
green
:
0.96
,
blue
:
0.99
,
alpha
:
1
)
return
imageView
}()
...
...
@@ -46,7 +87,7 @@ class CompressQualityController : BaseViewController{
lazy
var
detailTiplabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"You've selected 2
out of 253 photos
to compress."
label
.
text
=
"You've selected 2
photos(A total of 17)
to compress."
label
.
textAlignment
=
.
left
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
12
,
weight
:
.
regular
)
label
.
backgroundColor
=
.
clear
...
...
@@ -56,6 +97,7 @@ class CompressQualityController : BaseViewController{
let
view
=
QualityView
()
view
.
type
=
0
view
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_unsel_com"
)
view
.
layer
.
borderWidth
=
1
return
view
}()
...
...
@@ -76,6 +118,14 @@ class CompressQualityController : BaseViewController{
}()
lazy
var
buttonBacView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
.
white
view
.
addTopShadow
()
return
view
}()
lazy
var
submitButton
:
UIButton
=
{
let
view
=
UIButton
()
view
.
setTitle
(
"Compress"
,
for
:
UIControl
.
State
.
normal
)
...
...
@@ -95,13 +145,15 @@ class CompressQualityController : BaseViewController{
make
.
top
.
centerX
.
width
.
equalToSuperview
()
make
.
height
.
equalTo
(
statusBarHeight
+
44
)
})
self
.
view
.
addSubview
(
self
.
videoView
)
self
.
view
.
addSubview
(
self
.
imageView
)
self
.
view
.
addSubview
(
self
.
tipLabel
)
self
.
view
.
addSubview
(
self
.
detailTiplabel
)
self
.
view
.
addSubview
(
self
.
lowQualityView
)
self
.
view
.
addSubview
(
self
.
mediumQualityView
)
self
.
view
.
addSubview
(
self
.
highQualityView
)
self
.
view
.
addSubview
(
self
.
submitButton
)
self
.
view
.
addSubview
(
self
.
buttonBacView
)
self
.
buttonBacView
.
addSubview
(
self
.
submitButton
)
self
.
imageView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
compressNav
!.
height
+
20
)
...
...
@@ -109,6 +161,13 @@ class CompressQualityController : BaseViewController{
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
height
.
equalTo
(
259
)
}
self
.
videoView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
compressNav
!.
height
+
20
)
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
height
.
equalTo
(
259
)
}
self
.
tipLabel
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
imageView
.
snp
.
bottom
)
.
offset
(
28
)
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
...
...
@@ -140,11 +199,19 @@ class CompressQualityController : BaseViewController{
make
.
height
.
equalTo
(
61
)
}
self
.
buttonBacView
.
snp
.
makeConstraints
{
make
in
make
.
bottom
.
equalTo
(
-
safeHeight
)
make
.
left
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
make
.
height
.
equalTo
(
68
)
}
self
.
submitButton
.
snp
.
makeConstraints
{
make
in
make
.
bottom
.
equalTo
(
-
40
)
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
height
.
equalTo
(
46
)
make
.
centerY
.
equalToSuperview
()
}
}
...
...
@@ -161,25 +228,61 @@ class CompressQualityController : BaseViewController{
guard
let
self
else
{
return
}
self
.
currentQulityType
=
0
self
.
lowQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_unsel_com"
)
self
.
lowQualityView
.
layer
.
borderWidth
=
1
self
.
mediumQualityView
.
layer
.
borderWidth
=
0
self
.
highQualityView
.
layer
.
borderWidth
=
0
self
.
mediumQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
self
.
highQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
setButtonTitleByType
(
type
:
.
low
)
}
self
.
mediumQualityView
.
callBack
=
{[
weak
self
]
type
in
guard
let
self
else
{
return
}
self
.
currentQulityType
=
1
self
.
lowQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
self
.
lowQualityView
.
layer
.
borderWidth
=
0
self
.
mediumQualityView
.
layer
.
borderWidth
=
1
self
.
highQualityView
.
layer
.
borderWidth
=
0
self
.
mediumQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_unsel_com"
)
self
.
highQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
setButtonTitleByType
(
type
:
.
mid
)
}
self
.
highQualityView
.
callBack
=
{[
weak
self
]
type
in
guard
let
self
else
{
return
}
self
.
currentQulityType
=
2
self
.
lowQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
self
.
lowQualityView
.
layer
.
borderWidth
=
0
self
.
mediumQualityView
.
layer
.
borderWidth
=
0
self
.
highQualityView
.
layer
.
borderWidth
=
1
self
.
mediumQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_sel_com"
)
self
.
highQualityView
.
selectedImageView
.
image
=
UIImage
(
named
:
"ic_unsel_com"
)
setButtonTitleByType
(
type
:
.
high
)
}
// 设置默认值
setButtonTitleByType
(
type
:
.
low
)
}
func
setButtonTitleByType
(
type
:
CompressQualityType
){
var
size
:
Double
=
0.0
if
let
array
=
self
.
model
{
for
item
in
array
{
size
=
size
+
item
.
assetSize
}
}
// 求和之后看点击的是哪个
var
compressSize
:
Double
=
0.0
if
type
==
.
low
{
compressSize
=
size
*
0.2
}
else
if
type
==
.
mid
{
compressSize
=
size
*
0.5
}
else
{
compressSize
=
size
*
0.8
}
self
.
submitButton
.
setTitle
(
"Compress
\(
formatFileSize
(
compressSize
)
)
"
,
for
:
.
normal
)
}
fileprivate
func
updateNextView
(
_
compressAllSize
:
Double
,
_
compressingView
:
CompressingView
,
_
comDataSource
:
[
Data
],
_
comVideoDataSource
:
[
URL
?])
{
...
...
PhoneManager/Class/Page/Compress/View/CompressNavView.swift
View file @
f1791fbd
...
...
@@ -9,6 +9,7 @@ import Foundation
class
CompressNavView
:
UIView
{
private
var
backButton
:
UIButton
!
private
var
titleLabel
:
UILabel
!
private
var
proBtn
:
UIButton
!
override
init
(
frame
:
CGRect
)
{
...
...
@@ -38,13 +39,27 @@ class CompressNavView : UIView {
make
.
width
.
height
.
equalTo
(
iconWH
)
}
titleLabel
=
UILabel
()
titleLabel
.
text
=
"Compress"
titleLabel
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
titleLabel
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
titleLabel
.
textAlignment
=
.
center
self
.
addSubview
(
titleLabel
)
proBtn
=
UIButton
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
70
,
height
:
iconWH
))
proBtn
.
setBackgroundImage
(
UIImage
(
named
:
"
home_pro_star_back
"
),
for
:
.
normal
)
proBtn
.
setBackgroundImage
(
UIImage
(
named
:
"
ic_pro_home
"
),
for
:
.
normal
)
proBtn
.
addTarget
(
self
,
action
:
#selector(
proBtnClick
)
,
for
:
.
touchUpInside
)
self
.
addSubview
(
proBtn
)
proBtn
.
snp
.
makeConstraints
{
make
in
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
centerX
.
equalToSuperview
()
make
.
centerY
.
equalTo
(
navCenterY
)
make
.
width
.
equalTo
(
100
)
make
.
height
.
equalTo
(
28
)
}
proBtn
.
snp
.
makeConstraints
{
make
in
make
.
centerY
.
equalTo
(
navCenterY
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
width
.
equalTo
(
70
)
...
...
PhoneManager/Class/Page/Compress/View/QualityView.swift
View file @
f1791fbd
...
...
@@ -41,6 +41,14 @@ class QualityView : UIView{
make
.
width
.
equalTo
(
24
)
make
.
height
.
equalTo
(
24
)
}
self
.
layer
.
borderColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
.
cgColor
// 给自身添加手势
let
tap
=
UITapGestureRecognizer
()
tap
.
addTarget
(
self
,
action
:
#selector(
selectClick
)
)
self
.
isUserInteractionEnabled
=
true
self
.
addGestureRecognizer
(
tap
)
}
required
init
?(
coder
:
NSCoder
)
{
...
...
@@ -51,6 +59,7 @@ class QualityView : UIView{
let
label
=
UILabel
()
label
.
text
=
"Low quality"
label
.
textAlignment
=
.
left
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
bold
)
label
.
backgroundColor
=
.
clear
return
label
...
...
@@ -60,6 +69,7 @@ class QualityView : UIView{
let
label
=
UILabel
()
label
.
text
=
"Compress up to 80% of the size"
label
.
textAlignment
=
.
left
label
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
12
,
weight
:
.
regular
)
label
.
backgroundColor
=
.
clear
return
label
...
...
PhoneManager/Class/Page/Compress/View/VideoPlayView.swift
0 → 100644
View file @
f1791fbd
//
// VideoPlayView.swift
// PhoneManager
//
// Created by edy on 2025/5/15.
//
import
UIKit
class
VideoPlayView
:
UIView
{
var
videoUrl
:
URL
?
{
didSet
{
if
let
url
=
videoUrl
{
self
.
videoView
.
playVideo
(
from
:
url
)
self
.
videoView
.
pause
()
}
}
}
lazy
var
playImageView
:
UIImageView
=
{
let
imageView
=
UIImageView
()
imageView
.
backgroundColor
=
.
clear
imageView
.
image
=
UIImage
(
named
:
"playImage"
)
return
imageView
}()
lazy
var
timeLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
textColor
=
.
white
label
.
text
=
"00:00"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
semibold
)
label
.
textAlignment
=
.
right
return
label
}()
lazy
var
videoView
:
SecretVideoPlayer
=
{
let
view
=
SecretVideoPlayer
()
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
12
view
.
backgroundColor
=
UIColor
(
red
:
0.95
,
green
:
0.96
,
blue
:
0.99
,
alpha
:
1
)
return
view
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
addSubview
(
self
.
videoView
)
self
.
videoView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
right
.
bottom
.
equalToSuperview
()
}
self
.
addSubview
(
self
.
timeLabel
)
self
.
timeLabel
.
snp
.
makeConstraints
{
make
in
make
.
right
.
equalToSuperview
()
.
offset
(
-
8
)
make
.
top
.
equalToSuperview
()
.
offset
(
8
)
make
.
height
.
equalTo
(
20
)
}
self
.
videoView
.
callBackCurrtntTimeString
=
{[
weak
self
]
text
in
guard
let
self
else
{
return
}
DispatchQueue
.
main
.
async
{
self
.
timeLabel
.
text
=
text
}
}
self
.
videoView
.
tapPauseCallback
=
{[
weak
self
]
state
in
guard
let
self
else
{
return
}
if
state
==
.
playing
{
self
.
playImageView
.
isHidden
=
true
}
if
state
==
.
pause
{
self
.
playImageView
.
isHidden
=
false
}
if
state
==
.
end
{
self
.
playImageView
.
isHidden
=
false
self
.
timeLabel
.
text
=
"00:00"
}
}
self
.
addSubview
(
self
.
playImageView
)
self
.
playImageView
.
snp
.
makeConstraints
{
make
in
make
.
width
.
height
.
equalTo
(
18
)
make
.
center
.
equalToSuperview
()
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
PhoneManager/Class/Page/Home/Controller/HomePhotosDetailViewController.swift
View file @
f1791fbd
...
...
@@ -323,6 +323,7 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
}
if
let
view
=
self
.
videoDetailNavView
{
cell
.
selectImageView
.
isHidden
=
!
view
.
startSelectButton
.
isSelected
cell
.
extensionView
.
isHidden
=
!
view
.
startSelectButton
.
isSelected
}
cell
.
cellCallBack
=
{[
weak
self
]
ident
,
order
in
...
...
PhoneManager/Class/Page/Home/Controller/HomeVideoDetailController.swift
View file @
f1791fbd
...
...
@@ -249,6 +249,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
if
let
view
=
self
.
videoDetailNavView
{
cell
.
selectImageView
.
isHidden
=
!
view
.
startSelectButton
.
isSelected
cell
.
extensionView
.
isHidden
=
!
view
.
startSelectButton
.
isSelected
}
cell
.
clickCallBack
=
{[
weak
self
]
click
,
order
in
...
...
PhoneManager/Class/Page/Home/Controller/PhotoRemoveViewController.swift
View file @
f1791fbd
...
...
@@ -11,7 +11,15 @@ import Photos
class
PhotoRemoveViewController
:
BaseViewController
{
var
mediaType
:
TrashTypeEnum
?
var
mediaType
:
TrashTypeEnum
?
{
didSet
{
if
mediaType
==
.
video
{
self
.
trashSubView
.
tipLabel
.
text
=
"The video in the trash can"
}
else
{
self
.
trashSubView
.
tipLabel
.
text
=
"The photo in the trash can"
}
}
}
private
var
bottomConstraint
:
Constraint
?
...
...
@@ -96,14 +104,23 @@ class PhotoRemoveViewController: BaseViewController {
self
.
showCurrentPageUIWhenTashDataChanged
()
}
}
self
.
trashSubView
.
presentTashDetailViewClickCallBack
=
{
self
.
trashSubView
.
presentTashDetailViewClickCallBack
=
{[
weak
self
]
in
guard
let
self
else
{
return
}
// 进入垃圾桶详情页面
DispatchQueue
.
main
.
async
{
let
vc
:
TrashViewController
=
TrashViewController
()
vc
.
currentPage
=
self
.
getJumpPageIndex
()
vc
.
dissmisCallBack
=
{[
weak
self
]
in
guard
let
self
else
{
return
}
self
.
showCurrentPageUIWhenTashDataChanged
()
}
self
.
present
(
vc
,
animated
:
true
)
}
}
self
.
navView
.
reSetCallBack
=
{
if
self
.
currentIndex
>
0
{
...
...
@@ -122,6 +139,51 @@ class PhotoRemoveViewController: BaseViewController {
}
showCurrentPageUIWhenTashDataChanged
()
self
.
addListener
()
}
// 跳转垃圾桶第几个page
func
getJumpPageIndex
()
->
Int
{
if
self
.
mediaType
==
.
video
{
return
1
}
if
self
.
mediaType
==
.
other
{
return
2
}
if
self
.
mediaType
==
.
shot
{
return
3
}
return
1
}
private
func
addListener
(){
NotificationCenter
.
default
.
addObserver
(
forName
:
TrashDefaultView
.
jumpToPhotosDetailPageName
,
object
:
nil
,
queue
:
.
main
)
{
[
weak
self
]
notification
in
guard
let
self
=
self
,
let
type
=
notification
.
userInfo
?[
"type"
]
as?
String
else
{
return
}
if
let
targetVC
=
self
.
navigationController
?
.
viewControllers
.
first
(
where
:
{
$0
is
HomeViewController
})
as?
HomeViewController
{
self
.
navigationController
?
.
popToViewController
(
targetVC
,
animated
:
false
)
PhotoDataManager
.
manager
.
loadFromFileSystem
{
model
in
let
data
=
type
==
"Other"
?
model
.
otherModelArray
[
4
]
:
model
.
otherModelArray
[
2
]
let
vc
:
HomePhotosDetailViewController
=
HomePhotosDetailViewController
(
model
:
data
)
vc
.
mediaType
=
type
==
"Other"
?
.
Other
:
PhotsFileType
.
screenshots
vc
.
dealData
()
targetVC
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
}
NotificationCenter
.
default
.
addObserver
(
forName
:
TrashDefaultView
.
jumpToVideosDetailPageName
,
object
:
nil
,
queue
:
.
main
)
{
[
weak
self
]
notification
in
guard
let
self
else
{
return
}
if
let
targetVC
=
self
.
navigationController
?
.
viewControllers
.
first
(
where
:
{
$0
is
HomeViewController
})
as?
HomeViewController
{
self
.
navigationController
?
.
popToViewController
(
targetVC
,
animated
:
false
)
PhotoDataManager
.
manager
.
loadFromFileSystem
{
model
in
let
data
=
model
.
otherModelArray
[
0
]
let
vc
:
HomeVideoDetailController
=
HomeVideoDetailController
(
model
:
data
)
vc
.
dealData
()
targetVC
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
}
}
private
func
removeCurrentMediaTypeTrashLastData
()
{
// 移除单利中当前类型最后一个数据
...
...
@@ -278,7 +340,7 @@ class PhotoRemoveViewController: BaseViewController {
for
item
in
dataSg
{
// 如果是视频的话不会进行分组,所以每次传入不同的id组
let
uinqueId
=
UUID
()
.
uuidString
let
success
=
GroupDatabase
.
shared
.
insert
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
item
.
assetSize
,
createDate
:
item
.
createDate
,
mediaType
:
type
.
dbType
,
groupId
:
uinqueId
)
let
success
=
GroupDatabase
.
shared
.
insert
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
item
.
assetSize
,
createDate
:
item
.
createDate
,
mediaType
:
type
==
TrashTypeEnum
.
video
?
2
:
1
,
groupId
:
uinqueId
)
if
success
==
false
{
Print
(
"保留单利数据到数据库保留列表失败"
)
}
...
...
@@ -468,4 +530,17 @@ class PhotoRemoveViewController: BaseViewController {
}
}
}
@objc
func
popCurrentPage
(){
}
deinit
{
NotificationCenter
.
default
.
removeObserver
(
self
)
}
}
PhoneManager/Class/Page/Home/View/cell/HomeVideoDetailCell.swift
View file @
f1791fbd
...
...
@@ -80,14 +80,12 @@ class HomeVideoDetailCell : UICollectionViewCell {
lazy
var
backImageView
:
UIImageView
=
{
let
view
=
UIImageView
()
view
.
isUserInteractionEnabled
=
true
view
.
contentMode
=
.
scaleAspectFill
view
.
clipsToBounds
=
true
view
.
layer
.
masksToBounds
=
true
view
.
layer
.
cornerRadius
=
12
view
.
isUserInteractionEnabled
=
true
let
tap
=
UITapGestureRecognizer
()
tap
.
addTarget
(
self
,
action
:
#selector(
cellClick
)
)
view
.
addGestureRecognizer
(
tap
)
...
...
PhoneManager/Class/Page/Secret/View/SecretVideoPlayer.swift
View file @
f1791fbd
...
...
@@ -11,6 +11,12 @@ import AVFoundation
class
SecretVideoPlayer
:
UIView
{
var
callBackCurrtntTimeString
:
(
String
)
->
Void
=
{
currentTimeString
in
}
var
tapPauseCallback
:
(
playState
)
->
Void
=
{
state
in
}
var
timeObserverToken
:
Any
?
private
var
player
:
AVPlayer
?
var
isLooping
=
false
...
...
@@ -48,11 +54,11 @@ class SecretVideoPlayer: UIView {
state
=
.
playing
player
?
.
seek
(
to
:
CMTime
.
zero
)
resume
()
}
else
{
}
else
{
state
=
.
pause
pause
()
}
self
.
tapPauseCallback
(
state
)
}
private
func
setupPlayerLayer
()
{
...
...
@@ -91,15 +97,31 @@ class SecretVideoPlayer: UIView {
}
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector(
playerItemDidReachEnd
)
,
selector
:
#selector(
playerItemDidReachEnd
)
,
name
:
.
AVPlayerItemDidPlayToEndTime
,
object
:
player
?
.
currentItem
)
addTimeObserver
()
state
=
.
playing
player
?
.
play
()
}
func
addTimeObserver
(){
let
interval
=
CMTime
(
seconds
:
0.1
,
preferredTimescale
:
CMTimeScale
(
NSEC_PER_SEC
))
timeObserverToken
=
player
?
.
addPeriodicTimeObserver
(
forInterval
:
interval
,
queue
:
.
main
)
{
[
weak
self
]
time
in
guard
let
self
=
self
,
let
currentItem
=
self
.
player
?
.
currentItem
else
{
return
}
let
currentTime
=
time
.
seconds
let
totalDuration
=
currentItem
.
duration
.
seconds
// 更新进度标签
self
.
callBackCurrtntTimeString
(
"
\(
self
.
formatTime
(
seconds
:
currentTime
)
)
"
)
}
}
// 播放完成回调
@objc
private
func
playerItemDidReachEnd
(
notification
:
Notification
)
{
if
isLooping
{
...
...
@@ -107,6 +129,7 @@ class SecretVideoPlayer: UIView {
player
?
.
play
()
}
state
=
.
end
self
.
tapPauseCallback
(
state
)
}
// 暂停播放
...
...
@@ -128,10 +151,30 @@ class SecretVideoPlayer: UIView {
name
:
.
AVPlayerItemDidPlayToEndTime
,
object
:
nil
)
if
let
token
=
timeObserverToken
{
self
.
player
?
.
removeTimeObserver
(
token
)
timeObserverToken
=
nil
}
}
// 清理资源
deinit
{
removeObservers
()
}
func
formatTime
(
seconds
:
Double
)
->
String
{
guard
!
seconds
.
isNaN
else
{
return
"00:00"
}
let
totalSeconds
=
Int
(
seconds
)
let
hours
=
totalSeconds
/
3600
let
minutes
=
(
totalSeconds
%
3600
)
/
60
let
seconds
=
totalSeconds
%
60
if
hours
>
0
{
return
String
(
format
:
"%02d:%02d:%02d"
,
hours
,
minutes
,
seconds
)
}
else
{
return
String
(
format
:
"%02d:%02d"
,
minutes
,
seconds
)
}
}
}
PhoneManager/Class/Page/Trash/Controller/TrashViewController.swift
View file @
f1791fbd
...
...
@@ -7,7 +7,9 @@
import
UIKit
class
TrashViewController
:
UIViewController
{
class
TrashViewController
:
BaseViewController
{
var
dissmisCallBack
:()
->
Void
=
{}
var
source
:[
TrashTypeEnum
]
=
[
.
video
,
.
other
,
.
shot
,
.
chat
]
...
...
@@ -17,12 +19,17 @@ class TrashViewController: UIViewController {
var
currentType
:
TrashTypeEnum
=
.
other
let
pageCount
=
4
// 总页数
var
currentPage
=
1
var
currentPage
=
1
{
didSet
{
self
.
setDelButtonUI
()
}
}
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
configUI
()
getTrashDataAndRefreshPage
()
setContentOffSet
()
}
...
...
@@ -34,14 +41,20 @@ class TrashViewController: UIViewController {
if
view
.
isKind
(
of
:
TrashContenView
.
self
){
let
tempView
=
view
as!
TrashContenView
if
tempView
.
trashType
==
item
{
tempView
.
mediaType
=
item
tempView
.
dataSource
=
data
DispatchQueue
.
main
.
async
{
tempView
.
collectionView
.
reloadData
()
}
}
}
}
// 将所有数据获取完成之后,重新刷新下删除按钮
setDelButtonUI
()
}
// 在第一次进去的时候执行一次
private
func
setContentOffSet
(){
self
.
contentScrollView
.
contentOffset
=
CGPointMake
(
ScreenW
*
CGFloat
(
self
.
currentPage
-
1
),
0
)
}
...
...
@@ -62,7 +75,8 @@ class TrashViewController: UIViewController {
delBtn
.
setTitleColor
(
.
white
,
for
:
.
normal
)
delBtn
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
semibold
)
delBtn
.
backgroundColor
=
UIColor
.
colorWithHex
(
hexStr
:
"#0082FF"
)
delBtn
.
layer
.
cornerRadius
=
10
delBtn
.
layer
.
cornerRadius
=
20
delBtn
.
addTarget
(
self
,
action
:
#selector(
delBtnAction
)
,
for
:
.
touchUpInside
)
view
.
addSubview
(
delBtn
)
delBtn
.
snp
.
makeConstraints
{
make
in
...
...
@@ -85,6 +99,12 @@ class TrashViewController: UIViewController {
contentScrollView
.
addSubview
(
otherView
)
contentScrollView
.
addSubview
(
shotView
)
contentScrollView
.
addSubview
(
chatView
)
videoView
.
deleteButton
=
delBtn
otherView
.
deleteButton
=
delBtn
shotView
.
deleteButton
=
delBtn
chatView
.
deleteButton
=
delBtn
}
override
func
viewWillLayoutSubviews
()
{
...
...
@@ -191,4 +211,64 @@ extension TrashViewController:UIScrollViewDelegate{
self
.
currentPage
=
currentPage
+
1
}
@objc
func
delBtnAction
(){
let
info
=
self
.
getTypeByCurrentPage
(
pageIndex
:
currentPage
)
let
data
=
TrashDataManager
.
getCurrentMediaTypeTrashData
(
mediaType
:
info
.
0
)
if
data
.
count
>
0
{
TrashDataManager
.
clearTrashData
(
mediaType
:
info
.
0
)
{
info
.
1
.
dataSource
.
removeAll
()
}
}
}
private
func
getTypeByCurrentPage
(
pageIndex
:
Int
)
->
(
TrashTypeEnum
,
TrashContenView
){
if
self
.
currentPage
==
1
{
return
(
TrashTypeEnum
.
video
,
self
.
videoView
)
}
if
self
.
currentPage
==
2
{
return
(
TrashTypeEnum
.
other
,
self
.
otherView
)
}
if
self
.
currentPage
==
3
{
return
(
TrashTypeEnum
.
shot
,
self
.
shotView
)
}
if
self
.
currentPage
==
4
{
return
(
TrashTypeEnum
.
chat
,
self
.
chatView
)
}
return
(
TrashTypeEnum
.
video
,
self
.
videoView
)
}
private
func
setDelButtonUI
(){
let
info
=
self
.
getTypeByCurrentPage
(
pageIndex
:
currentPage
)
let
data
:
[
AssetModel
]
=
TrashDataManager
.
getCurrentMediaTypeTrashData
(
mediaType
:
info
.
0
)
let
type
:
TrashTypeEnum
=
info
.
0
DispatchQueue
.
main
.
async
{
if
data
.
count
<=
0
{
self
.
delBtn
.
setTitle
(
"Delete"
,
for
:
.
normal
)
self
.
delBtn
.
backgroundColor
=
UIColor
(
red
:
0.6
,
green
:
0.6
,
blue
:
0.6
,
alpha
:
1
)
}
else
{
self
.
delBtn
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
if
type
==
.
video
{
self
.
delBtn
.
setTitle
(
"Delete
\(
data
.
count
)
\(
self
.
getUnits
(
type
:
type
,
data
:
data
)
)
"
,
for
:
.
normal
)
}
else
{
self
.
delBtn
.
setTitle
(
"Delete
\(
data
.
count
)
\(
self
.
getUnits
(
type
:
type
,
data
:
data
)
)
"
,
for
:
.
normal
)
}
}
}
}
// 获取单位复数
private
func
getUnits
(
type
:
TrashTypeEnum
,
data
:
[
AssetModel
])
->
String
{
if
data
.
count
>
1
{
return
type
==
.
video
?
"videos"
:
"photos"
}
else
{
return
type
==
.
video
?
"video"
:
"photo"
}
}
override
func
viewWillDisappear
(
_
animated
:
Bool
)
{
super
.
viewWillDisappear
(
animated
)
self
.
dissmisCallBack
()
}
}
PhoneManager/Class/Page/Trash/DataManager/TrashDataManager.swift
View file @
f1791fbd
...
...
@@ -9,40 +9,58 @@ import UIKit
class
TrashDataManager
{
// 撤销当前类型垃圾桶某个数据
static
func
revokeTrashData
(
mediaType
:
TrashTypeEnum
?,
identifier
:
String
,
comlete
:
@escaping
()
->
Void
){
// 清空单利和数据库的数据
clearCurrentMediaTypeTrashSigtonData
(
mediaType
:
mediaType
,
identifier
:
identifier
)
clearCurrentMediaTypeTrashDBData
(
mediaType
:
mediaType
,
identifier
:
identifier
)
comlete
()
}
/// 清除当前垃圾桶的数据
/// 清除当前类型垃圾桶的所有数据
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
()
clearCurrentMediaTypeTrashSigtonData
(
mediaType
:
mediaType
)
clearCurrentMediaTypeTrashDBData
(
mediaType
:
mediaType
)
// 删除完成之后回调
comlete
()
}
}
else
{
comlete
()
}
}
func
clearCurrentMediaTypeTrashSigtonData
(){
static
func
clearCurrentMediaTypeTrashSigtonData
(
mediaType
:
TrashTypeEnum
?,
identifier
:
String
?
=
nil
){
if
let
type
=
mediaType
{
if
identifier
==
nil
{
Singleton
.
shared
.
trashData
[
type
]
=
[]
}
else
{
Singleton
.
shared
.
trashData
[
type
]
=
Singleton
.
shared
.
trashData
[
type
]?
.
filter
({
$0
.
localIdentifier
!=
identifier
})
}
Print
(
"删除单利中当前垃圾桶数据成功"
)
}
}
func
clearCurrentMediaTypeTrashDBData
(
){
static
func
clearCurrentMediaTypeTrashDBData
(
mediaType
:
TrashTypeEnum
?,
identifier
:
String
?
=
nil
){
if
let
type
=
mediaType
{
if
identifier
==
nil
{
let
dataDB
=
TrashDatabase
.
shared
.
queryByMediaType
(
type
.
dbType
)
let
success
=
TrashDatabase
.
shared
.
batchDelete
(
localIdentifiers
:
dataDB
.
map
({
$0
.
localIdentifier
}))
if
success
{
Print
(
"删除数据库当前垃圾桶数据成功"
)
}
else
{
if
!
success
{
Print
(
"删除数据库当前垃圾桶数据失败"
)
}
}
else
{
let
success
=
TrashDatabase
.
shared
.
delete
(
localIdentifier
:
identifier
!
)
if
!
success
{
Print
(
"删除数据库当前数据失败"
)
}
}
}
}
...
...
PhoneManager/Class/Page/Trash/Model/TrashUIModel.swift
View file @
f1791fbd
...
...
@@ -7,8 +7,11 @@
import
Foundation
enum
TrashTypeEnum
:
CaseIterable
{
case
video
,
other
,
shot
,
chat
enum
TrashTypeEnum
:
String
,
CaseIterable
{
case
video
=
"Video"
case
other
=
"Other"
case
shot
=
"Screenshot"
case
chat
=
"Chat"
var
dbType
:
Int
{
switch
self
{
...
...
PhoneManager/Class/Page/Trash/View/TrashContenAssetCell.swift
View file @
f1791fbd
...
...
@@ -9,6 +9,10 @@ import UIKit
class
TrashContenAssetCell
:
UICollectionViewCell
{
var
mediaType
:
TrashTypeEnum
?
var
revokeCallBack
:()
->
Void
=
{}
@IBOutlet
weak
var
assetImage
:
UIImageView
!
override
func
awakeFromNib
()
{
...
...
@@ -24,16 +28,29 @@ class TrashContenAssetCell: UICollectionViewCell {
var
model
:
AssetModel
?{
didSet
{
guard
let
model
=
model
else
{
return
guard
let
model
=
model
else
{
return
}
if
self
.
mediaType
==
.
video
{
PhotoAndVideoMananger
.
mananger
.
getPreImageFromVideo
(
identifier
:
model
.
localIdentifier
,
completed
:
{
[
weak
self
]
image
in
guard
let
self
else
{
return
}
DispatchQueue
.
main
.
async
{
self
.
assetImage
.
image
=
image
}
})
}
else
{
DispatchQueue
.
main
.
async
{
self
.
assetImage
.
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
model
.
localIdentifier
)
}
}
}
// assetImage.im
}
@IBAction
func
removeClick
(
_
sender
:
Any
)
{
// 移除数据
if
let
model
=
self
.
model
{
TrashDataManager
.
revokeTrashData
(
mediaType
:
self
.
mediaType
,
identifier
:
model
.
localIdentifier
)
{
self
.
revokeCallBack
()
}
}
}
...
...
PhoneManager/Class/Page/Trash/View/TrashContenView.swift
View file @
f1791fbd
...
...
@@ -11,6 +11,13 @@ class TrashContenView: UIView {
var
collectionView
:
UICollectionView
!
var
mediaType
:
TrashTypeEnum
?
var
defaultView
:
TrashDefaultView
=
{
let
view
=
TrashDefaultView
()
return
view
}()
var
typeLabel
:
UILabel
!
var
sizeLabel
:
UILabel
!
...
...
@@ -19,10 +26,16 @@ class TrashContenView: UIView {
var
lineThree
:
UIView
!
var
lineFour
:
UIView
!
var
deleteButton
:
UIButton
?
var
scrollLine
:
UIView
!
let
lineW
:
CGFloat
=
(
ScreenW
-
62
)
/
4.0
var
dataSource
:[
AssetModel
]
=
[]
var
dataSource
:[
AssetModel
]
=
[]
{
didSet
{
self
.
resetContenViewUI
()
}
}
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
...
...
@@ -45,6 +58,18 @@ class TrashContenView: UIView {
/// 当数据为空的时候显示默认页面
func
setDefauleUI
(){
self
.
collectionView
.
removeFromSuperview
()
self
.
defaultView
.
mediaType
=
self
.
mediaType
self
.
addSubview
(
self
.
defaultView
)
self
.
defaultView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
right
.
bottom
.
equalToSuperview
()
}
}
func
configUI
(){
let
layout
=
UICollectionViewFlowLayout
()
layout
.
minimumInteritemSpacing
=
12
...
...
@@ -254,6 +279,75 @@ extension TrashContenView:UICollectionViewDelegate,UICollectionViewDataSource,UI
func
collectionView
(
_
collectionView
:
UICollectionView
,
cellForItemAt
indexPath
:
IndexPath
)
->
UICollectionViewCell
{
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
"TrashContenAssetCell"
,
for
:
indexPath
)
as!
TrashContenAssetCell
// 设置image
cell
.
mediaType
=
self
.
trashType
cell
.
model
=
self
.
dataSource
[
indexPath
.
item
]
cell
.
revokeCallBack
=
{
// 重新设置数据源
self
.
dataSource
=
TrashDataManager
.
getCurrentMediaTypeTrashData
(
mediaType
:
self
.
mediaType
)
}
return
cell
}
/// 重新刷新页面UI
private
func
resetContenViewUI
(){
DispatchQueue
.
main
.
async
{
// 设置数量
if
self
.
trashType
==
.
video
{
self
.
sizeLabel
.
text
=
"
\(
self
.
dataSource
.
count
)
\(
self
.
getUnits
()
)
·
\(
self
.
getDataSize
(
array
:
self
.
dataSource
)
)
"
}
else
{
self
.
sizeLabel
.
text
=
"
\(
self
.
dataSource
.
count
)
\(
self
.
getUnits
()
)
·
\(
self
.
getDataSize
(
array
:
self
.
dataSource
)
)
"
}
// 设置标题
self
.
typeLabel
.
text
=
"Trash Can ·
\(
self
.
trashType
.
rawValue
)
"
// 设置button的文字和样式
self
.
setDeleteButtonUI
()
if
self
.
dataSource
.
count
>
0
{
self
.
collectionView
.
reloadData
()
}
else
{
self
.
setDefauleUI
()
}
}
}
/// 获取资源总大小
/// - Parameter array: 资源数组
/// - Returns: 格式化后的总大小
func
getDataSize
(
array
:
[
AssetModel
])
->
String
{
var
size
:
Double
=
0.0
for
item
in
array
{
size
=
size
+
item
.
assetSize
}
return
formatFileSize
(
size
)
}
private
func
setDeleteButtonUI
(){
if
let
deleteButton
=
self
.
deleteButton
{
if
self
.
dataSource
.
count
<=
0
{
deleteButton
.
setTitle
(
"Delete"
,
for
:
.
normal
)
deleteButton
.
backgroundColor
=
UIColor
(
red
:
0.6
,
green
:
0.6
,
blue
:
0.6
,
alpha
:
1
)
return
}
deleteButton
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
if
self
.
trashType
==
.
video
{
deleteButton
.
setTitle
(
"Delete
\(
self
.
dataSource
.
count
)
\(
self
.
getUnits
()
)
"
,
for
:
.
normal
)
}
else
{
deleteButton
.
setTitle
(
"Delete
\(
self
.
dataSource
.
count
)
\(
self
.
getUnits
()
)
"
,
for
:
.
normal
)
}
}
}
// 获取单位复数
private
func
getUnits
()
->
String
{
if
self
.
dataSource
.
count
>
1
{
return
self
.
trashType
==
.
video
?
"videos"
:
"photos"
}
else
{
return
self
.
trashType
==
.
video
?
"video"
:
"photo"
}
}
}
PhoneManager/Class/Page/Trash/View/TrashDefaultView.swift
0 → 100644
View file @
f1791fbd
//
// TrashDefaultView.swift
// PhoneManager
//
// Created by edy on 2025/5/15.
//
import
UIKit
class
TrashDefaultView
:
UIView
{
static
let
jumpToPhotosDetailPageName
=
Notification
.
Name
(
"jumpToPhotosDetailPageName"
)
static
let
jumpToVideosDetailPageName
=
Notification
.
Name
(
"jumpToVideosDetailPageName"
)
var
mediaType
:
TrashTypeEnum
?
lazy
var
logImageView
:
UIImageView
=
{
let
imageView
=
UIImageView
()
imageView
.
image
=
UIImage
(
named
:
"Frame 4"
)
return
imageView
}()
lazy
var
tipLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Your trash can is empty!!"
label
.
textAlignment
=
.
center
label
.
textColor
=
UIColor
(
red
:
0.07
,
green
:
0.07
,
blue
:
0.07
,
alpha
:
1
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
17
,
weight
:
.
semibold
)
label
.
backgroundColor
=
.
clear
return
label
}()
lazy
var
detailTiplabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Once you start sending the video photos to the trash can, they will be displayed here."
label
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
label
.
textAlignment
=
.
center
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
12
,
weight
:
.
semibold
)
label
.
backgroundColor
=
.
clear
label
.
numberOfLines
=
0
return
label
}()
lazy
var
startButton
:
UIButton
=
{
let
view
=
UIButton
()
view
.
setTitle
(
"Start cleaning"
,
for
:
UIControl
.
State
.
normal
)
view
.
setTitleColor
(
UIColor
(
red
:
1
,
green
:
1
,
blue
:
1
,
alpha
:
1
),
for
:
.
normal
)
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
12
,
weight
:
.
semibold
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
16.5
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
view
.
addTarget
(
self
,
action
:
#selector(
startButtonAction
)
,
for
:
.
touchUpInside
)
return
view
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
addSubview
(
self
.
logImageView
)
self
.
addSubview
(
self
.
tipLabel
)
self
.
addSubview
(
self
.
detailTiplabel
)
self
.
addSubview
(
self
.
startButton
)
self
.
logImageView
.
snp
.
makeConstraints
{
make
in
make
.
width
.
equalTo
(
230
)
make
.
height
.
equalTo
(
154
)
make
.
centerX
.
equalToSuperview
()
make
.
top
.
equalToSuperview
()
.
offset
(
105
)
}
self
.
tipLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
top
.
equalTo
(
self
.
logImageView
.
snp
.
bottom
)
.
offset
(
30
)
make
.
height
.
equalTo
(
22
)
}
self
.
detailTiplabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
top
.
equalTo
(
self
.
tipLabel
.
snp
.
bottom
)
.
offset
(
5
)
make
.
height
.
equalTo
(
44
)
}
self
.
startButton
.
snp
.
makeConstraints
{
make
in
make
.
width
.
equalTo
(
107
)
make
.
height
.
equalTo
(
33
)
make
.
top
.
equalTo
(
self
.
detailTiplabel
.
snp
.
bottom
)
.
offset
(
30
)
make
.
centerX
.
equalToSuperview
()
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
@objc
func
startButtonAction
(){
// 跳转页面
if
let
type
=
self
.
mediaType
{
switch
type
{
case
.
video
:
jumpToVideoDetailPage
(
type
:
type
)
break
case
.
other
,
.
shot
:
jumpToPhotosDetailPage
(
type
:
type
)
break
case
.
chat
:
break
}
}
}
func
jumpToPhotosDetailPage
(
type
:
TrashTypeEnum
){
self
.
responderViewController
()?
.
dismiss
(
animated
:
true
,
completion
:
{
NotificationCenter
.
default
.
post
(
name
:
TrashDefaultView
.
jumpToPhotosDetailPageName
,
object
:
nil
,
userInfo
:
[
"type"
:
self
.
mediaType
?
.
rawValue
??
""
])
})
// PhotoDataManager.manager.loadFromFileSystem { model in
// let data = type == .other ? model.otherModelArray[4] : model.otherModelArray[2]
// let vc:HomePhotosDetailViewController = HomePhotosDetailViewController(model: data)
// vc.mediaType = type == .other ? .Other : PhotsFileType.screenshots
// vc.dealData()
// self.responderViewController()?.navigationController?.pushViewController(vc, animated: true)
// }
}
func
jumpToVideoDetailPage
(
type
:
TrashTypeEnum
){
self
.
responderViewController
()?
.
dismiss
(
animated
:
true
,
completion
:
{
NotificationCenter
.
default
.
post
(
name
:
TrashDefaultView
.
jumpToVideosDetailPageName
,
object
:
nil
)
})
}
}
PhoneManager/Class/Tool/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
View file @
f1791fbd
...
...
@@ -670,9 +670,9 @@ class PhotoAndVideoMananger {
if
success
{
suc
()
}
else
if
let
error
=
error
{
PMLoadingHUD
.
share
.
disMiss
()
print
(
"删除失败:
\(
error
.
localizedDescription
)
"
)
}
PMLoadingHUD
.
share
.
disMiss
()
}
}
...
...
@@ -1329,4 +1329,71 @@ extension PhotoAndVideoMananger{
return
zip
(
hash1
,
hash2
)
.
filter
{
$0
!=
$1
}
.
count
}
/// 根据LocalIdentifier获取视频的URL
/// - Parameters:
/// - localIdentifier: 资源标识
/// - completion: 回调
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"
]))
}
}
}
}
/// 获取视频第一帧图片显示
/// - Parameters:
/// - identifier: 图片唯一标识
/// - completed: 回调
func
getPreImageFromVideo
(
identifier
:
String
?,
completed
:
@escaping
(
UIImage
)
->
Void
){
if
identifier
==
nil
{
completed
(
UIImage
())
return
}
let
options
=
PHImageRequestOptions
()
options
.
version
=
.
current
options
.
deliveryMode
=
.
highQualityFormat
options
.
isNetworkAccessAllowed
=
true
options
.
isSynchronous
=
false
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
identifier
!
]){
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
if
let
thumbnailImage
=
image
{
completed
(
thumbnailImage
)
}
else
{
completed
(
UIImage
())
}
}
}
else
{
completed
(
UIImage
())
}
}
}
PhoneManager/Class/Tool/Extension.swift/ UIView+Extension.swift
View file @
f1791fbd
...
...
@@ -12,6 +12,14 @@ var blurKey = "blurKey"
extension
UIView
{
func
addTopShadow
()
{
layer
.
masksToBounds
=
false
layer
.
shadowColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
0.15
)
.
cgColor
layer
.
shadowOpacity
=
1
layer
.
shadowOffset
=
CGSize
(
width
:
0
,
height
:
-
2
)
// 负值使阴影显示在顶部
layer
.
shadowRadius
=
14
}
func
responderViewController
()
->
UIViewController
?
{
for
view
in
sequence
(
first
:
self
.
superview
,
next
:
{
$0
?
.
superview
})
{
...
...
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