Commit 2cf5ae73 authored by shenyong's avatar shenyong

Merge branch 'Advertisement' of gitlab.huolea.com:ShuMing/phonemanager into Advertisement

# Conflicts:
#	PhoneManager/Class/Page/Contact/View/Common/AlertView/BaseAlertView.swift
#	PhoneManager/Class/Page/Home/Controller/PhotoSlideViewController.swift
#	PhoneManager/Class/Page/Home/View/AnchorRotatableView.swift
#	PhoneManager/Class/Page/Secret/PMShowImgVideoController.swift
#	PhoneManager/Class/Page/Widget/View/WidgetBornThenView.swift
parents 1a939e25 52802867
...@@ -77,6 +77,13 @@ ...@@ -77,6 +77,13 @@
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
widgetLockSreenView.swift,
);
target = EB388E5A2D8A61A800629B0D /* PhoneManager */;
};
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */ = { 0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet; isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = ( membershipExceptions = (
...@@ -104,6 +111,7 @@ ...@@ -104,6 +111,7 @@
0496DEF52D9E3F58005B2834 /* widget */ = { 0496DEF52D9E3F58005B2834 /* widget */ = {
isa = PBXFileSystemSynchronizedRootGroup; isa = PBXFileSystemSynchronizedRootGroup;
exceptions = ( exceptions = (
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */,
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */, 0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */,
); );
path = widget; path = widget;
...@@ -580,10 +588,12 @@ ...@@ -580,10 +588,12 @@
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PhoneManager/Info.plist; INFOPLIST_FILE = PhoneManager/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature"; INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature";
INFOPLIST_KEY_NSContactsUsageDescription = "Phone Manager needs access to your contacts to find and merge duplicate contacts";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content"; INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature"; INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSUserTrackingUsageDescription = "We need your permission to track your usage habits in order to provide a more personalized advertising experience";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
...@@ -626,10 +636,12 @@ ...@@ -626,10 +636,12 @@
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PhoneManager/Info.plist; INFOPLIST_FILE = PhoneManager/Info.plist;
INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature"; INFOPLIST_KEY_NSCameraUsageDescription = "We need to obtain your camera permission in order to save the photos you take in the private album feature";
INFOPLIST_KEY_NSContactsUsageDescription = "Phone Manager needs access to your contacts to find and merge duplicate contacts";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content"; INFOPLIST_KEY_NSLocalNetworkUsageDescription = "We need to access the network to load content";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature"; INFOPLIST_KEY_NSMicrophoneUsageDescription = "We need to obtain your microphone permission in order to use it when shooting videos in the private album feature";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "We need to access your album in order to find the photos you want to change and update them";
INFOPLIST_KEY_NSUserTrackingUsageDescription = "We need your permission to track your usage habits in order to provide a more personalized advertising experience";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main; INFOPLIST_KEY_UIMainStoryboardFile = Main;
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "button_switch_off.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "button_switch_off@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_switch_off@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "button_switch_on.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "button_switch_on@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "button_switch_on@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "emailSmall.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_delete_duplicates.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_delete_duplicates@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_delete_duplicates@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_sel_com.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_sel_com@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_sel_com@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_switch_email.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_switch_email@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_switch_email@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_unsel_com.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_unsel_com@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_unsel_com@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_unsel_com_red.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_unsel_com_red@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_unsel_com_red@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_add.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_add@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_add@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_left_setting_grey.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_left_setting_grey@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_left_setting_grey@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "img_email.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_email@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_email@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// //
import Foundation import Foundation
import Contacts
class ContactBackupDetailViewController : BaseViewController { class ContactBackupDetailViewController : BaseViewController {
...@@ -157,6 +158,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -157,6 +158,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
return 20 return 20
} }
func setupCustomIndexView() { func setupCustomIndexView() {
customIndexView = nil
customIndexView = UIStackView() customIndexView = UIStackView()
customIndexView.axis = .vertical customIndexView.axis = .vertical
customIndexView.alignment = .center customIndexView.alignment = .center
...@@ -166,9 +168,9 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -166,9 +168,9 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
self.customIndexView.snp.makeConstraints { make in self.customIndexView.snp.makeConstraints { make in
make.left.equalTo(self.tableView.snp.right).offset(0) make.left.equalTo(self.tableView.snp.right).offset(0)
make.top.equalTo(self.subTitleLabel.snp.bottom).offset(77) make.centerY.equalTo(self.view.snp.centerY)
make.width.equalTo(15 * RScreenW()) make.width.equalTo(15 * RScreenW())
make.height.equalTo(354) make.height.equalTo(self.sectionTitles.count * (14 + 2))
} }
for (index, section) in sectionTitles.enumerated() { for (index, section) in sectionTitles.enumerated() {
...@@ -193,8 +195,17 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -193,8 +195,17 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
} }
} }
func scrollViewDidScroll(_ scrollView: UIScrollView) { func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: tableView.contentOffset, size: tableView.bounds.size) // 获取可见区域的中心点,稍微向下偏移以更准确地检测当前可见的 section
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.minY) let visibleRect = CGRect(
origin: tableView.contentOffset,
size: tableView.bounds.size
)
// 将检测点从顶部边缘下移一些,例如下移10%的可见区域高度
let adjustedY = visibleRect.minY + visibleRect.height * 0.1
let visiblePoint = CGPoint(x: visibleRect.midX, y: adjustedY)
// 获取可见区域最顶部的单元格的 indexPath
if let visibleIndexPath = tableView.indexPathForRow(at: visiblePoint) { if let visibleIndexPath = tableView.indexPathForRow(at: visiblePoint) {
let newIndex = visibleIndexPath.section let newIndex = visibleIndexPath.section
if newIndex != selectedIndex { if newIndex != selectedIndex {
...@@ -218,7 +229,6 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -218,7 +229,6 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
let indexPath = IndexPath(row: 0, section: index) let indexPath = IndexPath(row: 0, section: index)
tableView.scrollToRow(at: indexPath, at: .top, animated: true) tableView.scrollToRow(at: indexPath, at: .top, animated: true)
selectedIndex = index selectedIndex = index
updateIndexStyles()
} }
} }
......
...@@ -12,6 +12,7 @@ class CustomContactViewController: CNContactViewController { ...@@ -12,6 +12,7 @@ class CustomContactViewController: CNContactViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.allowsEditing = false
setupCancelButton() setupCancelButton()
} }
......
...@@ -153,7 +153,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -153,7 +153,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
}else{ }else{
self.selectedContacts.removeAll(where: { $0.identifier == model.identifier }) self.selectedContacts.removeAll(where: { $0.identifier == model.identifier })
} }
DispatchQueue.main.async { DispatchQueue.main.async {
// 判断button是否显示 // 判断button是否显示
if self.selectedContacts.count > 0 { if self.selectedContacts.count > 0 {
...@@ -205,9 +205,9 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -205,9 +205,9 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
self.customIndexView.snp.makeConstraints { make in self.customIndexView.snp.makeConstraints { make in
make.left.equalTo(self.tableView.snp.right).offset(0) make.left.equalTo(self.tableView.snp.right).offset(0)
make.top.equalTo(self.subTitleLabel.snp.bottom).offset(77) make.centerY.equalTo(self.snp.centerY)
make.width.equalTo(15 * RScreenW()) make.width.equalTo(15 * RScreenW())
make.height.equalTo(354) make.height.equalTo(self.sectionTitles.count * (14 + 2))
} }
for (index, section) in sectionTitles.enumerated() { for (index, section) in sectionTitles.enumerated() {
...@@ -232,8 +232,17 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -232,8 +232,17 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
} }
} }
func scrollViewDidScroll(_ scrollView: UIScrollView) { func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(origin: tableView.contentOffset, size: tableView.bounds.size) // 获取可见区域的中心点,稍微向下偏移以更准确地检测当前可见的 section
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.minY) let visibleRect = CGRect(
origin: tableView.contentOffset,
size: tableView.bounds.size
)
// 将检测点从顶部边缘下移一些,例如下移10%的可见区域高度
let adjustedY = visibleRect.minY + visibleRect.height * 0.1
let visiblePoint = CGPoint(x: visibleRect.midX, y: adjustedY)
// 获取可见区域最顶部的单元格的 indexPath
if let visibleIndexPath = tableView.indexPathForRow(at: visiblePoint) { if let visibleIndexPath = tableView.indexPathForRow(at: visiblePoint) {
let newIndex = visibleIndexPath.section let newIndex = visibleIndexPath.section
if newIndex != selectedIndex { if newIndex != selectedIndex {
...@@ -257,7 +266,6 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -257,7 +266,6 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
let indexPath = IndexPath(row: 0, section: index) let indexPath = IndexPath(row: 0, section: index)
tableView.scrollToRow(at: indexPath, at: .top, animated: true) tableView.scrollToRow(at: indexPath, at: .top, animated: true)
selectedIndex = index selectedIndex = index
updateIndexStyles()
} }
} }
...@@ -271,12 +279,32 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -271,12 +279,32 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
guard let self else {return} guard let self else {return}
if isSure { if isSure {
backupContactsByselect { backupContactsByselect {
// 备份完成后删除 // 删除之前弹出是否真的需要删除
self.deleteContacts() let alertVc = ContactDeleteAlertView()
alertVc.frame = (self.responderViewController()?.view.bounds)!
cWindow?.addSubview(alertVc)
alertVc.sureCallBack = {[weak self] isSure in
guard let self else {return}
if isSure {
// 提示是否删除
self.deleteContacts()
}
}
} }
}else{ }else{
// 如果不备份,直接删除 // 删除之前弹出是否真的需要删除
self.deleteContacts() let alertVc = ContactDeleteAlertView()
alertVc.frame = (self.responderViewController()?.view.bounds)!
cWindow?.addSubview(alertVc)
alertVc.sureCallBack = {[weak self] isSure in
guard let self else {return}
if isSure {
// 提示是否删除
self.deleteContacts()
}
}
} }
} }
} }
...@@ -284,15 +312,15 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -284,15 +312,15 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
func backupContactsByselect(success:@escaping()->Void){ func backupContactsByselect(success:@escaping()->Void){
// 开始备份联系人,备份完成提示 // 开始备份联系人,备份完成提示
let vm = BackupViewModel() let vm = BackupViewModel()
vm.backupPartialContacts(self.selectedContacts) { finised, error in vm.backupPartialContacts(self.dataSourceModel) { finised, error in
if finised { if finised {
// 备份成功 // 备份成功
success()
DispatchQueue.main.async { DispatchQueue.main.async {
let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!) let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc) cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview() buAlertVc.removeFromSuperview()
success()
} }
} }
}else{ }else{
......
...@@ -99,7 +99,9 @@ class BackupViewModel { ...@@ -99,7 +99,9 @@ class BackupViewModel {
decoder.dateDecodingStrategy = .iso8601 decoder.dateDecodingStrategy = .iso8601
// 尝试解码为 BackupInfoModel 数组 // 尝试解码为 BackupInfoModel 数组
let backupInfos = try decoder.decode([BackupInfoModel].self, from: jsonData) let backupInfos = try decoder.decode([BackupInfoModel].self, from: jsonData)
completion(backupInfos, nil) // 根据时间倒序下
let sortedModels = backupInfos.sorted { $0.backupTime > $1.backupTime }
completion(sortedModels, nil)
} catch { } catch {
Print(error.localizedDescription) Print(error.localizedDescription)
completion(nil, error) completion(nil, error)
......
//
// BaseAlertView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import Foundation
import SnapKit
class BaseAlertView : UIView {
private var bottomConstraint: Constraint?
override init(frame: CGRect) {
super.init(frame: frame)
// 先显示背景,然后延迟显示弹框
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
UIView.animate(withDuration: 0.1) {
// 更新约束
self.bottomConstraint?.update(offset: 0)
self.layoutIfNeeded()
}
}
}
override func removeFromSuperview() {
UIView.animate(withDuration: 0.2) {
// 更新约束
self.backgroundColor = .clear
self.bottomConstraint?.update(offset: self.height)
self.layoutIfNeeded()
}completion: { _ in
super.removeFromSuperview()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
...@@ -13,7 +13,7 @@ class ContactBacRestoreAlertView : UIView { ...@@ -13,7 +13,7 @@ class ContactBacRestoreAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -12,7 +12,7 @@ class ContactBackUpCompletedAlertView : UIView { ...@@ -12,7 +12,7 @@ class ContactBackUpCompletedAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -14,7 +14,7 @@ class ContactBackUpDeleteCompletedAlertView : UIView { ...@@ -14,7 +14,7 @@ class ContactBackUpDeleteCompletedAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -11,7 +11,7 @@ class ContactBackUpNoDataAlertView : UIView { ...@@ -11,7 +11,7 @@ class ContactBackUpNoDataAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -8,12 +8,13 @@ ...@@ -8,12 +8,13 @@
import Foundation import Foundation
class ContactBackupAlertView : UIView { class ContactBackupAlertView : UIView {
var sureCallBack: (Bool)->Void = {isSure in } var sureCallBack: (Bool)->Void = {isSure in }
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
...@@ -124,7 +125,6 @@ class ContactBackupAlertView : UIView { ...@@ -124,7 +125,6 @@ class ContactBackupAlertView : UIView {
make.height.equalTo(46) make.height.equalTo(46)
} }
} }
@objc private func dismissAlert() { @objc private func dismissAlert() {
......
...@@ -13,7 +13,7 @@ class ContactDeleteAlertView : UIView { ...@@ -13,7 +13,7 @@ class ContactDeleteAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -13,7 +13,7 @@ class ContactMergeAlertView : UIView { ...@@ -13,7 +13,7 @@ class ContactMergeAlertView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -11,7 +11,7 @@ class ContactRestoreSuccessView : UIView { ...@@ -11,7 +11,7 @@ class ContactRestoreSuccessView : UIView {
// 懒加载背景视图 // 懒加载背景视图
private lazy var backgroundView: UIView = { private lazy var backgroundView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.4000)
return view return view
}() }()
......
...@@ -39,6 +39,19 @@ class HomeInfoViewController:BaseViewController { ...@@ -39,6 +39,19 @@ class HomeInfoViewController:BaseViewController {
let sview:HomeInfoView = HomeInfoView(frame: CGRect(x: 0, y: cY, width: view.width, height: view.height - cY), ids: ids,type: self.type,titleText: titleText) let sview:HomeInfoView = HomeInfoView(frame: CGRect(x: 0, y: cY, width: view.width, height: view.height - cY), ids: ids,type: self.type,titleText: titleText)
sview.titleShowHideCallBack = {[weak self] isShow in
guard let self else {return}
if isShow && self.titleLabel.alpha == 0 {
UIView.animate(withDuration: 0.1) {
self.titleLabel.alpha = 1
}
}else if isShow == false && self.titleLabel.alpha == 1{
UIView.animate(withDuration: 0.1) {
self.titleLabel.alpha = 0
}
}
}
sview.callBack = {[weak self] isSeleted in sview.callBack = {[weak self] isSeleted in
guard let self else {return} guard let self else {return}
...@@ -275,6 +288,16 @@ class HomeInfoViewController:BaseViewController { ...@@ -275,6 +288,16 @@ class HomeInfoViewController:BaseViewController {
return label return label
}() }()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 14, weight: .bold)
label.textColor = UIColor.colorWithHex(hexStr: black3Color)
label.text = titleText
label.alpha = 0
label.sizeToFit()
return label
}()
var ids: [[AssetModel]]? var ids: [[AssetModel]]?
var titleText : String? var titleText : String?
...@@ -373,6 +396,10 @@ class HomeInfoViewController:BaseViewController { ...@@ -373,6 +396,10 @@ class HomeInfoViewController:BaseViewController {
titleView.addSubview(seletedAllBtn) titleView.addSubview(seletedAllBtn)
titleLabel.x = titleView.backBtn.width + titleView.backBtn.x + 10
titleLabel.centerY = navCenterY
titleView.addSubview(titleLabel)
view.addSubview(tablewView) view.addSubview(tablewView)
view.addSubview(self.defaultImageView) view.addSubview(self.defaultImageView)
self.defaultImageView.snp.makeConstraints { make in self.defaultImageView.snp.makeConstraints { make in
......
...@@ -62,7 +62,14 @@ class HomeViewController:BaseViewController { ...@@ -62,7 +62,14 @@ class HomeViewController:BaseViewController {
case 3 : case 3 :
DispatchQueue.main.async {[weak self] in DispatchQueue.main.async {[weak self] in
guard let self else {return} guard let self else {return}
//FIXME: 是否登录了谷歌邮箱
if false {
let vc:EmailCleanController = EmailCleanController()
self.navigationController?.pushViewController(vc, animated: true)
}else{
let vc:EmailLoginController = EmailLoginController()
self.navigationController?.pushViewController(vc, animated: true)
}
} }
break break
case 4 : case 4 :
...@@ -142,9 +149,9 @@ class HomeViewController:BaseViewController { ...@@ -142,9 +149,9 @@ class HomeViewController:BaseViewController {
let homeSimilarImageResourceUpdate = Notification.Name("HomeSimilarImageResourceUpdate") let homeSimilarImageResourceUpdate = Notification.Name("HomeSimilarImageResourceUpdate")
NotificationCenter.default.addObserver(self, selector: #selector(handleHomeSimilarImageResourceUpdate(_:)), name: homeSimilarImageResourceUpdate, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleHomeSimilarImageResourceUpdate(_:)), name: homeSimilarImageResourceUpdate, object: nil)
homeView = HomeView(frame: view.bounds) homeView = HomeView(frame: view.bounds)
homeView?.y = cWindow?.safeAreaInsets.top ?? 20
homeView?.height = view.height - (cWindow?.safeAreaInsets.top ?? 20)
homeView?.titleCallBack = {[weak self] model,type in homeView?.titleCallBack = {[weak self] model,type in
guard let self else {return} guard let self else {return}
......
//
// PhotoSlideViewController.swift
// AIClean
//
// Created by 赵前 on 2025/5/10.
//
import UIKit
class PhotoSlideViewController: BaseViewController {
// 按钮竖直方向偏移量
let buttonVerticalOffset : CGFloat = 20
// MARK: - 数据与视图
var dataSource: [AssetModel] = []
private var currentIndex = 0
private var nextIndex = 0
private lazy var topView: AnchorRotatableView = {
let view = AnchorRotatableView()
view.configure(anchorPoint: CGPoint(x: 0.5, y: 0.5))
return view
}()
private lazy var bottomView: AnchorRotatableView = {
let view = AnchorRotatableView()
view.configure(anchorPoint: CGPoint(x: 0.5, y: 0.5))
return view
}()
private let leftButton: UIButton = {
let btn = UIButton()
btn.setTitle("Left", for: .normal)
btn.backgroundColor = .systemBlue.withAlphaComponent(0.8)
btn.alpha = 0
btn.layer.cornerRadius = 8
return btn
}()
private let rightButton: UIButton = {
let btn = UIButton()
btn.setTitle("Right", for: .normal)
btn.backgroundColor = .systemBlue.withAlphaComponent(0.8)
btn.alpha = 0
btn.layer.cornerRadius = 8
return btn
}()
// MARK: - 生命周期
override func viewDidLoad() {
super.viewDidLoad()
setupData()
setupViews()
setupGestures()
}
// MARK: - 初始化方法
private func setupData() {
currentIndex = dataSource.count - 1
updateCardContent()
}
private func setupViews() {
// 卡片视图
view.addSubview(bottomView)
view.addSubview(topView)
topView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(100)
make.bottom.equalToSuperview().offset(-100)
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().offset(-20)
}
bottomView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(100)
make.bottom.equalToSuperview().offset(-100)
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().offset(-20)
}
// 操作按钮
view.addSubview(leftButton)
view.addSubview(rightButton)
resetButtonsPosition()
}
private func resetButtonsPosition() {
leftButton.snp.makeConstraints { make in
make.height.width.equalTo(50)
make.centerX.equalTo(100)
make.centerY.equalTo(100)
}
rightButton.snp.makeConstraints { make in
make.height.width.equalTo(50)
make.centerX.equalTo(45)
make.centerY.equalTo(100)
}
}
private func setupGestures() {
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
topView.addGestureRecognizer(pan)
}
// MARK: - 手势处理
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: view)
let velocity = gesture.velocity(in: view)
switch gesture.state {
case .began:
break
case .changed:
let progress = translation.x * 2 / topView.bounds.size.width
updateCardTransform(translation: translation)
updateButtons(progress: progress,translation: translation)
case .ended, .cancelled:
endDragAnimation(velocity: velocity)
default: break
}
}
// MARK: - 新手势绑定
private func setupGesturesForNewTopView() {
// 移除旧手势
topView.gestureRecognizers?.forEach { topView.removeGestureRecognizer($0) }
// 添加新手势
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
pan.delegate = self
topView.addGestureRecognizer(pan)
// 确保视图层级
view.bringSubviewToFront(bottomView)
view.bringSubviewToFront(topView)
view.bringSubviewToFront(leftButton)
view.bringSubviewToFront(rightButton)
}
private func updateCardTransform(translation: CGPoint) {
let progress = translation.x / topView.bounds.size.width
// 角度
let rotationAngle = topView.maxRotationAngle * progress
topView.transform = CGAffineTransform(translationX: translation.x, y: 0)
.rotated(by: rotationAngle)
}
private func updateButtons(progress: CGFloat,translation:CGPoint) {
// 计算X轴坐标 向右的时候progress为正数
if progress > 0 {
leftButton.isHidden = false
rightButton.isHidden = true
}else {
leftButton.isHidden = true
rightButton.isHidden = false
}
let leftX = min(translation.x + 25 , topView.bounds.size.width / 2)
let rightX = max(360 - abs(translation.x) , topView.bounds.size.width / 2)
// 计算Y轴坐标
let verY = min(100 + buttonVerticalOffset,100 + buttonVerticalOffset * abs(progress))
UIView.animate(withDuration: 0.1) {
self.leftButton.center = CGPoint(
x: leftX,
y:verY
)
self.rightButton.center = CGPoint(
x: rightX,
y: verY
)
// 渐变效果
let alpha = abs(progress)
self.leftButton.alpha = alpha
self.rightButton.alpha = alpha
}
}
private func endDragAnimation(velocity: CGPoint) {
let translation = topView.transform.tx
let shouldDisappear = abs(translation) > topView.bounds.size.width/2 || abs(velocity.x) > 800
self.leftButton.alpha = 0
self.rightButton.alpha = 0
shouldDisappear ? animateCardDisappear() : resetCardPosition()
}
private func animateCardDisappear() {
let direction: UISwipeGestureRecognizer.Direction = topView.transform.tx > 0 ? .right : .left
UIView.animate(withDuration: 0.4) {
let targetX = direction == .right ? self.view.bounds.width * 1.5 : -self.view.bounds.width * 1.5
self.topView.transform = CGAffineTransform(translationX: targetX, y: 0)
self.topView.alpha = 0
} completion: { _ in
self.handleCardDisappeared()
}
}
private func resetCardPosition() {
UIView.animate(withDuration: 0.6,
delay: 0,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 0.5) {
self.topView.transform = .identity
self.resetButtonsPosition()
}
}
// MARK: - 数据更新
private func updateCardContent() {
guard dataSource.indices.contains(currentIndex) else { return }
// 获取资源
topView.imageView.image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: dataSource[currentIndex].localIdentifier)
// 预加载下一张
let next = currentIndex - 1 >= 0 ? currentIndex - 1 : dataSource.count - 1
bottomView.imageView.image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: dataSource[next].localIdentifier)
}
private func handleCardDisappeared() {
// 更新索引(循环逻辑)
currentIndex = currentIndex - 1 >= 0 ? currentIndex - 1 : dataSource.count - 1
// 交换视图层级
let temp = topView
topView = bottomView
bottomView = temp
// 重置视图状态
topView.transform = .identity
topView.alpha = 1
topView.isUserInteractionEnabled = true
// 重新绑定新手势
setupGesturesForNewTopView()
resetButtonsPosition()
updateCardContent()
// 重置底层视图位置
bottomView.snp.remakeConstraints { make in
make.top.equalToSuperview().offset(100)
make.bottom.equalToSuperview().offset(-100)
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().offset(-20)
}
bottomView.transform = .identity
bottomView.alpha = 1
}
}
extension PhotoSlideViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
//
// AnchorRotatableView.swift
// AIClean
//
// Created by 赵前 on 2025/5/10.
//
import Foundation
import UIKit
class AnchorRotatableView: UIView {
var maxRotationAngle: CGFloat = .pi/12
lazy var imageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
backgroundColor = .gray
layer.cornerRadius = 12
clipsToBounds = true
addSubview(imageView)
imageView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}
}
extension AnchorRotatableView {
func configure(anchorPoint: CGPoint) {
layer.anchorPoint = anchorPoint
}
}
...@@ -32,25 +32,25 @@ class HomeCollectionViewHeader : UICollectionReusableView { ...@@ -32,25 +32,25 @@ class HomeCollectionViewHeader : UICollectionReusableView {
return view return view
}() }()
private lazy var tipLabel:UILabel = { // private lazy var tipLabel:UILabel = {
let label = UILabel() // let label = UILabel()
label.numberOfLines = 0 // 支持多行 // label.numberOfLines = 0 // 支持多行
return label // return label
}() // }()
private func setupUI() { private func setupUI() {
// 文本 // 文本
self.addSubview(self.tipLabel) // self.addSubview(self.tipLabel)
self.tipLabel.snp.makeConstraints { make in // self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8) // make.left.equalToSuperview().offset(8)
make.top.equalToSuperview().offset(4) // make.top.equalToSuperview().offset(44)
make.height.equalTo(17) // make.height.equalTo(17)
} // }
self.addSubview(self.progressBar) self.addSubview(self.progressBar)
self.progressBar.snp.makeConstraints { make in self.progressBar.snp.makeConstraints { make in
make.top.equalTo(self.tipLabel.snp.bottom).offset(12) make.top.equalTo(self.snp.top).offset(12 + 44 + 17)
make.width.equalToSuperview().offset(-16) make.width.equalToSuperview().offset(-16)
make.height.equalTo(31) make.height.equalTo(31)
make.left.equalToSuperview().offset(8) make.left.equalToSuperview().offset(8)
...@@ -90,7 +90,7 @@ extension HomeCollectionViewHeader{ ...@@ -90,7 +90,7 @@ extension HomeCollectionViewHeader{
/// - Parameters: /// - Parameters:
/// - count: 文件数量 /// - count: 文件数量
/// - fileSize: 文件总大小 /// - fileSize: 文件总大小
func setFileAndCount(count:Int,fileSize:Double) { func setFileAndCount(count:Int,fileSize:Double) -> NSMutableAttributedString {
let countString = "\(count)" let countString = "\(count)"
let fileSizeString = formatFileSize(fileSize) let fileSizeString = formatFileSize(fileSize)
...@@ -122,9 +122,9 @@ extension HomeCollectionViewHeader{ ...@@ -122,9 +122,9 @@ extension HomeCollectionViewHeader{
.foregroundColor: UIColor.colorWithHex(hexStr: black6Color) .foregroundColor: UIColor.colorWithHex(hexStr: black6Color)
], range: nsRange2) ], range: nsRange2)
} }
return attributedText
// 将 attributedText 赋值给 UILabel // 将 attributedText 赋值给 UILabel
self.tipLabel.attributedText = attributedText // self.tipLabel.attributedText = attributedText
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import UIKit import UIKit
class HomeInfoView :UIView{ class HomeInfoView :UIView {
var ids:[[AssetModel]]? var ids:[[AssetModel]]?
...@@ -20,10 +20,11 @@ class HomeInfoView :UIView{ ...@@ -20,10 +20,11 @@ class HomeInfoView :UIView{
var callBack:callBack<Any> = {text in} var callBack:callBack<Any> = {text in}
var deleteCallBack:callBack<[AssetModel]> = {array in } var deleteCallBack:callBack<[AssetModel]> = {array in }
var titleShowHideCallBack:callBack<Bool> = {isShow in}
lazy var tableView:UITableView = { lazy var tableView:UITableView = {
let sview:UITableView = UITableView.init(frame: bounds) let sview:UITableView = UITableView(frame: bounds, style: .grouped) //UITableView.init(frame: bounds )
sview.backgroundColor = .clear sview.backgroundColor = .clear
sview.separatorStyle = .none sview.separatorStyle = .none
sview.showsVerticalScrollIndicator = false sview.showsVerticalScrollIndicator = false
...@@ -35,16 +36,13 @@ class HomeInfoView :UIView{ ...@@ -35,16 +36,13 @@ class HomeInfoView :UIView{
sview.sectionHeaderTopPadding = 0 sview.sectionHeaderTopPadding = 0
} }
return sview return sview
}() }()
lazy var headerView:HomeInfoTitleView = { lazy var headerView:HomeInfoTitleView = {
let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84)) let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84))
sview.titleLabel.text = self.titleText sview.titleLabel.text = self.titleText
tableView.addSubview(sview)
return sview return sview
}() }()
...@@ -164,6 +162,7 @@ class HomeInfoView :UIView{ ...@@ -164,6 +162,7 @@ class HomeInfoView :UIView{
for section in 0..<self.tableView.numberOfSections { for section in 0..<self.tableView.numberOfSections {
for item in 0..<self.tableView.numberOfRows(inSection: section) { for item in 0..<self.tableView.numberOfRows(inSection: section) {
if let cell = self.tableView.cellForRow(at: IndexPath(row: item, section: section)) as? HomeInfoTableViewCell { if let cell = self.tableView.cellForRow(at: IndexPath(row: item, section: section)) as? HomeInfoTableViewCell {
cell.checkSeletedAll()
UIView.transition(with: cell.collectionView!, duration: 0.3, options: .transitionCrossDissolve, animations: { UIView.transition(with: cell.collectionView!, duration: 0.3, options: .transitionCrossDissolve, animations: {
cell.collectionView?.reloadData() cell.collectionView?.reloadData()
}, completion: nil) }, completion: nil)
...@@ -182,7 +181,6 @@ class HomeInfoView :UIView{ ...@@ -182,7 +181,6 @@ class HomeInfoView :UIView{
} }
} }
} }
return selectedArray return selectedArray
} }
...@@ -255,6 +253,20 @@ class HomeInfoView :UIView{ ...@@ -255,6 +253,20 @@ class HomeInfoView :UIView{
extension HomeInfoView:UITableViewDataSource,UITableViewDelegate { extension HomeInfoView:UITableViewDataSource,UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let OffsetY = scrollView.contentOffset.y
let top = CGRectGetMaxY(self.headerView.titleLabel.frame) + 8
var orgy = OffsetY - top
if orgy < 0 {
orgy = 0
}
titleShowHideCallBack( OffsetY > top )
var farme = self.headerView.frame
farme.origin.y = orgy
self.headerView.frame = farme
tableView.bringSubviewToFront(self.headerView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ids?.count ?? 0 return ids?.count ?? 0
...@@ -284,13 +296,11 @@ extension HomeInfoView:UITableViewDataSource,UITableViewDelegate { ...@@ -284,13 +296,11 @@ extension HomeInfoView:UITableViewDataSource,UITableViewDelegate {
} }
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerView.height return headerView.height
} }
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return UIView()
return headerView
} }
} }
......
...@@ -9,7 +9,7 @@ import UIKit ...@@ -9,7 +9,7 @@ import UIKit
class HomeNavView:UIView { class HomeNavView:UIView {
private var settingBtn:UIButton! // private var settingBtn:UIButton!
private var proBtn:UIButton! private var proBtn:UIButton!
private lazy var homeTitle : UILabel = { private lazy var homeTitle : UILabel = {
let label = UILabel() let label = UILabel()
...@@ -38,24 +38,22 @@ class HomeNavView:UIView { ...@@ -38,24 +38,22 @@ class HomeNavView:UIView {
self.addSubview(self.homeTitle) self.addSubview(self.homeTitle)
self.homeTitle.snp.makeConstraints { make in self.homeTitle.snp.makeConstraints { make in
make.left.equalTo(15 + 8) make.left.equalTo(15 + 8)
make.top.equalTo(8 + statusBarHeight) make.top.equalTo(8)
make.height.equalTo(28) make.height.equalTo(28)
make.width.equalTo(149) make.width.equalTo(149)
} }
// 设置按钮 // 设置按钮
self.settingBtn = UIButton() // self.settingBtn = UIButton()
self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal) // self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal)
self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside) // self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(settingBtn) // self.addSubview(settingBtn)
self.settingBtn.snp.makeConstraints { make in // self.settingBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeTitle.snp.centerY) // make.centerY.equalTo(self.homeTitle.snp.centerY)
make.right.equalTo(-marginLR) // make.right.equalTo(-marginLR)
make.width.height.equalTo(iconWH) // make.width.height.equalTo(iconWH)
//
} // }
// 会员按钮 // 会员按钮
self.proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH)) self.proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH))
self.proBtn.setBackgroundImage(UIImage(named: "ic_pro_home"), for: .normal) self.proBtn.setBackgroundImage(UIImage(named: "ic_pro_home"), for: .normal)
...@@ -63,7 +61,7 @@ class HomeNavView:UIView { ...@@ -63,7 +61,7 @@ class HomeNavView:UIView {
self.addSubview(proBtn) self.addSubview(proBtn)
self.proBtn.snp.makeConstraints { make in self.proBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeTitle.snp.centerY) make.centerY.equalTo(self.homeTitle.snp.centerY)
make.right.equalTo(self.settingBtn.snp.left).offset(-8) make.right.equalTo(self.snp.right).offset(-8-iconWH-marginLR)
make.width.equalTo(78) make.width.equalTo(78)
make.height.equalTo(iconWH) make.height.equalTo(iconWH)
} }
...@@ -73,11 +71,12 @@ class HomeNavView:UIView { ...@@ -73,11 +71,12 @@ class HomeNavView:UIView {
extension HomeNavView { extension HomeNavView {
@objc private func settingBtnClick() { // @objc private func settingBtnClick() {
let homeNavViewModel = HomeNavViewModel() // let homeNavViewModel = HomeNavViewModel()
let settingViewController = SettingViewController() // let settingViewController = SettingViewController()
homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController) // homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
} // }
@objc private func proBtnClick() { @objc private func proBtnClick() {
if IAPManager.share.isSubscribed == false { if IAPManager.share.isSubscribed == false {
HomePayViewController.show {} HomePayViewController.show {}
......
...@@ -11,6 +11,7 @@ import SnapKit ...@@ -11,6 +11,7 @@ import SnapKit
class HomeView:UIView { class HomeView:UIView {
private var homeTabbarView:HomeTabbarView? private var homeTabbarView:HomeTabbarView?
private var settingBtn:UIButton!
private var homeNavView:HomeNavView? private var homeNavView:HomeNavView?
...@@ -30,6 +31,17 @@ class HomeView:UIView { ...@@ -30,6 +31,17 @@ class HomeView:UIView {
var model:PhotosManagerModel? var model:PhotosManagerModel?
var isScroll = false {
didSet {
if isScroll {
DispatchQueue.main.async {
self.tipLabel.attributedText = self.attribet
}
}
}
}
var attribet:NSAttributedString?
lazy var collectionView:UICollectionView = { lazy var collectionView:UICollectionView = {
let cY:CGFloat = 16.RW() let cY:CGFloat = 16.RW()
...@@ -51,11 +63,19 @@ class HomeView:UIView { ...@@ -51,11 +63,19 @@ class HomeView:UIView {
if #available(iOS 11.0, *) { if #available(iOS 11.0, *) {
sview.contentInsetAdjustmentBehavior = .never sview.contentInsetAdjustmentBehavior = .never
} }
sview.clipsToBounds = true
sview.backgroundColor = .clear sview.backgroundColor = .clear
return sview return sview
}() }()
private lazy var topNaviView: UIView = {
let backView = UIView()
backView.backgroundColor = UIColor(hex: "#DAEAFF")
addSubview(backView)
return backView
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
...@@ -68,20 +88,21 @@ class HomeView:UIView { ...@@ -68,20 +88,21 @@ class HomeView:UIView {
} }
func setTitle() { func setTitle() {
self.attribet = self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0)
DispatchQueue.main.async {[weak self] in DispatchQueue.main.async {[weak self] in
guard let self else {return} guard let self else {return}
if isScroll == false {
self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0) self.tipLabel.attributedText = self.attribet
self.homeHeader?.setNeedsLayout() self.homeHeader?.setNeedsLayout()
self.homeHeader?.layoutIfNeeded() self.homeHeader?.layoutIfNeeded()
}
} }
} }
private func setupUI() { private func setupUI() {
backgroundColor = .clear backgroundColor = .clear
clipsToBounds = true
homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66)) homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66))
...@@ -102,14 +123,29 @@ class HomeView:UIView { ...@@ -102,14 +123,29 @@ class HomeView:UIView {
homeNavView = HomeNavView(frame: CGRect(x: 0, y: 0, width: width, height: statusBarHeight + 44)) homeNavView = HomeNavView(frame: CGRect(x: 0, y: 0, width: width, height: statusBarHeight + 44))
topNaviView.snp.makeConstraints { make in
make.top.centerX.width.equalToSuperview()
make.height.equalTo(44)
}
self.addSubview(homeNavView!) self.addSubview(homeNavView!)
homeNavView?.snp.makeConstraints({ make in homeNavView?.snp.makeConstraints({ make in
make.top.centerX.width.equalToSuperview() make.top.centerX.width.equalToSuperview()
make.height.equalTo(statusBarHeight + 44) make.height.equalTo(44)
}) })
self.settingBtn = UIButton()
self.settingBtn.setImage(UIImage(named: "ic_setting_com"), for: .normal)
self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: .touchUpInside)
self.addSubview(settingBtn)
self.settingBtn.snp.makeConstraints { make in
make.centerY.equalTo(self.homeNavView!.snp.centerY)
make.right.equalTo(-marginLR)
make.width.height.equalTo(iconWH)
}
bottomView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: safeHeight + 10)) bottomView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: safeHeight + 10))
bottomView?.backgroundColor = .white bottomView?.backgroundColor = .white
self.addSubview(bottomView!) self.addSubview(bottomView!)
...@@ -118,15 +154,19 @@ class HomeView:UIView { ...@@ -118,15 +154,19 @@ class HomeView:UIView {
make.bottom.equalToSuperview().offset(10) make.bottom.equalToSuperview().offset(10)
make.height.equalTo(safeHeight + 10) make.height.equalTo(safeHeight + 10)
}) })
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(0) make.top.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)
} }
self.addSubview(self.tipLabel)
self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8+marginLR)
make.top.equalTo(self.collectionView.snp.top).offset(44)
make.height.equalTo(17)
}
} }
func etCell(indexPath: IndexPath) -> UICollectionViewCell { func etCell(indexPath: IndexPath) -> UICollectionViewCell {
...@@ -134,10 +174,53 @@ class HomeView:UIView { ...@@ -134,10 +174,53 @@ class HomeView:UIView {
return UICollectionViewCell() return UICollectionViewCell()
} }
private lazy var tipLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0 // 支持多行
return label
}()
} }
extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate { extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isScroll = true
}
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
isScroll = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
var changeY = offsetY
if changeY < 0 {
changeY = 0
}
var cframe = self.homeNavView?.frame
cframe?.origin.y = -changeY
self.homeNavView?.frame = cframe ?? CGRect()
var centerY = 22 + iconWH - offsetY
let setCenterY = settingBtn.center.y
if centerY < setCenterY {
centerY = setCenterY
}
tipLabel.centerY = centerY
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
isScroll = false // 拖动停止且无需减速
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
isScroll = false // 减速完全停止
}
func numberOfSections(in collectionView: UICollectionView) -> Int { func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2 return 2
...@@ -322,7 +405,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -322,7 +405,7 @@ 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 {
if Singleton.shared.photoPermission == .authorized { if Singleton.shared.photoPermission == .authorized {
return CGSize(width: self.collectionView.width, height: 76) return CGSize(width: self.collectionView.width, height: 76 + (self.homeNavView?.height ?? 0))
}else{ }else{
return CGSize(width: self.collectionView.width, height: 404) return CGSize(width: self.collectionView.width, height: 404)
} }
...@@ -334,4 +417,12 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol ...@@ -334,4 +417,12 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
let indexPath = IndexPath(item: 0, section: 0) let indexPath = IndexPath(item: 0, section: 0)
return self.collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath) return self.collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: indexPath)
} }
@objc private func settingBtnClick() {
let homeNavViewModel = HomeNavViewModel()
let settingViewController = SettingViewController()
homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
}
} }
...@@ -72,10 +72,21 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -72,10 +72,21 @@ class HomeOtherCollectionCell: UICollectionViewCell {
return iv return iv
}() }()
lazy var playerView: SecretVideoPlayer = {
let play = SecretVideoPlayer()
play.isUserInteractionEnabled = false
play.fromState = .home
play.Radius = 16
play.contentMode = .scaleAspectFill
play.isLooping = true
return play
}()
// MARK: - Lifecycle // MARK: - Lifecycle
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setupUI() setupUI()
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: Notification.Name("applicationDidBecomeActive"), object: nil)
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -87,16 +98,20 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -87,16 +98,20 @@ class HomeOtherCollectionCell: UICollectionViewCell {
backgroundColor = .white backgroundColor = .white
self.contentView.addSubview(self.titleLabel) self.contentView.addSubview(self.titleLabel)
self.contentView.addSubview(self.imageView) self.contentView.addSubview(self.imageView)
self.contentView.addSubview(self.playImageView) self.contentView.addSubview(self.playerView)
// self.contentView.addSubview(self.playImageView)
self.imageView.addSubview(self.infoBackView) self.playerView.addSubview(self.infoBackView)
self.infoBackView.addSubview(self.countLabel) self.infoBackView.addSubview(self.countLabel)
self.infoBackView.addSubview(self.sizeLabel) self.infoBackView.addSubview(self.sizeLabel)
self.infoBackView.addSubview(self.moreImageView) self.infoBackView.addSubview(self.moreImageView)
} }
@objc private func didBecomeActive() -> Void {
self.playerView.resume()
}
var model:HomePhotosModel? { var model:HomePhotosModel? {
didSet { didSet {
...@@ -161,19 +176,35 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -161,19 +176,35 @@ class HomeOtherCollectionCell: UICollectionViewCell {
// 从 PHAsset 获取 AVAsset // 从 PHAsset 获取 AVAsset
if let videoAsset = PhotoAndVideoMananger.mananger.getPHAsssetwithID(ids: [asset.localIdentifier]){ if let videoAsset = PhotoAndVideoMananger.mananger.getPHAsssetwithID(ids: [asset.localIdentifier]){
// 使用requestImageForAsset方法请求视频的第一帧图片 // 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager.default().requestImage(for: videoAsset, targetSize: CGSize(width: 400, height: 400), contentMode: PHImageContentMode.aspectFit, options: options) { image, _ in
// 处理获取到的图片 let options = PHVideoRequestOptions()
if let thumbnailImage = image { options.version = .current
// 使用获取到的图片,例如显示在UIImageView上 options.deliveryMode = .automatic // 根据需求调整视频质量:ml-citation{ref="2,7" data="citationList"}
DispatchQueue.main.async {
// 确保在主线程更新UI PHImageManager.default().requestAVAsset(
self.imageView.image = thumbnailImage forVideo: videoAsset,
} options: options
} else { ) { (avAsset, audioMix, info) in
self.imageView.image = UIImage(named: "img_vedio_defpage") guard let avAsset = avAsset as? AVURLAsset else { return }
print("无法获取图片") let videoURL = avAsset.url
} print("视频地址: \(videoURL)")
} DispatchQueue.main.async {
self.playerView.playVideo(from: videoURL)
}
}
// PHImageManager.default().requestImage(for: videoAsset, targetSize: CGSize(width: 400, height: 400), contentMode: PHImageContentMode.aspectFit, options: options) { image, _ in
// // 处理获取到的图片
// if let thumbnailImage = image {
// // 使用获取到的图片,例如显示在UIImageView上
// DispatchQueue.main.async {
// // 确保在主线程更新UI
// self.imageView.image = thumbnailImage
// }
// } else {
// self.imageView.image = UIImage(named: "img_vedio_defpage")
// print("无法获取图片")
// }
// }
} }
} }
} }
...@@ -206,14 +237,16 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -206,14 +237,16 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.height.equalTo(self.width - 32) make.height.equalTo(self.width - 32)
} }
self.infoBackView.snp.makeConstraints { make in self.infoBackView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview() make.left.right.bottom.equalToSuperview()
make.height.equalTo(40) make.height.equalTo(40)
} }
self.playImageView.snp.makeConstraints { make in // self.playImageView.snp.makeConstraints { make in
make.width.height.equalTo(43) // make.width.height.equalTo(43)
make.center.equalTo(self.imageView.snp.center) // make.center.equalTo(self.imageView.snp.center)
// }
self.playerView.snp.makeConstraints { make in
make.left.right.top.bottom.equalTo(imageView)
} }
titleLabel.snp.makeConstraints { make in titleLabel.snp.makeConstraints { make in
...@@ -237,7 +270,10 @@ class HomeOtherCollectionCell: UICollectionViewCell { ...@@ -237,7 +270,10 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.right.equalToSuperview().offset(-12) make.right.equalToSuperview().offset(-12)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
// titleLabel.sizeToFit()
} }
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name("applicationDidBecomeActive"), object: nil)
}
} }
...@@ -54,7 +54,7 @@ class ImageCollectionCell:UICollectionViewCell { ...@@ -54,7 +54,7 @@ class ImageCollectionCell:UICollectionViewCell {
backImageView = UIImageView() backImageView = UIImageView()
backImageView?.isUserInteractionEnabled = true backImageView?.isUserInteractionEnabled = true
backImageView?.contentMode = .scaleAspectFit backImageView?.contentMode = .scaleAspectFill
backImageView?.clipsToBounds = true backImageView?.clipsToBounds = true
backImageView?.layer.masksToBounds = true backImageView?.layer.masksToBounds = true
backImageView?.isUserInteractionEnabled = true backImageView?.isUserInteractionEnabled = true
......
...@@ -26,7 +26,6 @@ class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObs ...@@ -26,7 +26,6 @@ class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObs
private let productIdentifiers:[String] = ["com.app.phonemanager.week.member" , "com.app.phonemanager.lifetime.member"] private let productIdentifiers:[String] = ["com.app.phonemanager.week.member" , "com.app.phonemanager.lifetime.member"]
var isSubscribed:Bool = false var isSubscribed:Bool = false
var isNoAd:Bool { var isNoAd:Bool {
get { get {
......
...@@ -11,40 +11,62 @@ let PMShowImgCellID = "PMShowImgCell" ...@@ -11,40 +11,62 @@ let PMShowImgCellID = "PMShowImgCell"
class PMShowImgCell: UICollectionViewCell { class PMShowImgCell: UICollectionViewCell {
var callblock:(()->Void) = {}
@objc private func selectTap() -> Void {
callblock()
}
var icon:UIImage = UIImage() { var icon:UIImage = UIImage() {
didSet { didSet {
iconView.image = icon scaleImg.icon = icon
var size = icon.size // iconView.image = icon
if size.width != 0 && size.height != 0 { // var size = icon.size
if size.height < size.width { // if size.width != 0 && size.height != 0 {
let width = self.width // if size.height < size.width {
size = CGSize(width: width, height: size.height * (width/size.width) ) // let width = self.width
}else{ // size = CGSize(width: width, height: size.height * (width/size.width) )
let width = self.width // }else{
let height = size.height * (width/size.width) // let width = self.width
if height > self.height { // let height = size.height * (width/size.width)
size = CGSize(width: width * (self.height/height), height: height ) // if height > self.height {
}else { // size = CGSize(width: width * (self.height/height), height: height )
size = CGSize(width: width, height: height ) // }else {
} // size = CGSize(width: width, height: height )
} // }
} // }
// }
iconView.snp.remakeConstraints { make in //
make.centerX.centerY.equalToSuperview() // iconView.snp.remakeConstraints { make in
make.size.equalTo(size) // make.centerX.centerY.equalToSuperview()
} // make.size.equalTo(size)
// }
} }
} }
private lazy var iconView: UIImageView = { private lazy var iconView: UIImageView = {
let info = UIImageView() let info = UIImageView()
info.contentMode = .scaleToFill info.contentMode = .scaleAspectFill
contentView.addSubview(info) contentView.addSubview(info)
info.clipsToBounds = true info.clipsToBounds = true
return info return info
}() }()
lazy var selectBtn: UIButton = {
let select = UIButton(type: .custom)
select.setImage(UIImage(named: ""), for: .normal)
select.setImage(UIImage(named: ""), for: .selected)
select.addTarget(self, action: #selector(selectTap), for: .touchUpInside)
contentView.addSubview(select)
return select
}()
private lazy var scaleImg: PMScaleImageView = {
let img = PMScaleImageView()
contentView.addSubview(img)
return img
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setup() setup()
...@@ -59,5 +81,13 @@ class PMShowImgCell: UICollectionViewCell { ...@@ -59,5 +81,13 @@ class PMShowImgCell: UICollectionViewCell {
iconView.snp.makeConstraints { make in iconView.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview() make.left.right.bottom.top.equalToSuperview()
} }
scaleImg.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview().offset(-10)
}
} }
} }
...@@ -11,7 +11,7 @@ import UIKit ...@@ -11,7 +11,7 @@ import UIKit
let PMShowItemCellID = "PMShowItemCell" let PMShowItemCellID = "PMShowItemCell"
class PMShowItemCell: UICollectionViewCell { class PMShowItemCell: UICollectionViewCell {
var isCurrent:Bool = false { var isCurrent:Bool = false {
didSet { didSet {
if isCurrent { if isCurrent {
...@@ -37,6 +37,15 @@ class PMShowItemCell: UICollectionViewCell { ...@@ -37,6 +37,15 @@ class PMShowItemCell: UICollectionViewCell {
return ic return ic
}() }()
private lazy var selectBtn: UIButton = {
let select = UIButton(type: .custom)
select.setImage(UIImage(named: ""), for: .normal)
select.setImage(UIImage(named: ""), for: .selected)
contentView.addSubview(select)
select.isUserInteractionEnabled = false
return select
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
clipsToBounds = true clipsToBounds = true
...@@ -52,6 +61,11 @@ class PMShowItemCell: UICollectionViewCell { ...@@ -52,6 +61,11 @@ class PMShowItemCell: UICollectionViewCell {
iconV.snp.makeConstraints { make in iconV.snp.makeConstraints { make in
make.left.right.top.bottom.equalToSuperview() make.left.right.top.bottom.equalToSuperview()
} }
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview()
}
} }
} }
...@@ -29,41 +29,25 @@ class PMShowImgVideoController: BaseViewController { ...@@ -29,41 +29,25 @@ class PMShowImgVideoController: BaseViewController {
var homeDataSource : [ImageSeletedCollectionItem]? var homeDataSource : [ImageSeletedCollectionItem]?
var currentIdx = 0 var currentIdx = 0
var selectSet = NSMutableSet()
var url : URL? var url : URL?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
configUI()
}
func configUI(){
// 垃圾桶临时入口
let trashBtn = UIButton()
trashBtn.setTitle("trash", for: .normal)
trashBtn.setTitleColor(.black, for: .normal)
trashBtn.addTarget(self, action: #selector(pushToTrash), for: .touchUpInside)
titleView.addSubview(trashBtn)
trashBtn.snp.makeConstraints { make in
make.right.equalTo(-16)
make.centerY.equalTo(titleView.titleLabel)
}
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.MaxCollection.snp.makeConstraints { make in self.MaxCollection.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20) make.left.right.equalToSuperview().inset(20)
make.top.top.equalTo(titleView.snp.bottom).offset(20) make.top.equalTo(titleView.snp.bottom).offset(20)
make.bottom.equalToSuperview().inset(100) make.bottom.equalToSuperview().inset(100 + (cWindow?.safeAreaInsets.bottom ?? 0))
} }
self.bottItems.snp.makeConstraints { make in self.bottItems.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalTo(MaxCollection)
make.top.equalTo(MaxCollection.snp.bottom) make.top.equalTo(MaxCollection.snp.bottom)
make.bottom.equalToSuperview() make.bottom.equalToSuperview().offset(-(cWindow?.safeAreaInsets.bottom ?? 0))
} }
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false) self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false)
...@@ -88,27 +72,20 @@ class PMShowImgVideoController: BaseViewController { ...@@ -88,27 +72,20 @@ class PMShowImgVideoController: BaseViewController {
private lazy var bottItems: UICollectionView = { private lazy var bottItems: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout() let flowlayout = UICollectionViewFlowLayout()
flowlayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) flowlayout.sectionInset = UIEdgeInsets()
flowlayout.minimumInteritemSpacing = 0 flowlayout.minimumInteritemSpacing = 10
flowlayout.minimumLineSpacing = 10 flowlayout.minimumLineSpacing = 10
flowlayout.scrollDirection = .horizontal flowlayout.scrollDirection = .horizontal
let col = UICollectionView(frame: CGRect(), collectionViewLayout: flowlayout) let col = UICollectionView(frame: CGRect(), collectionViewLayout: flowlayout)
col.delegate = self; col.delegate = self;
col.dataSource = self; col.dataSource = self;
col.register(PMShowItemCell.self, forCellWithReuseIdentifier: PMShowItemCellID) col.register(PMShowItemCell.self, forCellWithReuseIdentifier: PMShowItemCellID)
col.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
col.showsHorizontalScrollIndicator = false col.showsHorizontalScrollIndicator = false
col.isPagingEnabled = true
view.addSubview(col) view.addSubview(col)
return col return col
}() }()
@objc func pushToTrash(){
let vc = TrashViewController()
self.present(vc, animated: true)
}
} }
extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
...@@ -119,29 +96,52 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -119,29 +96,52 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let offsetx = MaxCollection.contentOffset.x let offsetx = MaxCollection.contentOffset.x
let width = collectView.width let width = collectView.width
let current:Int = Int(offsetx / width) let current:Int = Int(offsetx / width)
currentIdx = current // currentIdx = current
bottItems.scrollToItem(at: IndexPath(row: current, section: 0), at: .left, animated: true)
}
}
private func setMaxCollection(collectionView:UICollectionView) -> Void {
if collectionView == bottItems {
let offsetX = collectionView.contentOffset.x
let idx = round(offsetX / (68 + 10))
UIView.animate(withDuration: 0.5) {
collectionView.contentOffset = CGPointMake( idx * (68 + 10) , 0)
}
MaxCollection.scrollToItem(at: IndexPath(row: Int(idx), section: 0), at: .centeredHorizontally, animated: true)
} }
} }
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
Print("1")
guard let collectView = scrollView as? UICollectionView else { return } guard let collectView = scrollView as? UICollectionView else { return }
if collectView == MaxCollection { // if collectView == MaxCollection {
bottItems.reloadData() // bottItems.reloadData()
} // }
self.setMaxCollection(collectionView: collectView)
} }
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
Print("2") if !decelerate {
guard let collectView = scrollView as? UICollectionView else { return }
self.setMaxCollection(collectionView: collectView)
}
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == bottItems { if collectionView == bottItems {
if currentIdx != indexPath.row { if selectSet.contains(indexPath.row) {
currentIdx = indexPath.row selectSet.remove(indexPath.row)
MaxCollection.scrollToItem(at: indexPath, at: .left, animated: false) }else{
collectionView.reloadData() selectSet.add(indexPath.row)
} }
self.MaxCollection.reloadData()
collectionView.reloadData()
// if currentIdx != indexPath.row {
// currentIdx = indexPath.row
// MaxCollection.scrollToItem(at: indexPath, at: .left, animated: false)
// collectionView.reloadData()
// }
} }
} }
...@@ -149,7 +149,11 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -149,7 +149,11 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if self.state == .secret { if self.state == .secret {
return imageVideoPath.count return imageVideoPath.count
}else { }else {
return self.homeDataSource?.count ?? 0 if collectionView == MaxCollection{
return self.homeDataSource?.count ?? 0
}else{
return (self.homeDataSource?.count ?? 0) + 1
}
} }
} }
...@@ -197,12 +201,25 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -197,12 +201,25 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection { if collectionView == MaxCollection {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isSelected = selectSet.contains(indexPath.row)
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.selectSet.contains(indexPath.row){
self.selectSet.remove(indexPath.row)
}else{
self.selectSet.add(indexPath.row)
}
self.MaxCollection.reloadData()
self.bottItems.reloadData()
}
return cell return cell
}else { }else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell if indexPath.row < self.homeDataSource?.count ?? 0 {
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.isCurrent = (self.currentIdx == indexPath.row) cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
return cell cell.isCurrent = selectSet.contains(indexPath.row) //(self.currentIdx == indexPath.row)
return cell
}
} }
} }
...@@ -226,13 +243,15 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -226,13 +243,15 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
cell.type = 1 cell.type = 1
return cell return cell
}else{ }else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell if indexPath.row < self.homeDataSource?.count ?? 0 {
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage() let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.isCurrent = (self.currentIdx == indexPath.row) cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
return cell cell.isCurrent = (self.currentIdx == indexPath.row)
return cell
}
} }
} }
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "", for: indexPath) let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
return cell return cell
} }
...@@ -240,11 +259,13 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa ...@@ -240,11 +259,13 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection { if collectionView == MaxCollection {
return collectionView.size return collectionView.size
} }
return CGSize(width: 68, height: 68) if indexPath.row < self.homeDataSource?.count ?? 0 {
return CGSize(width: 68, height: 68)
}
return CGSize(width: collectionView.width - 68, height: 68)
} }
/// 根据LocalIdentifier获取视频的URL /// 根据LocalIdentifier获取视频的URL
/// - Parameters: /// - Parameters:
/// - localIdentifier: 资源标识 /// - localIdentifier: 资源标识
......
...@@ -14,6 +14,11 @@ class SecretVideoPlayer: UIView { ...@@ -14,6 +14,11 @@ class SecretVideoPlayer: UIView {
private var player: AVPlayer? private var player: AVPlayer?
var isLooping = false var isLooping = false
enum PlayerFrom {
case home
case other
}
enum playState { enum playState {
case start case start
case playing case playing
...@@ -21,6 +26,8 @@ class SecretVideoPlayer: UIView { ...@@ -21,6 +26,8 @@ class SecretVideoPlayer: UIView {
case end case end
} }
var fromState:PlayerFrom = .other
var state:playState = .start var state:playState = .start
override init(frame: CGRect) { override init(frame: CGRect) {
...@@ -49,8 +56,11 @@ class SecretVideoPlayer: UIView { ...@@ -49,8 +56,11 @@ class SecretVideoPlayer: UIView {
} }
private func setupPlayerLayer() { private func setupPlayerLayer() {
backgroundColor = .clear
let playerLayer = AVPlayerLayer() let playerLayer = AVPlayerLayer()
playerLayer.videoGravity = .resizeAspect playerLayer.backgroundColor = UIColor.clear.cgColor
playerLayer.shouldRasterize = true
playerLayer.rasterizationScale = UIScreen.main.scale
layer.addSublayer(playerLayer) layer.addSublayer(playerLayer)
let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick)) let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick))
self.addGestureRecognizer(tap) self.addGestureRecognizer(tap)
...@@ -60,6 +70,7 @@ class SecretVideoPlayer: UIView { ...@@ -60,6 +70,7 @@ class SecretVideoPlayer: UIView {
super.layoutSubviews() super.layoutSubviews()
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer { if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = bounds playerLayer.frame = bounds
} }
} }
...@@ -71,6 +82,12 @@ class SecretVideoPlayer: UIView { ...@@ -71,6 +82,12 @@ class SecretVideoPlayer: UIView {
player = AVPlayer(url: url!) player = AVPlayer(url: url!)
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer { if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.player = player playerLayer.player = player
if fromState == .home {
playerLayer.videoGravity = .resizeAspectFill
player?.isMuted = true
}else{
playerLayer.videoGravity = .resizeAspect
}
} }
NotificationCenter.default.addObserver( NotificationCenter.default.addObserver(
self, self,
...@@ -79,6 +96,7 @@ class SecretVideoPlayer: UIView { ...@@ -79,6 +96,7 @@ class SecretVideoPlayer: UIView {
object: player?.currentItem object: player?.currentItem
) )
state = .playing state = .playing
player?.play() player?.play()
} }
......
...@@ -20,6 +20,18 @@ class WidgetPublicModel: NSObject { ...@@ -20,6 +20,18 @@ class WidgetPublicModel: NSObject {
return batt return batt
} }
public class func BatteryState() -> Bool {
let device = UIDevice.current
device.isBatteryMonitoringEnabled = true
switch device.batteryState {
case .charging:
return true
default:
return false
}
}
/// 已使用 /// 已使用
/// - Returns: 已使用空间 /// - Returns: 已使用空间
...@@ -68,6 +80,10 @@ class WidgetPublicModel: NSObject { ...@@ -68,6 +80,10 @@ class WidgetPublicModel: NSObject {
return val return val
} }
class func isLowPowerModeEnabled() -> Bool {
return ProcessInfo.processInfo.isLowPowerModeEnabled
}
} }
class widgetAppgourp: NSObject { class widgetAppgourp: NSObject {
...@@ -75,7 +91,12 @@ class widgetAppgourp: NSObject { ...@@ -75,7 +91,12 @@ class widgetAppgourp: NSObject {
static let share = widgetAppgourp() static let share = widgetAppgourp()
func PushWidgetData(_ widget:Int = 0 , battery:Int , storage:Int ) -> Void { func PushWidgetData(_ widget:Int = 0 , battery:Int , storage:Int ) -> Void {
let data = WidgetData(userId: "", widget: widget, battery: battery, widgetStorage: storage)
let disk = WidgetPublicModel.getDiskSpace()
let allInt = Int(CGFloat(disk.0)/(1000.0 * 1000.0 * 1000.0))
let useInt = Int(CGFloat(disk.0 - disk.1)/(1000.0 * 1000.0 * 1000.0))
let state = (WidgetPublicModel.isLowPowerModeEnabled() ? "On" : "Off")
let data = WidgetData(userId: "", widget: widget, battery: battery, widgetStorage: storage,AllSpace: allInt , UseSpace: useInt ,batteryState:state ,isCharging: WidgetPublicModel.BatteryState())
if let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager") { if let sharedDefaults = UserDefaults(suiteName: "group.com.app.phonemanager") {
let encodedData = try? JSONEncoder().encode(data) let encodedData = try? JSONEncoder().encode(data)
sharedDefaults.set(encodedData, forKey: "widgetSharedData") sharedDefaults.set(encodedData, forKey: "widgetSharedData")
...@@ -91,4 +112,8 @@ struct WidgetData: Codable { ...@@ -91,4 +112,8 @@ struct WidgetData: Codable {
var widget: Int var widget: Int
var battery: Int var battery: Int
var widgetStorage :Int var widgetStorage :Int
var AllSpace: Int
var UseSpace: Int
let batteryState: String
let isCharging: Bool
} }
This diff is collapsed.
...@@ -24,13 +24,27 @@ class WidgetTopStackView: UIView { ...@@ -24,13 +24,27 @@ class WidgetTopStackView: UIView {
if type == 0 { if type == 0 {
battryBtn.isSelected = true battryBtn.isSelected = true
storageBtn.isSelected = false storageBtn.isSelected = false
battryBtn.backgroundColor = .white battryBtn.backgroundColor = .white
storageBtn.backgroundColor = .clear storageBtn.backgroundColor = .clear
}else{
bronThem.isSelected = false
bronThem.backgroundColor = .clear
}else if type == 1{
battryBtn.isSelected = false battryBtn.isSelected = false
storageBtn.isSelected = true storageBtn.isSelected = true
battryBtn.backgroundColor = .clear battryBtn.backgroundColor = .clear
storageBtn.backgroundColor = .white storageBtn.backgroundColor = .white
bronThem.isSelected = false
bronThem.backgroundColor = .clear
}else{
battryBtn.isSelected = false
storageBtn.isSelected = false
battryBtn.backgroundColor = .clear
storageBtn.backgroundColor = .clear
bronThem.isSelected = true
bronThem.backgroundColor = .white
} }
} }
} }
...@@ -43,16 +57,37 @@ class WidgetTopStackView: UIView { ...@@ -43,16 +57,37 @@ class WidgetTopStackView: UIView {
} }
private func setUI() -> Void { private func setUI() -> Void {
battryBtn.snp.makeConstraints { make in stack.snp.makeConstraints { make in
make.left.top.bottom.equalToSuperview().inset(4) make.left.top.bottom.right.equalToSuperview().inset(4)
make.right.equalTo(self.snp.centerX)
}
storageBtn.snp.makeConstraints { make in
make.right.top.bottom.equalToSuperview().inset(4)
make.left.equalTo(self.snp.centerX)
} }
stack.addArrangedSubview(battryBtn)
stack.addArrangedSubview(storageBtn)
stack.addArrangedSubview(bronThem)
// battryBtn.snp.makeConstraints { make in
// make.left.top.bottom.equalToSuperview().inset(4)
// make.width.equalTo(self.snp.width).multipliedBy(1/3.0).offset(-8)
// }
// storageBtn.snp.makeConstraints { make in
// make.top.bottom.equalToSuperview().inset(4)
// make.left.equalTo(battryBtn.snp.right)
// make.width.equalTo(battryBtn.snp.width)
// }
// bronThem.snp.makeConstraints { make in
// make.right.top.bottom.equalToSuperview().inset(4)
// make.left.equalTo(storageBtn.snp.right)
// }
} }
private lazy var stack: UIStackView = {
let stack = UIStackView()
stack.spacing = 2
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
addSubview(stack)
return stack
}()
private lazy var battryBtn: UIButton = { private lazy var battryBtn: UIButton = {
let b = UIButton(type: .custom) let b = UIButton(type: .custom)
b.tag = 0 b.tag = 0
...@@ -61,7 +96,6 @@ class WidgetTopStackView: UIView { ...@@ -61,7 +96,6 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected) b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside) b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4 b.layer.cornerRadius = 4
addSubview(b)
return b return b
}() }()
...@@ -73,7 +107,17 @@ class WidgetTopStackView: UIView { ...@@ -73,7 +107,17 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected) b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside) b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4 b.layer.cornerRadius = 4
addSubview(b) return b
}()
private lazy var bronThem: UIButton = {
let b = UIButton(type: .custom)
b.tag = 2
b.setTitle("Both", for: .normal)
b.setTitleColor(.colorWithHex(hexStr: "#B3B3B3"), for: .normal)
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4
return b return b
}() }()
......
...@@ -9,21 +9,23 @@ import UIKit ...@@ -9,21 +9,23 @@ import UIKit
class WidgetViewController: BaseViewController { class WidgetViewController: BaseViewController {
enum widgetType { enum widgetType:Int {
case battery case battery = 0
case storage case storage = 1
case bothThem = 2
} }
var widgets:widgetType = .battery { var widgets:widgetType = .battery {
didSet { didSet {
topButs.type = (self.widgets == .battery ? 0 : 1) topButs.type = self.widgets.rawValue
batterySta.widgetType = (self.widgets == .battery ? 0 : 1) batterySta.widgetType = self.widgets.rawValue
} }
} }
var widgetMode = 0 {// 0 1 2 var widgetMode = 0 {// 0 1 2
didSet{ didSet{
batterySta.widgetMode = widgetMode batterySta.widgetMode = widgetMode
born.widgetMode = widgetMode
} }
} }
...@@ -33,11 +35,16 @@ class WidgetViewController: BaseViewController { ...@@ -33,11 +35,16 @@ class WidgetViewController: BaseViewController {
setUI() setUI()
} }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
widgetMode = 0
}
@objc func setWidgetTouch() -> Void { @objc func setWidgetTouch() -> Void {
let battery = WidgetPublicModel.battery() let battery = WidgetPublicModel.battery()
let storage = WidgetPublicModel.UseDiskSpace() * 100 let storage = WidgetPublicModel.UseDiskSpace() * 100
var widgetIdx = 0 var widgetIdx = 0
widgetIdx = (widgets == .battery ? 0 : 1) * 10 + widgetMode widgetIdx = widgets.rawValue * 10 + widgetMode
widgetAppgourp.share.PushWidgetData(widgetIdx, battery: Int(battery), storage: Int(storage)) widgetAppgourp.share.PushWidgetData(widgetIdx, battery: Int(battery), storage: Int(storage))
PMAlert("Set Widget Successfully") PMAlert("Set Widget Successfully")
} }
...@@ -61,14 +68,19 @@ class WidgetViewController: BaseViewController { ...@@ -61,14 +68,19 @@ class WidgetViewController: BaseViewController {
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.top.equalTo(batterySta.snp.bottom).offset(50) make.top.equalTo(batterySta.snp.bottom).offset(50)
} }
born.snp.makeConstraints { make in
make.top.equalTo(batterySta.snp.top)
make.left.right.equalToSuperview().inset(30)
make.height.equalTo(born.snp.width)
}
statesBottom.snp.makeConstraints { make in statesBottom.snp.makeConstraints { make in
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.size.equalTo(CGSize(width: 180, height: 40)) make.size.equalTo(CGSize(width: 180, height: 40))
make.top.equalTo(widgetPageCtrol.snp.bottom).offset(50) make.top.equalTo(born.snp.bottom).offset(20)
} }
setWidgetBtn.snp.makeConstraints { make in setWidgetBtn.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(15) make.left.right.equalToSuperview().inset(15)
make.bottom.equalToSuperview().offset(-50) make.bottom.equalToSuperview().offset(-30)
make.height.equalTo(46) make.height.equalTo(46)
} }
} }
...@@ -84,24 +96,37 @@ class WidgetViewController: BaseViewController { ...@@ -84,24 +96,37 @@ class WidgetViewController: BaseViewController {
private lazy var topButs: WidgetTopStackView = { private lazy var topButs: WidgetTopStackView = {
let topbuts = WidgetTopStackView() let topbuts = WidgetTopStackView()
topbuts.type = (self.widgets == .battery ? 0 : 1) topbuts.type = self.widgets.rawValue
topbuts.callback = { [weak self] idx in topbuts.callback = { [weak self] idx in
self?.born.isHidden = true
if idx == 0 { if idx == 0 {
self?.widgets = .battery self?.widgets = .battery
self?.widgetPageCtrol.currentPage = 0 self?.widgetPageCtrol.currentPage = 0
}else{ }else if idx == 1{
self?.widgets = .storage self?.widgets = .storage
self?.widgetPageCtrol.currentPage = 1 self?.widgetPageCtrol.currentPage = 1
}else{
self?.born.isHidden = false
self?.widgets = .bothThem
self?.widgetPageCtrol.currentPage = 2
} }
} }
view.addSubview(topbuts) view.addSubview(topbuts)
return topbuts return topbuts
}() }()
private lazy var born: WidgetBornThenView = {
let born = WidgetBornThenView()
born.layer.cornerRadius = 20
born.isHidden = true
view.addSubview(born)
return born
}()
private lazy var batterySta: WidgetBatteryStView = { private lazy var batterySta: WidgetBatteryStView = {
let stav = WidgetBatteryStView() let stav = WidgetBatteryStView()
stav.layer.cornerRadius = 20 stav.layer.cornerRadius = 20
stav.widgetType = (self.widgets == .battery ? 0 : 1) stav.widgetType = self.widgets.rawValue
stav.widgetMode = widgetMode stav.widgetMode = widgetMode
view.addSubview(stav) view.addSubview(stav)
return stav return stav
...@@ -110,7 +135,7 @@ class WidgetViewController: BaseViewController { ...@@ -110,7 +135,7 @@ class WidgetViewController: BaseViewController {
private lazy var widgetPageCtrol: UIPageControl = { private lazy var widgetPageCtrol: UIPageControl = {
let page = UIPageControl() let page = UIPageControl()
page.currentPage = 0 page.currentPage = 0
page.numberOfPages = 2 page.numberOfPages = 3
page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF") page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF")
page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0") page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0")
view.addSubview(page) view.addSubview(page)
......
//
// EmailCleanListViewCell.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailCleanListViewCell: UITableViewCell {
static let id = "EmailCleanListViewCell"
var callblock = {}
@IBOutlet weak var ListFirstL: UILabel!
@IBOutlet weak var selectBtn: UIButton!
@IBOutlet weak var ListDot: UIView!
@IBOutlet weak var groupName: UILabel!
@IBOutlet weak var descpText: UILabel!
@IBOutlet weak var descpText1: UILabel!
@IBOutlet weak var EmailTimeL: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
@IBAction func selectActions(_ sender: Any) {
callblock()
}
}
//
// EmailContentTabCell.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailContentTabCell: UITableViewCell {
static let id = "EmailContentTabCell"
var callblock = {}
@IBOutlet weak var selectBtn: UIButton!
@IBOutlet weak var groupName: UILabel!
@IBOutlet weak var groupNumbers: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
@IBAction func selectActions(_ sender: Any) {
callblock()
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="EmailContentTabCell" customModule="PhoneManager" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="86"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="86"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HGx-M7-LQS">
<rect key="frame" x="15" y="0.0" width="290" height="74"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SFC-9k-JL4">
<rect key="frame" x="6" y="15.000000000000004" width="44" height="44.333333333333343"/>
<inset key="contentEdgeInsets" minX="10" minY="10" maxX="10" maxY="10"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="ic_sel_com"/>
<state key="selected" image="ic_unsel_com_red"/>
<connections>
<action selector="selectActions:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="PTj-Zp-HqP"/>
</connections>
</button>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="1" translatesAutoresizingMaskIntoConstraints="NO" id="a94-EP-nFu">
<rect key="frame" x="50" y="18.333333333333332" width="92" height="37.333333333333343"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Social Media" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eH5-kI-3vv">
<rect key="frame" x="0.0" y="0.0" width="92" height="19.333333333333332"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0 Emails" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dgz-WN-aKh">
<rect key="frame" x="0.0" y="20.333333333333332" width="92" height="16.999999999999996"/>
<color key="backgroundColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="0.0" colorSpace="custom" customColorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_left_setting_grey" translatesAutoresizingMaskIntoConstraints="NO" id="JWZ-DO-70m">
<rect key="frame" x="254" y="27" width="20" height="20"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.94901960784313721" green="0.96470588235294119" blue="0.9882352941176471" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="JWZ-DO-70m" secondAttribute="trailing" constant="16" id="9Be-SQ-UxW"/>
<constraint firstItem="SFC-9k-JL4" firstAttribute="centerY" secondItem="HGx-M7-LQS" secondAttribute="centerY" id="Gww-V3-ADp"/>
<constraint firstItem="SFC-9k-JL4" firstAttribute="leading" secondItem="HGx-M7-LQS" secondAttribute="leading" constant="6" id="MuS-Bu-Wyb"/>
<constraint firstItem="a94-EP-nFu" firstAttribute="centerY" secondItem="HGx-M7-LQS" secondAttribute="centerY" id="b2x-dx-sEC"/>
<constraint firstItem="a94-EP-nFu" firstAttribute="leading" secondItem="SFC-9k-JL4" secondAttribute="trailing" id="kS8-jn-NTj"/>
<constraint firstItem="JWZ-DO-70m" firstAttribute="centerY" secondItem="HGx-M7-LQS" secondAttribute="centerY" id="q4H-To-Ycj"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="12"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="HGx-M7-LQS" secondAttribute="bottom" constant="12" id="5ow-Tb-b9b"/>
<constraint firstAttribute="trailing" secondItem="HGx-M7-LQS" secondAttribute="trailing" constant="15" id="7pZ-zP-neq"/>
<constraint firstItem="HGx-M7-LQS" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="15" id="o6P-oe-F5F"/>
<constraint firstItem="HGx-M7-LQS" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="z1a-C6-L0w"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<connections>
<outlet property="groupName" destination="eH5-kI-3vv" id="SJQ-eI-X4U"/>
<outlet property="groupNumbers" destination="dgz-WN-aKh" id="HJh-jw-nFW"/>
<outlet property="selectBtn" destination="SFC-9k-JL4" id="4V0-CJ-STJ"/>
</connections>
<point key="canvasLocation" x="131" y="-11"/>
</tableViewCell>
</objects>
<resources>
<image name="ic_sel_com" width="24" height="24.333333969116211"/>
<image name="ic_unsel_com_red" width="24" height="24"/>
<image name="icon_left_setting_grey" width="20" height="20"/>
</resources>
</document>
//
// EmailFilterSelectCell.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailFilterBaseCell: UITableViewCell {
var callblock:((Bool)->Void) = { select in}
var top:Bool = false
var bot:Bool = false
func reload() -> Void {
DispatchQueue.main.async {
if self.top && self.bot {
self.cornerCut(radius: 12, corner: [.allCorners])
}else if self.top {
self.cornerCut(radius: 12, corner: [.topLeft,.topRight])
}else if self.bot {
self.cornerCut(radius: 12, corner: [.bottomLeft,.bottomRight])
}else{
self.cornerCut(radius: 0, corner: [.allCorners])
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
@IBOutlet weak var titleL: UILabel!
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="KGk-i7-Jjw" customClass="EmailFilterBaseCell">
<rect key="frame" x="0.0" y="0.0" width="320" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bYm-Ap-ASH">
<rect key="frame" x="16" y="0.0" width="0.0" height="50"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="50" id="ByC-vP-p5G"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
<color key="textColor" red="0.20000001788139343" green="0.20000001788139343" blue="0.20000001788139343" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
<real key="value" value="1"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<color key="backgroundColor" red="0.9490196704864502" green="0.96470588445663452" blue="0.98823529481887817" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="bYm-Ap-ASH" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="64l-PN-erS"/>
<constraint firstItem="bYm-Ap-ASH" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="Phe-hO-ZzN"/>
<constraint firstAttribute="bottom" secondItem="bYm-Ap-ASH" secondAttribute="bottom" id="qz2-bx-e67"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="titleL" destination="bYm-Ap-ASH" id="mmr-1G-Kh5"/>
</connections>
<point key="canvasLocation" x="104" y="-11"/>
</tableViewCell>
</objects>
</document>
//
// EmailFilterSelectCell.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailFilterSelectCell: EmailFilterBaseCell {
static let id = "EmailFilterSelectCell"
@IBOutlet weak var selectBtn: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.titleL.snp.remakeConstraints { make in
make.right.equalTo(selectBtn.snp.left).offset(-5)
make.top.bottom.equalToSuperview()
make.left.equalToSuperview().offset(16)
make.height.equalTo(50)
}
}
@IBAction func selectActions(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
callblock(sender.isSelected)
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
//
// EmailContentDelAlert.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailContentDelAlert: UIViewController {
enum EmailStateAlert {
case group
case list
}
var callblock:((Int)->Void) = { idx in}
var state:EmailStateAlert = .group
@IBOutlet weak var EmailContentMessage: UILabel!
@IBOutlet weak var EmailContentAction1: UIButton!
@IBOutlet weak var EmailContentAction2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.colorWithHex(hexStr: "#000000", alpha: 0.5)
switch state {
case .group:
EmailContentMessage.text = "Do you want to apply filters\nfirst or delete mails\nimmediately?"
EmailContentAction1.setTitle("Open Filters", for: .normal)
EmailContentAction2.setTitle("Delete Mails", for: .normal)
break
case .list:
EmailContentMessage.text = "Are you sure you want to delete\nthe selected message?"
EmailContentAction1.setTitle("Delete", for: .normal)
EmailContentAction2.setTitle("Cancel", for: .normal)
break
}
}
func show() -> Void {
self.modalTransitionStyle = .crossDissolve
self.modalPresentationStyle = .overFullScreen
UIViewController.topMostViewController()?.present(self, animated: true)
}
@IBAction func openAction(_ sender: Any) {
callblock(1)
self.dismiss(animated: true)
}
@IBAction func delMails(_ sender: Any) {
callblock(2)
self.dismiss(animated: true)
}
init(state:EmailStateAlert) {
super.init(nibName: nil, bundle: nil)
self.state = state
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="EmailContentDelAlert" customModule="PhoneManager" customModuleProvider="target">
<connections>
<outlet property="EmailContentAction1" destination="H0G-H1-Hx9" id="UGo-uz-h5v"/>
<outlet property="EmailContentAction2" destination="jnJ-Cn-DN9" id="kvy-Tn-fkZ"/>
<outlet property="EmailContentMessage" destination="LvN-1W-NqV" id="Njf-Gw-nPY"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pSS-8M-78U">
<rect key="frame" x="15" y="324" width="363" height="204"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Do you want to apply filters first or delete mails immediately?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LvN-1W-NqV">
<rect key="frame" x="30" y="28" width="303" height="48"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H0G-H1-Hx9">
<rect key="frame" x="20" y="92" width="323" height="46"/>
<color key="backgroundColor" red="0.0" green="0.50980392156862742" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="46" id="5di-G4-1L2"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Open Filters"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="23"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="openAction:" destination="-1" eventType="touchUpInside" id="cXg-7i-361"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jnJ-Cn-DN9">
<rect key="frame" x="20" y="142" width="323" height="46"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="46" id="nV9-Zl-cHG"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Delete Mails">
<color key="titleColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="calibratedRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="23"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="delMails:" destination="-1" eventType="touchUpInside" id="4eY-Ct-AUg"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="jnJ-Cn-DN9" firstAttribute="trailing" secondItem="H0G-H1-Hx9" secondAttribute="trailing" id="4ng-Lt-WbX"/>
<constraint firstAttribute="trailing" secondItem="H0G-H1-Hx9" secondAttribute="trailing" constant="20" id="905-Xu-9S0"/>
<constraint firstItem="jnJ-Cn-DN9" firstAttribute="leading" secondItem="H0G-H1-Hx9" secondAttribute="leading" id="LEk-uf-rgE"/>
<constraint firstAttribute="bottom" secondItem="jnJ-Cn-DN9" secondAttribute="bottom" constant="16" id="Md6-lU-fDx"/>
<constraint firstAttribute="trailing" secondItem="LvN-1W-NqV" secondAttribute="trailing" constant="30" id="NSl-d7-q7R"/>
<constraint firstItem="H0G-H1-Hx9" firstAttribute="leading" secondItem="pSS-8M-78U" secondAttribute="leading" constant="20" id="Ug2-zL-HbE"/>
<constraint firstItem="LvN-1W-NqV" firstAttribute="top" secondItem="pSS-8M-78U" secondAttribute="top" constant="28" id="WEG-CD-zit"/>
<constraint firstItem="H0G-H1-Hx9" firstAttribute="top" secondItem="LvN-1W-NqV" secondAttribute="bottom" constant="16" id="iri-xQ-fNU"/>
<constraint firstItem="jnJ-Cn-DN9" firstAttribute="top" secondItem="H0G-H1-Hx9" secondAttribute="bottom" constant="4" id="lRP-Ui-Mbq"/>
<constraint firstItem="LvN-1W-NqV" firstAttribute="leading" secondItem="pSS-8M-78U" secondAttribute="leading" constant="30" id="nXB-dD-AvZ"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="Radius">
<real key="value" value="20"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="pSS-8M-78U" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="15" id="HFc-06-2Br"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="pSS-8M-78U" secondAttribute="trailing" constant="15" id="gCg-jq-x1v"/>
<constraint firstItem="pSS-8M-78U" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="j7D-f0-DPt"/>
</constraints>
<point key="canvasLocation" x="131" y="-12"/>
</view>
</objects>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
//
// EmailCleanController.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailCleanController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() -> Void {
contentView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(titleView.snp.bottom)
}
}
private lazy var contentView: EmailContentView = {
let content = EmailContentView(self)
view.addSubview(content)
return content
}()
}
//
// EmailCleanListController.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailCleanListController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setup()
}
@objc func seletedAllBtnClick() {
DispatchQueue.main.async {[weak self] in
guard let self else {return}
seletedAllBtn.isSelected = !seletedAllBtn.isSelected
UIView.animate(withDuration: 0.1) {
self.seletedAllBtn.width = self.seletedAllBtn.isSelected ? 131 : 115
self.seletedAllBtn.x = self.titleView.width - marginLR - self.seletedAllBtn.width
}
tableView.changeSelectAll(seletedAllBtn.isSelected)
}
}
private func setup() -> Void {
titleLabel.snp.makeConstraints { make in
make.top.equalTo(titleView.snp.bottom).offset(20)
make.left.equalToSuperview().offset(marginLR)
}
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.bottom.equalToSuperview()
}
titleView.addSubview(seletedAllBtn)
seletedAllBtn.centerY = navCenterY
seletedAllBtn.x = titleView.width - marginLR - seletedAllBtn.width
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "Social Media"
label.font = UIFont.systemFont(ofSize: 20, weight: .bold)
label.textColor = .black
label.textAlignment = .left
view.addSubview(label)
return label
}()
private lazy var tableView: EmailCleanListView = {
let tab = EmailCleanListView()
view.addSubview(tab)
tab.callblock = { [weak self] select in
guard let self = self else { return }
self.seletedAllBtn.isSelected = select
}
return tab
}()
private lazy var seletedAllBtn:UIButton = {
let btn:UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 115, height: 32))
btn.addTarget(self, action: #selector(seletedAllBtnClick), for: .touchUpInside)
btn.backgroundColor = UIColor.colorWithHex(hexStr: "#F2F6FC")
btn.setImage(UIImage.init(named: "ic_check_similar"), for: .normal)
btn.setTitle("Select All", for: .normal)
btn.setImage(UIImage.init(named: "ic_close_similar"), for: .selected)
btn.setTitle("Deselect All", for: .selected)
btn.setTitleColor(UIColor.colorWithHex(hexStr: mColor), for: .normal)
btn.setTitleColor(UIColor.colorWithHex(hexStr: black3Color), for: .selected)
btn.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .bold)
btn.layer.cornerRadius = btn.height / 2
btn.layer.masksToBounds = true
btn.changBtnWithStytl(btnStyle: .defalut, margin: 8)
return btn
}()
}
//
// EmailFilterController.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailFilterController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
}
var datasource:[EmailFilterModel] = EmailFilterManager.filter()
private func setup() -> Void {
titleLabel.snp.makeConstraints({ make in
make.left.equalTo(titleView.backBtn.snp.right).offset(5)
make.centerY.equalTo(titleView.backBtn)
})
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(marginLR)
make.top.equalTo(titleView.snp.bottom).offset(10)
make.bottom.equalTo(ApplyBtn.snp.top)
}
ApplyBtn.snp.makeConstraints { make in
make.height.equalTo(46)
make.bottom.equalToSuperview().offset(-(cWindow?.safeAreaInsets.bottom ?? 0)-10)
make.left.right.equalToSuperview().inset(marginLR)
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "Filters"
label.font = UIFont.systemFont(ofSize: 20, weight: .bold)
label.textColor = .black
label.textAlignment = .left
titleView.addSubview(label)
return label
}()
private lazy var tableView: UITableView = {
let tab = UITableView(frame: CGRectZero, style: .plain)
tab.delegate = self;
tab.dataSource = self
tab.separatorStyle = .none
tab.separatorInset = UIEdgeInsets()
tab.sectionHeaderHeight = 50
tab.register(UINib(nibName: EmailFilterSelectCell.id, bundle: nil), forCellReuseIdentifier: EmailFilterSelectCell.id)
if #available(iOS 15.0, *) {
tab.sectionHeaderTopPadding = 0
}
view.addSubview(tab)
return tab
}()
private lazy var ApplyBtn: UIButton = {
let emailLogin = UIButton(type: .custom)
emailLogin.backgroundColor = UIColor.colorWithHex(hexStr: "#0082FF")
emailLogin.setTitle("Apply Filters", for: .normal)
emailLogin.setTitleColor(.white, for: .normal)
emailLogin.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
emailLogin.layer.cornerRadius = 46/2.0
emailLogin.clipsToBounds = true
emailLogin.addTarget(self, action: #selector(ApplyAction), for: .touchUpInside)
view.addSubview(emailLogin)
return emailLogin
}()
}
extension EmailFilterController : UITableViewDelegate,UITableViewDataSource {
@objc func ApplyAction() -> Void {
guard var path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
path = path.appendingPathComponent("EmailFilter.json")
do{
let data = try JSONEncoder().encode(datasource)
try data.write(to: path)
}catch{
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return datasource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datasource[section].child?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: EmailFilterSelectCell.id, for: indexPath) as! EmailFilterSelectCell
let dataA = datasource[indexPath.section].child
let data = dataA?[indexPath.row]
cell.titleL.text = data?.title ?? ""
cell.selectBtn.isSelected = data?.isSelect ?? false
cell.top = (indexPath.row == 0)
cell.bot = (indexPath.row == (dataA?.count ?? 0 - 1))
cell.callblock = {[weak self] select in
guard let self = self else { return }
self.datasource[indexPath.section].child?[indexPath.row].isSelect = select
tableView.reloadData()
}
cell.reload()
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UILabel()
header.font = UIFont.boldSystemFont(ofSize: 12)
header.text = datasource[section].header ?? ""
header.textColor = UIColor.colorWithHex(hexStr: "#B3B3B3")
return header
}
}
//
// EmailListDetailController.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailListDetailController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() -> Void {
line.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(titleView.snp.bottom).offset(20)
make.height.equalTo(1)
}
LT.snp.makeConstraints { make in
make.left.equalToSuperview().inset(15)
make.top.equalTo(line.snp.bottom).offset(15)
make.size.equalTo(CGSizeMake(40, 40))
}
SendL.snp.makeConstraints { make in
make.left.equalTo(LT.snp.right).offset(4)
make.right.equalTo(dateL.snp.left).inset(-5)
make.bottom.equalTo(LT.snp.centerY).offset(-2)
}
ToEmail.snp.makeConstraints { make in
make.left.equalTo(LT.snp.right).offset(4)
make.right.equalTo(dateL.snp.left).inset(-5)
make.top.equalTo(LT.snp.centerY).offset(2)
}
dateL.snp.makeConstraints { make in
make.right.equalToSuperview().inset(marginLR)
make.centerY.equalTo(LT.snp.centerY).offset(2)
make.width.equalTo(55)
}
line1.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(LT.snp.bottom).offset(15)
make.height.equalTo(1)
}
titleL.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(marginLR)
make.top.equalTo(line1.snp.bottom).offset(20)
}
}
private lazy var LT: UILabel = {
let l = UILabel()
l.Radius = 20
l.text = "G"
l.font = UIFont.systemFont(ofSize: 20, weight: .heavy)
l.textAlignment = .center
l.textColor = .white
l.backgroundColor = UIColor.colorWithHex(hexStr: "#0082FF")
view.addSubview(l)
return l
}()
private lazy var SendL: UILabel = {
let l = UILabel()
l.text = "Google Play Support"
l.font = UIFont.systemFont(ofSize: 16, weight: .bold)
l.textColor = UIColor.colorWithHex(hexStr: "#333333")
view.addSubview(l)
return l
}()
private lazy var ToEmail: UILabel = {
let l = UILabel()
l.text = "To:zxcvbnm@gmail.com"
l.font = UIFont.systemFont(ofSize: 14, weight: .regular)
l.textColor = UIColor.colorWithHex(hexStr: "#666666")
view.addSubview(l)
return l
}()
private lazy var dateL: UILabel = {
let l = UILabel()
l.text = "20 Dec"
l.textAlignment = .right
l.font = UIFont.systemFont(ofSize: 12, weight: .regular)
l.textColor = UIColor.colorWithHex(hexStr: "#B3B3B3")
view.addSubview(l)
return l
}()
private lazy var titleL: UILabel = {
let l = UILabel()
l.text = "Notification from Google Play"
l.font = UIFont.systemFont(ofSize: 16, weight: .bold)
l.textColor = UIColor.colorWithHex(hexStr: "#333333")
view.addSubview(l)
return l
}()
private lazy var line: UIView = {
let l = UIView()
l.backgroundColor = UIColor.colorWithHex(hexStr: "#EBEFF5")
view.addSubview(l)
return l
}()
private lazy var line1: UIView = {
let l = UIView()
l.backgroundColor = UIColor.colorWithHex(hexStr: "#EBEFF5")
view.addSubview(l)
return l
}()
}
//
// EmailLoginController.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailLoginController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() -> Void {
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(marginLR)
make.top.equalTo(titleView.snp.bottom).offset(20)
}
EmptyView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalTo(titleLabel.snp.bottom)
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "Email Cleaner"
label.font = UIFont.systemFont(ofSize: 20, weight: .bold)
label.textColor = .black
label.textAlignment = .left
view.addSubview(label)
return label
}()
private lazy var EmptyView: EmailEmptyView = {
let empty = EmailEmptyView()
view.addSubview(empty)
empty.callblock = {[weak self] in
guard let self = self else { return }
let gourp = EmailCleanController()
var navigation = self.navigationController?.viewControllers
if navigation?.count ?? 0 > 1 {
navigation![navigation!.count-1] = gourp
self.navigationController?.setViewControllers(navigation ?? [], animated: true)
}
}
return empty
}()
}
//
// EmailFilterModel.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailFilterManager: NSObject {
class func filter() -> [EmailFilterModel] {
let data = [ ["header":"TIME","child":[ ["title":"Delete all mails from selected categories",
"isSelect":false],
["title":"Delete 1 week and older mails",
"isSelect":false],
["title":"Delete 1 month and older mails",
"isSelect":false],
["title":"Delete 1 year and older mails",
"isSelect":false] ]
],
["header":"FAVORITE","child":[ ["title":"Delete stared mails",
"isSelect":false] ]
],
["header":"READ & UNREAD","child":[ ["title":"Delete read mails",
"isSelect":false],
["title":"Delete unread mails",
"isSelect":false]]
],
["header":"KEYWORDS","child":[ ["title":"Do not delete mails that contains the keywords below",
"isSelect":false,
"keyword":[] ] ]
]
]
guard var path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return [] }
path = path.appendingPathComponent("EmailFilter.json")
do {
let dataFile = try Data(contentsOf: path)
let decode = try JSONDecoder().decode([EmailFilterModel].self, from:dataFile)
return decode
}catch{
}
do{
let encode = try JSONSerialization.data(withJSONObject: data)
let decode = try JSONDecoder().decode([EmailFilterModel].self, from: encode)
return decode
}catch{
return []
}
}
}
struct EmailFilterModel: Codable {
var header:String?
var child:[EmailFilterChildModel]?
}
struct EmailFilterChildModel:Codable {
var title:String?
var isSelect:Bool = false
var keyword:[String]?
}
//
// EmailCleanListView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailCleanListView: UIView {
var callblock:((Bool)->Void) = { select in }
private func setup() -> Void {
tableView.snp.makeConstraints { make in
make.left.right.top.equalToSuperview()
make.bottom.equalTo(botAction.snp.top)
}
botAction.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(52 + (cWindow?.safeAreaInsets.bottom ?? 0) + 24 )
}
}
var mailset = NSMutableSet()
var datasource:[String] = ["","","","","","","",""]
func changeSelectAll(_ select:Bool) -> Void {
if select {
for i in 0..<datasource.count {
self.mailset.add(i)
}
}else{
self.mailset.removeAllObjects()
}
botAction.numberMails = self.mailset.count
tableView.reloadData()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private lazy var tableView: UITableView = {
let tab = UITableView(frame: CGRectZero, style: .plain)
tab.delegate = self;
tab.dataSource = self
tab.separatorStyle = .none
tab.separatorInset = UIEdgeInsets()
tab.rowHeight = 101
tab.sectionHeaderHeight = 10
tab.register(UINib(nibName: EmailCleanListViewCell.id, bundle: nil), forCellReuseIdentifier: EmailCleanListViewCell.id)
if #available(iOS 15.0, *) {
tab.sectionHeaderTopPadding = 0
} else {
// Fallback on earlier versions
}
addSubview(tab)
return tab
}()
private lazy var botAction: EmailContentBottonAction = {
let bot = EmailContentBottonAction(state: .EmailList)
bot.clipsToBounds = false
addSubview(bot)
bot.numberMails = 0
bot.callblock = { [weak self] in
guard let self = self else { return }
let alert = EmailContentDelAlert(state: .list)
alert.callblock = { idx in
}
alert.show()
}
return bot
}()
}
extension EmailCleanListView : UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datasource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: EmailCleanListViewCell.id, for: indexPath) as! EmailCleanListViewCell
cell.selectionStyle = .none
cell.selectBtn.isSelected = self.mailset.contains(indexPath.row)
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.mailset.contains(indexPath.row) {
self.mailset.remove(indexPath.row)
}else{
self.mailset.add(indexPath.row)
}
self.botAction.numberMails = self.mailset.count
callblock(self.mailset.count == self.datasource.count)
tableView.reloadData()
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detail = EmailListDetailController()
UIViewController.topMostViewController()?.navigationController?.pushViewController(detail, animated: true)
}
}
//
// EmailCleanTopView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailCleanTopView: UIView {
var callblock:(()->Void) = {}
private func setup() -> Void {
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(marginLR)
make.top.equalToSuperview().offset(20)
}
settingsButton.snp.makeConstraints { make in
make.right.equalToSuperview().inset(marginLR)
make.centerY.equalTo(titleLabel.snp.centerY)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "Email Cleaner"
label.font = UIFont.systemFont(ofSize: 20, weight: .bold)
label.textColor = .black
label.textAlignment = .left
addSubview(label)
return label
}()
private lazy var settingsButton: UIButton = {
let button = UIButton(type: .custom)
button.clipsToBounds = true
button.setImage(UIImage(named: "ic_switch_email"), for: .normal)
button.addTarget(self, action: #selector(filter), for: .touchUpInside)
addSubview(button)
return button
}()
@objc private func filter() -> Void {
callblock()
}
}
//
// EmailContentBottonAction.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailContentBottonAction: UIView {
enum ActionState:Int {
case EmailGroup = 0
case EmailList = 1
}
var callblock = {}
var state:ActionState = .EmailGroup
var numberMails:Int = 0 {
didSet {
DelEmailBtn.setTitle(btnTitle(), for: .normal)
DelEmailBtn.isEnabled = numberMails > 0
}
}
@objc private func delMails() -> Void {
callblock()
}
private func setup() -> Void {
DelEmailBtn.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(marginLR)
make.height.equalTo(46)
make.top.equalToSuperview().offset(12)
}
if state == .EmailGroup {
DelEmailBtn.setBackgroundImage(UIImage.Clear(UIColor(hex: "#7FC0FF") ?? .clear), for: .disabled)
DelEmailBtn.setBackgroundImage(UIImage.Clear(UIColor(hex: "#0082FF") ?? .clear), for: .normal)
}else{
DelEmailBtn.setBackgroundImage(UIImage.Clear(UIColor(hex: "#F5A2A2") ?? .clear), for: .disabled)
DelEmailBtn.setBackgroundImage(UIImage.Clear(UIColor(hex: "#EB4545") ?? .clear), for: .normal)
}
}
convenience init(state:ActionState) {
self.init(frame: CGRect())
self.state = state
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private lazy var DelEmailBtn: UIButton = {
let emailLogin = UIButton(type: .custom)
emailLogin.setImage(UIImage(named: "ic_delete_duplicates"), for: .normal)
emailLogin.setTitle(btnTitle(), for: .normal)
emailLogin.setTitleColor(.white, for: .normal)
emailLogin.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
emailLogin.layer.cornerRadius = 46/2.0
emailLogin.clipsToBounds = true
emailLogin.addTarget(self, action: #selector(delMails), for: .touchUpInside)
emailLogin.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
emailLogin.setBackgroundImage(UIImage.Clear(UIColor(hex: "#7FC0FF") ?? .clear), for: .disabled)
emailLogin.setBackgroundImage(UIImage.Clear(UIColor(hex: "#0082FF") ?? .clear), for: .normal)
addSubview(emailLogin)
return emailLogin
}()
private func btnTitle() -> String {
return "Delete \(numberMails) Mails"
}
}
//
// EmailContentView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailContentView: UIView {
var parent:UIViewController?
var mailset = NSMutableSet()
private func setup() -> Void {
topItem.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalTo(self.snp.top).offset(0)
make.height.equalTo(60)
}
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.bottom.equalTo(botAction.snp.top)
make.top.equalTo(topItem.snp.bottom)
}
botAction.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(52 + (cWindow?.safeAreaInsets.bottom ?? 0) + 24 )
}
}
convenience init( _ parent:UIViewController) {
self.init(frame: CGRect())
self.parent = parent
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private lazy var topItem: EmailCleanTopView = {
let item = EmailCleanTopView()
addSubview(item)
item.callblock = { [weak self] in
guard let self = self else { return }
let vc = EmailFilterController()
UIViewController.topMostViewController()?.navigationController?.pushViewController(vc, animated: true)
}
return item
}()
private lazy var tableView: UITableView = {
let tab = UITableView(frame: CGRectZero, style: .plain)
tab.delegate = self;
tab.dataSource = self
tab.separatorStyle = .none
tab.separatorInset = UIEdgeInsets()
tab.rowHeight = 74 + 12
tab.sectionHeaderHeight = 40 + 12
tab.register(UINib(nibName: EmailContentTabCell.id, bundle: nil), forCellReuseIdentifier: EmailContentTabCell.id)
if #available(iOS 15.0, *) {
tab.sectionHeaderTopPadding = 0
}
addSubview(tab)
return tab
}()
private lazy var botAction: EmailContentBottonAction = {
let bot = EmailContentBottonAction(state: .EmailGroup)
bot.clipsToBounds = false
addSubview(bot)
bot.numberMails = 0
bot.callblock = { [weak self] in
guard let self = self else { return }
let alert = EmailContentDelAlert(state: .group)
alert.callblock = { idx in
}
alert.show()
}
return bot
}()
}
extension EmailContentView :UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: EmailContentTabCell.id, for: indexPath) as! EmailContentTabCell
cell.selectionStyle = .none
cell.selectBtn.isSelected = self.mailset.contains(indexPath.row)
cell.callblock = {[weak self] in
guard let self = self else { return }
if self.mailset.contains(indexPath.row) {
self.mailset.remove(indexPath.row)
}else{
self.mailset.add(indexPath.row)
}
self.botAction.numberMails = self.mailset.count
tableView.reloadData()
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = EmailCleanListController()
parent?.navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView()
header.backgroundColor = .white
let headerT = UILabel()
headerT.text = "Cleans the mails in the categories you choose,according to the filters you applied."
headerT.numberOfLines = 0
headerT.font = UIFont.systemFont(ofSize: 14)
headerT.textColor = UIColor(hex: "#333333")
headerT.numberOfLines = 0
header.addSubview(headerT)
headerT.snp.makeConstraints { make in
make.left.right.top.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15))
}
return header
}
}
//
// EmailEmptyView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import UIKit
class EmailEmptyView: UIView {
var callblock:(()->Void) = {}
@objc private func loginAction() -> Void {
callblock()
}
//FIXME: 差个链接
@objc private func PrivacyPolicy(_ ges:UIGestureRecognizer) -> Void {
let touch = ges.location(in: descpLabel)
let content = CGRectMake((descpLabel.width - 100) / 2.0, descpLabel.height - 25, 100, 25)
if CGRectContainsPoint(content, touch) {
let web = BaseWebViewController()
web.LoadWithUrl(url: "")
UIViewController.topMostViewController()?.navigationController?.pushViewController(web, animated: true)
}
}
private func setup() -> Void {
emptystack.addArrangedSubview(icon)
emptystack.addArrangedSubview(descpLabel)
emptystack.addArrangedSubview(signEmail)
emptystack.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(30)
make.centerY.equalToSuperview().offset(-30.RH())
}
signEmail.snp.makeConstraints { make in
make.height.equalTo(50)
make.width.equalToSuperview()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private lazy var emptystack: UIStackView = {
let stack = UIStackView()
stack.axis = .vertical
stack.spacing = 50
stack.alignment = .center
stack.distribution = .equalSpacing
addSubview(stack)
return stack
}()
private lazy var icon: UIImageView = {
let icon = UIImageView(image: UIImage(named: "img_email"))
icon.contentMode = .scaleAspectFill
return icon
}()
private lazy var descpLabel: UILabel = {
let l = UILabel()
l.textAlignment = .center
l.numberOfLines = 0
l.textColor = UIColor(hex: "#666666")
l.font = UIFont.systemFont(ofSize: 14)
let attrString = NSMutableAttributedString(string: "Cleans the mails in the categories you choose,according to the filters you apply. Your Gmail account and password is not stored in our app and Gmail secures the process.\nPrivacy Policy")
let strSubAttr2: [NSMutableAttributedString.Key: Any] = [.foregroundColor: UIColor(hex: "#0082FF") ?? .clear, .underlineStyle: NSUnderlineStyle.single.rawValue, .underlineColor: UIColor(hex: "#0082FF") ?? .clear]
attrString.addAttributes(strSubAttr2, range: NSRange(location: 170, length: 14))
l.attributedText = attrString
l.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(PrivacyPolicy(_:)))
l.addGestureRecognizer(tap)
return l
}()
private lazy var signEmail: UIButton = {
let emailLogin = UIButton(type: .custom)
emailLogin.setImage(UIImage(named: "emailSmall"), for: .normal)
emailLogin.setTitle("Sign in with Google", for: .normal)
emailLogin.setTitleColor(.white, for: .normal)
emailLogin.titleLabel?.font = UIFont.systemFont(ofSize: 16)
emailLogin.backgroundColor = UIColor(hex: "#0082FF")
emailLogin.layer.cornerRadius = 50/2.0
emailLogin.addTarget(self, action: #selector(loginAction), for: .touchUpInside)
emailLogin.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
return emailLogin
}()
}
//
// PMScaleImageView.swift
// PhoneManager
//
// Created by edy on 2025/5/7.
//
import UIKit
class PMScaleImageView: UIView , UIScrollViewDelegate {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
var icon:UIImage? {
didSet {
showImg.image = icon
DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: {
let size = self.icon?.size ?? CGSize()
// self.showImg.snp.remakeConstraints({ make in
// make.size.equalTo(size)
// })
// self.layoutIfNeeded()
// self.showImg.center = CGPoint(x: self.scroll.width/2.0, y: self.scroll.height/2.0)
})
}
}
private func setup() -> Void {
scroll.snp.makeConstraints { make in
make.left.right.bottom.top.equalToSuperview()
}
showImg.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.width.height.equalToSuperview()
}
}
private lazy var showImg: UIImageView = {
let iv = UIImageView()
iv.contentMode = .center
scroll.addSubview(iv)
return iv
}()
private lazy var scroll: UIScrollView = {
let scroll = UIScrollView()
scroll.delegate = self
scroll.showsVerticalScrollIndicator = false
scroll.showsHorizontalScrollIndicator = false
scroll.minimumZoomScale = 1.0
scroll.maximumZoomScale = 3.0
addSubview(scroll)
return scroll
}()
func scrollViewDidZoom(_ scrollView: UIScrollView) {
Print(scrollView.zoomScale)
if scrollView.zoomScale > 1.5 {
self.Radius = 16
}else{
self.Radius = 0
}
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return showImg
}
}
...@@ -30,7 +30,6 @@ extension UIView { ...@@ -30,7 +30,6 @@ extension UIView {
} }
func cornerCut(radius:CGFloat,corner:UIRectCorner){ func cornerCut(radius:CGFloat,corner:UIRectCorner){
let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize.init(width: radius, height: radius)) let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize.init(width: radius, height: radius))
let maskLayer = CAShapeLayer() let maskLayer = CAShapeLayer()
maskLayer.frame = bounds maskLayer.frame = bounds
......
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSContactsUsageDescription</key> <key>GADApplicationIdentifier</key>
<string>Phone Manager needs access to your contacts to find and merge duplicate contacts</string> <string>ca-app-pub-3940256099942544~1458002511</string>
<key>NSUserTrackingUsageDescription</key>
<string>We need your permission to track your usage habits in order to provide a more personalized advertising experience</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
...@@ -18,15 +16,10 @@ ...@@ -18,15 +16,10 @@
<string>ChargeShowIntent</string> <string>ChargeShowIntent</string>
<string>LaunchAppIntent</string> <string>LaunchAppIntent</string>
</array> </array>
<key>NSWidgetUsageDescription</key>
<string>Need to access device data to provide real-time information</string>
<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key> <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/> <true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key> <key>SKAdNetworkItems</key>
<array> <array>
<dict> <dict>
...@@ -226,6 +219,11 @@ ...@@ -226,6 +219,11 @@
<string>3qcr597p9d.skadnetwork</string> <string>3qcr597p9d.skadnetwork</string>
</dict> </dict>
</array> </array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>processing</string> <string>processing</string>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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