Commit 0dbf1f97 authored by CZ1004's avatar CZ1004

【修复】问题修复

parent 6cf21672
{ {
"images" : [ "images" : [
{ {
"filename" : "img_photo__home_defpage.png", "filename" : "ic_details_charging.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"filename" : "img_photo__home_defpage@2x.png", "filename" : "ic_details_charging@2x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"filename" : "img_photo__home_defpage@3x.png", "filename" : "ic_details_charging@3x.png",
"idiom" : "universal", "idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }
......
{
"images" : [
{
"filename" : "ic_charging_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_charging_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_charging_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_cmpress_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_cmpress_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_cmpress_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_contacts_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_contacts_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_contacts_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_email_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_email_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_email_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_secret_home_pre.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_secret_home_pre@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_secret_home_pre@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "othermoren.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "othermoren@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "othermoren@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "photosmoren.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "photosmoren@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "photosmoren@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "videosmoren.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "videosmoren@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "videosmoren@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -85,7 +85,7 @@ class AdvTipDeleteView : UIView { ...@@ -85,7 +85,7 @@ class AdvTipDeleteView : UIView {
}() }()
lazy var collectionView : UICollectionView = { lazy var collectionView : UICollectionView = {
let layout = CenteredGroupCollectionViewLayout() let layout = CenteredHorizontalCollectionViewLayout()
layout.scrollDirection = .horizontal layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 8 layout.minimumInteritemSpacing = 8
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
...@@ -276,7 +276,12 @@ extension AdvTipDeleteView : UICollectionViewDataSource, UICollectionViewDelegat ...@@ -276,7 +276,12 @@ extension AdvTipDeleteView : UICollectionViewDataSource, UICollectionViewDelegat
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCell.reuseIdentifier, for: indexPath) as! ImageCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCell.reuseIdentifier, for: indexPath) as! ImageCell
cell.imageView.image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: self.dataSource![indexPath.item].localIdentifier) // 这里重新写一个异步方法去加载图片
Task {
if let image = await PhotoAndVideoMananger.mananger.getImageByIdent(identifier: self.dataSource![indexPath.item].localIdentifier) {
cell.imageView.image = image
}
}
return cell return cell
} }
...@@ -329,43 +334,75 @@ class ImageCell: UICollectionViewCell { ...@@ -329,43 +334,75 @@ class ImageCell: UICollectionViewCell {
} }
} }
class CenteredGroupCollectionViewLayout: UICollectionViewFlowLayout { class CenteredHorizontalCollectionViewLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { private var cachedAttributes: [UICollectionViewLayoutAttributes] = []
guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil } private var contentWidth: CGFloat = 0
guard let collectionView = collectionView, !attributes.isEmpty else { return attributes }
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
cachedAttributes.removeAll()
contentWidth = 0
// 计算内容总宽度 let numberOfItems = collectionView.numberOfItems(inSection: 0)
var contentWidth: CGFloat = 0 var runningOffset: CGFloat = 0
for (index, attribute) in attributes.enumerated() {
contentWidth += attribute.frame.width for item in 0..<numberOfItems {
if index < attributes.count - 1 { let indexPath = IndexPath(item: item, section: 0)
contentWidth += minimumInteritemSpacing if let attributes = layoutAttributesForItem(at: indexPath) {
if cachedAttributes.count > 0 {
runningOffset += minimumInteritemSpacing
}
attributes.frame.origin.x = runningOffset
cachedAttributes.append(attributes)
runningOffset += attributes.frame.width
contentWidth += attributes.frame.width + minimumInteritemSpacing
} }
} }
contentWidth -= minimumInteritemSpacing
contentWidth += sectionInset.left + sectionInset.right contentWidth += sectionInset.left + sectionInset.right
// 计算偏移量
let collectionViewWidth = collectionView.bounds.width let collectionViewWidth = collectionView.bounds.width
var offsetX: CGFloat = 0 var offsetX: CGFloat = 0
if contentWidth < collectionViewWidth { if contentWidth < collectionViewWidth {
offsetX = (collectionViewWidth - contentWidth) / 2 offsetX = (collectionViewWidth - contentWidth) / 2
} }
// 调整布局属性 runningOffset = offsetX + sectionInset.left
var runningOffset: CGFloat = offsetX + sectionInset.left for attribute in cachedAttributes {
for (index, attribute) in attributes.enumerated() {
attribute.frame.origin.x = runningOffset attribute.frame.origin.x = runningOffset
if index < attributes.count - 1 { runningOffset += attribute.frame.width + minimumInteritemSpacing
runningOffset += attribute.frame.width + minimumInteritemSpacing }
} else { }
runningOffset += attribute.frame.width
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleAttributes: [UICollectionViewLayoutAttributes] = []
for attributes in cachedAttributes {
if attributes.frame.intersects(rect) {
visibleAttributes.append(attributes)
} }
} }
return visibleAttributes
}
return attributes override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes
} }
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true return true
} }
}
override var collectionViewContentSize: CGSize {
guard let collectionView = collectionView else { return .zero }
let collectionViewWidth = collectionView.bounds.width
if contentWidth < collectionViewWidth {
return CGSize(width: collectionViewWidth, height: collectionView.bounds.height)
}
return CGSize(width: contentWidth, height: collectionView.bounds.height)
}
}
...@@ -87,6 +87,21 @@ class ChargeGuideController : BaseViewController,UIScrollViewDelegate,UINavigati ...@@ -87,6 +87,21 @@ class ChargeGuideController : BaseViewController,UIScrollViewDelegate,UINavigati
view.tipTitleLabel.text = self.tipString[i] view.tipTitleLabel.text = self.tipString[i]
if i==0 { if i==0 {
view.detailTipTitleLabel.isHidden = false view.detailTipTitleLabel.isHidden = false
// 在滑动的第一个添加一个button
let jumpButton = UIButton(type: .custom)
jumpButton.setTitle("Open shortcut command", for: .normal)
jumpButton.setTitleColor(.white, for: .normal)
jumpButton.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
jumpButton.layer.cornerRadius = 25
jumpButton.clipsToBounds = true
view.addSubview(jumpButton)
jumpButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(32)
make.right.equalToSuperview().offset(-32)
make.height.equalTo(50)
make.bottom.equalToSuperview().offset(-122 * RScreenH())
}
jumpButton.addTarget(self, action: #selector(jumpButtonAction), for: .touchUpInside)
}else { }else {
view.detailTipTitleLabel.isHidden = true view.detailTipTitleLabel.isHidden = true
} }
...@@ -117,6 +132,14 @@ class ChargeGuideController : BaseViewController,UIScrollViewDelegate,UINavigati ...@@ -117,6 +132,14 @@ class ChargeGuideController : BaseViewController,UIScrollViewDelegate,UINavigati
self.navigationController?.popViewController(animated: true) self.navigationController?.popViewController(animated: true)
} }
@objc func jumpButtonAction(){
if let url = URL(string: "shortcuts://") {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation == .pop { if operation == .pop {
return CustomPopAnimator() return CustomPopAnimator()
......
...@@ -264,7 +264,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie ...@@ -264,7 +264,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
vc.getVideoURLFromLocalIdentifier(localIdentifier: ident.localIdentifier) { url, error in vc.getVideoURLFromLocalIdentifier(localIdentifier: ident.localIdentifier) { url, error in
if url != nil{ if url != nil{
DispatchQueue.main.async { DispatchQueue.main.async {
vc.url = url
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
} }
}else{ }else{
......
...@@ -94,6 +94,9 @@ class HomeViewController:BaseViewController { ...@@ -94,6 +94,9 @@ class HomeViewController:BaseViewController {
// 调用下追踪权限 // 调用下追踪权限
checkTrackingAuthorization() checkTrackingAuthorization()
// 获取主页数据
setupData()
let dataUpdated = Notification.Name("DataUpdatedNotification") let dataUpdated = Notification.Name("DataUpdatedNotification")
NotificationCenter.default.addObserver(self, selector: #selector(handleDataUpdated(_:)), name: dataUpdated, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleDataUpdated(_:)), name: dataUpdated, object: nil)
...@@ -206,34 +209,27 @@ class HomeViewController:BaseViewController { ...@@ -206,34 +209,27 @@ class HomeViewController:BaseViewController {
self?.homeView?.model = model self?.homeView?.model = model
self?.homeView?.collectionView.reloadData() self?.homeView?.collectionView.reloadData()
} }
// 总数据 文件数量和文件大小
PhotoAndVideoMananger.mananger.fetchAllFile {[weak self] index, FileSize in
guard let self else {return}
// 相当于进度条
self.homeView?.model?.allFileNumber = index
self.homeView?.model?.allFileSize = FileSize
self.homeView?.setTitle()
} completion: {[weak self] fileSize,index in
guard let self else {return}
self.homeView?.model?.allFileNumber = index
self.homeView?.model?.allFileSize = fileSize
self.homeView?.setTitle()
}
}) })
// 总数据 文件数量和文件大小
PhotoAndVideoMananger.mananger.fetchAllFile {[weak self] index, FileSize in
guard let self else {return}
// 相当于进度条
self.homeView?.model?.allFileNumber = index
self.homeView?.model?.allFileSize = FileSize
self.homeView?.setTitle()
} completion: {[weak self] fileSize,index in
guard let self else {return}
self.homeView?.model?.allFileNumber = index
self.homeView?.model?.allFileSize = fileSize
self.homeView?.setTitle()
}
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
// 获取主页数据
setupData()
if !isShowCharge { if !isShowCharge {
if BatteryMonitorManager.shared.getBatteryIsCharging() { if BatteryMonitorManager.shared.getBatteryIsCharging() {
// 从字典里面取 如果有 // 从字典里面取 如果有
...@@ -424,12 +420,7 @@ class HomeViewController:BaseViewController { ...@@ -424,12 +420,7 @@ class HomeViewController:BaseViewController {
@objc func handleDataUpdated(_ notification: Notification) { @objc func handleDataUpdated(_ notification: Notification) {
// 首页这里要重新获取下数据 // 首页这里要重新获取下数据
PhotoDataManager.manager.loadFromFileSystem(resultModel: {[weak self] model in setupData()
DispatchQueue.main.async {
self?.homeView?.model = model
self?.homeView?.collectionView.reloadData()
}
})
} }
} }
......
...@@ -23,21 +23,26 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -23,21 +23,26 @@ class HomeCollectionViewHeader : UICollectionReusableView {
setupUI() setupUI()
} }
private lazy var logoImageView:UIImageView = { lazy var progressBar : CustomProgressBar = {
let imageView = UIImageView() let bar = CustomProgressBar()
imageView.image = UIImage(named: "img_file_home") return bar
imageView.backgroundColor = .clear
return imageView
}()
private lazy var cleanNowButton : UIButton = {
let button = UIButton(type: .custom)
button.backgroundColor = .clear
button.setImage(UIImage(named: "but_clean_home"), for: .normal)
button.addTarget(self, action: #selector(clickCleanNowButton), for: .touchUpInside)
return button
}() }()
// private lazy var logoImageView:UIImageView = {
// let imageView = UIImageView()
// imageView.image = UIImage(named: "img_file_home")
// imageView.backgroundColor = .clear
// return imageView
// }()
//
// private lazy var cleanNowButton : UIButton = {
// let button = UIButton(type: .custom)
// button.backgroundColor = .clear
// button.setImage(UIImage(named: "but_clean_home"), for: .normal)
// button.addTarget(self, action: #selector(clickCleanNowButton), for: .touchUpInside)
// return button
// }()
//
private lazy var tipLabel:UILabel = { private lazy var tipLabel:UILabel = {
...@@ -47,67 +52,73 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -47,67 +52,73 @@ class HomeCollectionViewHeader : UICollectionReusableView {
}() }()
private lazy var subTiplabel : UILabel = { // private lazy var subTiplabel : UILabel = {
let label = UILabel() // let label = UILabel()
label.textAlignment = .left // label.textAlignment = .left
label.text = "of storage to clean up" // label.text = "of storage to clean up"
label.textColor = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 1) // label.textColor = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 1)
label.font = UIFont.systemFont(ofSize: 14, weight: .regular) // label.font = UIFont.systemFont(ofSize: 14, weight: .regular)
return label // return label
}() // }()
private func setupUI() { private func setupUI() {
// logo图片 // logo图片
self.addSubview(self.logoImageView) // self.addSubview(self.logoImageView)
self.logoImageView.snp.makeConstraints { make in // self.logoImageView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(8) // make.top.equalToSuperview().offset(8)
make.right.equalToSuperview() // make.right.equalToSuperview()
make.width.height.equalTo(182) // make.width.height.equalTo(182)
} // }
// 文本 // 文本
self.addSubview(self.tipLabel) self.addSubview(self.tipLabel)
self.setFileAndCount(count: 0, fileSize: 0)
self.tipLabel.snp.makeConstraints { make in self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview() make.left.equalToSuperview()
make.top.equalToSuperview().offset(32) make.top.equalToSuperview().offset(4)
make.height.equalTo(31) make.height.equalTo(17)
} }
self.addSubview(self.progressBar)
self.addSubview(self.subTiplabel) self.progressBar.snp.makeConstraints { make in
self.subTiplabel.snp.makeConstraints { make in make.top.equalTo(self.tipLabel.snp.bottom).offset(12)
make.top.equalTo(self.tipLabel.snp.bottom).offset(4) make.width.equalToSuperview()
make.height.equalTo(31)
make.left.equalToSuperview() make.left.equalToSuperview()
make.width.equalTo(168)
make.height.equalTo(20)
} }
// self.addSubview(self.subTiplabel)
// self.subTiplabel.snp.makeConstraints { make in
// make.top.equalTo(self.tipLabel.snp.bottom).offset(4)
// make.left.equalToSuperview()
// make.width.equalTo(168)
// make.height.equalTo(20)
// }
// 按钮 // 按钮
self.addSubview(self.cleanNowButton) // self.addSubview(self.cleanNowButton)
self.cleanNowButton.snp.makeConstraints { make in // self.cleanNowButton.snp.makeConstraints { make in
make.top.equalTo(self.subTiplabel.snp.bottom).offset(24) // make.top.equalTo(self.subTiplabel.snp.bottom).offset(24)
make.left.equalToSuperview() // make.left.equalToSuperview()
make.width.equalTo(159) // make.width.equalTo(159)
make.height.equalTo(45) // make.height.equalTo(45)
} // }
} }
@objc func clickCleanNowButton(){ // @objc func clickCleanNowButton(){
cleanNowButtonCallback() // cleanNowButtonCallback()
} // }
func setFileAndCount(count:Int,fileSize:Double) { func setFileAndCount(count:Int,fileSize:Double) {
let countString = "\(count)" let countString = "\(count)"
let fileSizeString = formatFileSize(fileSize) let fileSizeString = formatFileSize(fileSize)
let text = countString + " files · " + fileSizeString let text = countString + " files · " + fileSizeString + " of storage to clean up"
let attributedText = NSMutableAttributedString(string: text) let attributedText = NSMutableAttributedString(string: text)
// 设置整体文本样式 // 设置整体文本样式
let fullTextAttributes: [NSAttributedString.Key: Any] = [ let fullTextAttributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 18, weight: .bold), .font: UIFont.systemFont(ofSize: 12, weight: .regular),
.foregroundColor: UIColor(red: 0.4, green: 0.4, blue: 0.4,alpha:1) .foregroundColor: UIColor(red: 0.4, green: 0.4, blue: 0.4,alpha:1)
] ]
attributedText.addAttributes(fullTextAttributes, range: NSRange(location: 0, length: text.count)) attributedText.addAttributes(fullTextAttributes, range: NSRange(location: 0, length: text.count))
...@@ -116,8 +127,8 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -116,8 +127,8 @@ class HomeCollectionViewHeader : UICollectionReusableView {
if let range1 = text.range(of: countString) { if let range1 = text.range(of: countString) {
let nsRange1 = NSRange(range1, in: text) let nsRange1 = NSRange(range1, in: text)
attributedText.addAttributes([ attributedText.addAttributes([
.foregroundColor: UIColor.colorWithHex(hexStr: mColor), .foregroundColor: UIColor.colorWithHex(hexStr: black6Color),
.font:UIFont.systemFont(ofSize: 21, weight: .bold) .font:UIFont.systemFont(ofSize: 12, weight: .semibold)
], range: nsRange1) ], range: nsRange1)
} }
...@@ -125,13 +136,132 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -125,13 +136,132 @@ class HomeCollectionViewHeader : UICollectionReusableView {
if let range2 = text.range(of: fileSizeString) { if let range2 = text.range(of: fileSizeString) {
let nsRange2 = NSRange(range2, in: text) let nsRange2 = NSRange(range2, in: text)
attributedText.addAttributes([ attributedText.addAttributes([
.font:UIFont.systemFont(ofSize: 21, weight: .bold), .font:UIFont.systemFont(ofSize: 12, weight: .semibold),
.foregroundColor: UIColor.colorWithHex(hexStr: mColor) .foregroundColor: UIColor.colorWithHex(hexStr: black6Color)
], range: nsRange2) ], range: nsRange2)
} }
// 将 attributedText 赋值给 UILabel // 将 attributedText 赋值给 UILabel
self.tipLabel.attributedText = attributedText self.tipLabel.attributedText = attributedText
} }
}
class CustomProgressBar: UIView {
private let progressLayer = CALayer()
private let usedColor = UIColor(hex: "#0082FF") ?? .blue
private let chaoticColor = UIColor(hex: "#FFAE00") ?? .yellow
private let idleColor = UIColor(hex: "#FFFFFF") ?? .white
private let usedLabel = UILabel()
private let chaoticLabel = UILabel()
private let idleLabel = UILabel()
private let dotSize: CGFloat = 8
private let labelSpacing: CGFloat = 18
var usedProgress: CGFloat = 0
var chaoticProgress: CGFloat = 0
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupUI()
}
private func setupUI() {
layer.addSublayer(progressLayer)
usedLabel.text = "Used"
usedLabel.font = UIFont.systemFont(ofSize: 12)
usedLabel.textColor = .black
addSubview(usedLabel)
chaoticLabel.text = "Chaotic content"
chaoticLabel.font = UIFont.systemFont(ofSize: 12)
chaoticLabel.textColor = .black
addSubview(chaoticLabel)
idleLabel.text = "Idle"
idleLabel.font = UIFont.systemFont(ofSize: 12)
idleLabel.textColor = .black
addSubview(idleLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
progressLayer.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 10)
progressLayer.cornerRadius = 5
progressLayer.masksToBounds = true
updateProgress()
let dotY = progressLayer.frame.maxY + 9
let usedDotX = bounds.minX
let chaoticDotX = usedDotX + usedLabel.intrinsicContentSize.width + dotSize + labelSpacing
let idleDotX = chaoticDotX + chaoticLabel.intrinsicContentSize.width + dotSize + labelSpacing
drawDot(at: CGPoint(x: usedDotX, y: dotY), color: usedColor)
usedLabel.frame = CGRect(x: usedDotX + dotSize + 5, y: 0, width: usedLabel.intrinsicContentSize.width, height: usedLabel.intrinsicContentSize.height)
usedLabel.centerY = dotY + 4
drawDot(at: CGPoint(x: chaoticDotX, y: dotY), color: chaoticColor)
chaoticLabel.frame = CGRect(x: chaoticDotX + dotSize + 5, y: 0, width: chaoticLabel.intrinsicContentSize.width, height: chaoticLabel.intrinsicContentSize.height)
chaoticLabel.centerY = dotY + 4
drawDot(at: CGPoint(x: idleDotX, y: dotY), color: idleColor)
idleLabel.frame = CGRect(x: idleDotX + dotSize + 5, y: 0, width: idleLabel.intrinsicContentSize.width, height: idleLabel.intrinsicContentSize.height)
idleLabel.centerY = dotY + 4
}
private func updateProgress() {
DispatchQueue.global(qos: .userInitiated).async {
let disk = WidgetPublicModel.getDiskSpace()
let usedData = Double(disk.1)
let tolData = Double(disk.0)
Task {
let photoData = await Double(StorageManager.manager.getPhotoResourceMemory())
// 回到主线程更新 UI
DispatchQueue.main.async {
let usedProgress = CGFloat(usedData / tolData)
let chaoticProgress = CGFloat(photoData / tolData)
let totalProgress = usedProgress + chaoticProgress
let remainingProgress = 1 - totalProgress
let usedWidth = self.bounds.width * usedProgress
let chaoticWidth = self.bounds.width * chaoticProgress
let idleWidth = self.bounds.width * remainingProgress
let usedLayer = CALayer()
usedLayer.frame = CGRect(x: 0, y: 0, width: usedWidth, height: self.progressLayer.bounds.height)
usedLayer.backgroundColor = self.usedColor.cgColor
let chaoticLayer = CALayer()
chaoticLayer.frame = CGRect(x: usedWidth, y: 0, width: chaoticWidth, height: self.progressLayer.bounds.height)
chaoticLayer.backgroundColor = self.chaoticColor.cgColor
let idleLayer = CALayer()
idleLayer.frame = CGRect(x: usedWidth + chaoticWidth, y: 0, width: idleWidth, height: self.progressLayer.bounds.height)
idleLayer.backgroundColor = self.idleColor.cgColor
self.progressLayer.sublayers = [usedLayer, chaoticLayer, idleLayer]
}
}
}
}
private func drawDot(at point: CGPoint, color: UIColor) {
let dotLayer = CAShapeLayer()
let dotPath = UIBezierPath(ovalIn: CGRect(x: point.x, y: point.y, width: dotSize, height: dotSize))
dotLayer.path = dotPath.cgPath
dotLayer.fillColor = color.cgColor
layer.addSublayer(dotLayer)
}
} }
...@@ -122,7 +122,7 @@ class HomeView:UIView { ...@@ -122,7 +122,7 @@ class HomeView:UIView {
self.insertSubview(collectionView, at: 0) self.insertSubview(collectionView, at: 0)
collectionView.snp.makeConstraints { make in collectionView.snp.makeConstraints { make in
make.top.equalTo(self.homeNavView!.snp.bottom).offset(16) make.top.equalTo(self.homeNavView!.snp.bottom).offset(0)
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.width.equalToSuperview().offset(-2 * marginLR) make.width.equalToSuperview().offset(-2 * marginLR)
make.bottom.equalToSuperview().offset( -homeTabbarView!.height - 16) make.bottom.equalToSuperview().offset( -homeTabbarView!.height - 16)
...@@ -175,7 +175,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -175,7 +175,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
self.titleCallBack(smodel!,.similar) self.titleCallBack(smodel!,.similar)
} }
} }
if indexPath.row == 0 { if indexPath.row == 0 {
self.dupHeadCell = cell self.dupHeadCell = cell
}else{ }else{
...@@ -198,6 +198,10 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -198,6 +198,10 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
cell.mediaType = 1 cell.mediaType = 1
cell.playImageView.isHidden = false cell.playImageView.isHidden = false
} }
if indexPath.row == 1 || indexPath.row == 2{
cell.mediaType = 2
cell.playImageView.isHidden = true
}
cell.model = model?.otherModelArray[indexPath.row] cell.model = model?.otherModelArray[indexPath.row]
return cell return cell
default: default:
...@@ -317,8 +321,13 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -317,8 +321,13 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
// 设置头部视图的大小 // 设置头部视图的大小
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize { func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
if section == 0 { if section == 0 {
return CGSize(width: self.collectionView.width, height: 210) return CGSize(width: self.collectionView.width, height: 76)
} }
return CGSize.zero return CGSize.zero
} }
func getOuterCollectionViewHeader() -> UICollectionReusableView? {
let indexPath = IndexPath(item: 0, section: 0)
return self.collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath)
}
} }
...@@ -7,7 +7,7 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -7,7 +7,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
var similarFlag : Bool = false var similarFlag : Bool = false
// 如果是图片,类型为0,视频为1 // 图片-0,视频-1,截图-2
var mediaType : Int = 0 var mediaType : Int = 0
// MARK: - Properties // MARK: - Properties
...@@ -111,7 +111,7 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -111,7 +111,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
count = count + item.count count = count + item.count
} }
// 设置数量文字 // 设置数量文字
if self.mediaType == 0 { if self.mediaType == 0 || self.mediaType == 2{
self.countLabel.text = "\(count) Photos" self.countLabel.text = "\(count) Photos"
}else{ }else{
self.countLabel.text = "\(count) Videos" self.countLabel.text = "\(count) Videos"
...@@ -128,8 +128,19 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -128,8 +128,19 @@ class HomeOtherCollectionCell: UICollectionViewCell {
} }
guard let asset = model.assets.first?.first else {return} guard let asset = model.assets.first?.first else {
if self.mediaType == 0 { DispatchQueue.main.async {
if self.mediaType == 0 {
self.imageView.image = UIImage(named: "othermoren")
}else if self.mediaType == 2 {
self.imageView.image = UIImage(named: "photosmoren")
} else{
self.imageView.image = UIImage(named: "videosmoren")
}
}
return
}
if self.mediaType == 0 || self.mediaType == 2 {
let image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: asset.localIdentifier) let image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: asset.localIdentifier)
DispatchQueue.main.async {[weak self] in DispatchQueue.main.async {[weak self] in
guard let self else {return} guard let self else {return}
...@@ -142,7 +153,7 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -142,7 +153,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
// 获取当前版本的照片或视频 // 获取当前版本的照片或视频
options.version = .current options.version = .current
// 尽可能快地提供结果 // 尽可能快地提供结果
options.deliveryMode = .opportunistic options.deliveryMode = .highQualityFormat
// 允许从iCloud请求 // 允许从iCloud请求
options.isNetworkAccessAllowed = true options.isNetworkAccessAllowed = true
// 异步请求 // 异步请求
...@@ -159,7 +170,7 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -159,7 +170,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
self.imageView.image = thumbnailImage self.imageView.image = thumbnailImage
} }
} else { } else {
self.imageView.image = UIImage(named: "img_photo__home_defpage") self.imageView.image = UIImage(named: "img_vedio_defpage")
print("无法获取图片") print("无法获取图片")
} }
} }
...@@ -190,7 +201,7 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -190,7 +201,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
imageView.snp.makeConstraints { make in imageView.snp.makeConstraints { make in
make.top.equalTo(self.titleLabel.snp.bottom).offset(8) make.top.equalTo(self.titleLabel.snp.bottom).offset(8)
make.bottom.equalToSuperview().offset(-16) // make.bottom.equalToSuperview().offset(-16)
make.left.equalToSuperview().offset(16) make.left.equalToSuperview().offset(16)
make.width.equalToSuperview().offset(-32) make.width.equalToSuperview().offset(-32)
make.height.equalTo(self.width - 32) make.height.equalTo(self.width - 32)
...@@ -230,6 +241,6 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -230,6 +241,6 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
titleLabel.sizeToFit() // titleLabel.sizeToFit()
} }
} }
...@@ -65,7 +65,7 @@ class ImageSeletedCollectionCell:UICollectionViewCell { ...@@ -65,7 +65,7 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
// 获取当前版本的照片或视频 // 获取当前版本的照片或视频
options.version = .current options.version = .current
// 尽可能快地提供结果 // 尽可能快地提供结果
options.deliveryMode = .opportunistic options.deliveryMode = .highQualityFormat
// 允许从iCloud请求 // 允许从iCloud请求
options.isNetworkAccessAllowed = true options.isNetworkAccessAllowed = true
// 异步请求 // 异步请求
......
...@@ -30,6 +30,8 @@ class PMShowImgVideoController: BaseViewController { ...@@ -30,6 +30,8 @@ class PMShowImgVideoController: BaseViewController {
var currentIdx = 0 var currentIdx = 0
var url : URL?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
} }
...@@ -183,22 +185,10 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -183,22 +185,10 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
// 相似视频 // 相似视频
if collectionView == MaxCollection { if collectionView == MaxCollection {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowVideoCellID, for: indexPath) as! PMShowVideoCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowVideoCellID, for: indexPath) as! PMShowVideoCell
// 获取相似视频的URL cell.homeResouceUrl = self.url
DispatchQueue.global().async { // 表示这个是视频
self.getVideoURLFromLocalIdentifier(localIdentifier: self.homeDataSource![indexPath.row].id!.localIdentifier) {[weak self] url, error in cell.type = 1
guard self != nil else {return} cell.reload()
if let error = error {
print("获取视频 URL 时出错: \(error.localizedDescription)")
} else if let url = url {
DispatchQueue.main.async {
cell.homeResouceUrl = url
// 表示这个是视频
cell.type = 1
cell.reload()
}
}
}
}
return cell return cell
}else{ }else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
......
...@@ -132,7 +132,7 @@ class SettingViewHeaderCell : UITableViewCell { ...@@ -132,7 +132,7 @@ class SettingViewHeaderCell : UITableViewCell {
@objc func leanMoreBtnClick() { @objc func leanMoreBtnClick() {
HomeNoAdsViewController.show { HomePayViewController.show {
} }
} }
......
...@@ -136,53 +136,75 @@ class PhotoAndVideoMananger { ...@@ -136,53 +136,75 @@ class PhotoAndVideoMananger {
func fetchAllFile(propress:@escaping (Int,Double) -> Void,completion: @escaping (Double,Int) -> Void) { func fetchAllFile(propress:@escaping (Int,Double) -> Void,completion: @escaping (Double,Int) -> Void) {
if (self.allAssets.count == 0 ) { // if (self.allAssets.count == 0 ) {
//
let fetchOptions = PHFetchOptions() // let fetchOptions = PHFetchOptions()
//
let photoAllAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions) // let photoAllAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
//
let videoAllAssets = PHAsset.fetchAssets(with: .video, options: fetchOptions) // let videoAllAssets = PHAsset.fetchAssets(with: .video, options: fetchOptions)
//
let photoAssetsArray = photoAllAssets.objects(at: IndexSet(0..<photoAllAssets.count)) // let photoAssetsArray = photoAllAssets.objects(at: IndexSet(0..<photoAllAssets.count))
//
let videoAssetsArray = videoAllAssets.objects(at: IndexSet(0..<videoAllAssets.count)) // let videoAssetsArray = videoAllAssets.objects(at: IndexSet(0..<videoAllAssets.count))
//
let combinedArray = photoAssetsArray + videoAssetsArray // let combinedArray = photoAssetsArray + videoAssetsArray
//
DispatchQueue.global().async {[weak self] in // DispatchQueue.global().async {[weak self] in
//
guard let self = self else { return } // guard let self = self else { return }
// 计算总大小 // // 计算总大小
self.calculateTotalSize(of: combinedArray,progress: { fileSiez, index in // self.calculateTotalSize(of: combinedArray,progress: { fileSiez, index in
propress(index,Double(fileSiez)) // propress(index,Double(fileSiez))
}, completion: { fileSize,index in // }, completion: { fileSize,index in
completion(Double(fileSize),index) // completion(Double(fileSize),index)
}) // })
//
} // }
//
}else { // }else {
//
//
// let combinedArray = self.allAssets
//
// DispatchQueue.global().async {[weak self] in
//
// guard let self = self else { return }
// // 计算总大小
// self.calculateTotalSize(of: combinedArray,progress: { fileSiez, index in
//
// propress(index,Double(fileSiez))
// }, completion: { fileSize,index in
// completion(Double(fileSize),index)
// })
//
// }
// }
let fetchOptions = PHFetchOptions()
let photoAllAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
let videoAllAssets = PHAsset.fetchAssets(with: .video, options: fetchOptions)
let photoAssetsArray = photoAllAssets.objects(at: IndexSet(0..<photoAllAssets.count))
let videoAssetsArray = videoAllAssets.objects(at: IndexSet(0..<videoAllAssets.count))
let combinedArray = photoAssetsArray + videoAssetsArray
DispatchQueue.global().async {[weak self] in
let combinedArray = self.allAssets guard let self = self else { return }
// 计算总大小
self.calculateTotalSize(of: combinedArray,progress: { fileSiez, index in
propress(index,Double(fileSiez))
}, completion: { fileSize,index in
completion(Double(fileSize),index)
})
DispatchQueue.global().async {[weak self] in
guard let self = self else { return }
// 计算总大小
self.calculateTotalSize(of: combinedArray,progress: { fileSiez, index in
propress(index,Double(fileSiez))
}, completion: { fileSize,index in
completion(Double(fileSize),index)
})
}
} }
} }
func fetXSOther( resulte:@escaping ([[PHAsset]]) -> Void) { func fetXSOther( resulte:@escaping ([[PHAsset]]) -> Void) {
...@@ -329,6 +351,28 @@ class PhotoAndVideoMananger { ...@@ -329,6 +351,28 @@ class PhotoAndVideoMananger {
return image return image
} }
/// 根据id获取图片
/// - Parameter identifier: 资源id
/// - Returns: 图片
func getImageByIdent(identifier:String) async -> UIImage? {
let imageManager = PHImageManager.default()
let targetSize = CGSize(width: 400, height: 400)
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
return await withCheckedContinuation { continuation in
var hasResumed = false
if let asset = getPHAsssetwithID(ids: [identifier]){
imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { result, _ in
guard !hasResumed else { return }
hasResumed = true
continuation.resume(returning: result)
}
}
}
}
func groupSimilarAssets(from assets: [PHAsset]) -> [[PHAsset]] { func groupSimilarAssets(from assets: [PHAsset]) -> [[PHAsset]] {
var groupedAssets: [[PHAsset]] = [] var groupedAssets: [[PHAsset]] = []
var visitedAssets = Set<String>() // 记录已处理的 asset ID var visitedAssets = Set<String>() // 记录已处理的 asset ID
...@@ -888,7 +932,7 @@ class PhotoAndVideoMananger { ...@@ -888,7 +932,7 @@ class PhotoAndVideoMananger {
// 获取当前版本的照片或视频 // 获取当前版本的照片或视频
options.version = .current options.version = .current
// 尽可能快地提供结果 // 尽可能快地提供结果
options.deliveryMode = .opportunistic options.deliveryMode = .highQualityFormat
// 允许从iCloud请求 // 允许从iCloud请求
options.isNetworkAccessAllowed = true options.isNetworkAccessAllowed = true
// 异步请求 // 异步请求
......
//
// StorageManager.swift
// PhoneManager
//
// Created by edy on 2025/4/28.
//
import Foundation
import Photos
import Darwin
class StorageManager {
static let manager : StorageManager = StorageManager()
// 获取照片内存
func getPhotoResourceMemory() async -> Double {
return await withCheckedContinuation { continuation in
PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
switch status {
case .authorized:
Task {
var totalSize: UInt64 = 0
let options = PHFetchOptions()
let fetchResult = PHAsset.fetchAssets(with: .image, options: options)
fetchResult.enumerateObjects { (asset, _, _) in
let resources = PHAssetResource.assetResources(for: asset)
for resource in resources {
if let fileSize = resource.value(forKey: "fileSize") as? UInt64 {
totalSize += fileSize
}
}
}
let result = Double(totalSize)
continuation.resume(returning: result)
}
case .denied, .restricted:
print("没有权限访问照片库")
continuation.resume(returning: 0)
case .notDetermined, .limited:
print("照片库权限未确定或受限")
continuation.resume(returning: 0)
@unknown default:
print("未知的照片库权限状态")
continuation.resume(returning: 0)
}
}
}
}
}
...@@ -55,4 +55,35 @@ extension UIColor { ...@@ -55,4 +55,35 @@ extension UIColor {
return UIColor(red: red, green: green, blue: blue, alpha: 1.0) return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
} }
convenience init?(hex: String) {
var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
var rgb: UInt64 = 0
var r: CGFloat = 0.0
var g: CGFloat = 0.0
var b: CGFloat = 0.0
var a: CGFloat = 1.0
let length = hexSanitized.count
guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }
if length == 6 {
r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
b = CGFloat(rgb & 0x0000FF) / 255.0
} else if length == 8 {
r = CGFloat((rgb & 0xFF000000) >> 24) / 255.0
g = CGFloat((rgb & 0x00FF0000) >> 16) / 255.0
b = CGFloat((rgb & 0x0000FF00) >> 8) / 255.0
a = CGFloat(rgb & 0x000000FF) / 255.0
} else {
return nil
}
self.init(red: r, green: g, blue: b, alpha: a)
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment