Commit cd9820bc authored by yqz's avatar yqz

邮箱界面

parent 4b92a5f0
......@@ -77,6 +77,13 @@
/* End PBXFileReference 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 */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
......@@ -104,6 +111,7 @@
0496DEF52D9E3F58005B2834 /* widget */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
041E22DC2DCCD63B0028E917 /* Exceptions for "widget" folder in "PhoneManager" target */,
0496DF032D9E3F59005B2834 /* Exceptions for "widget" folder in "widgetExtension" target */,
);
path = widget;
......@@ -580,10 +588,12 @@
GENERATE_INFOPLIST_FILE = YES;
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_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_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_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_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
......@@ -626,10 +636,12 @@
GENERATE_INFOPLIST_FILE = YES;
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_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_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_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_UILaunchStoryboardName = LaunchScreen;
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
}
}
//
// 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
}()
}
......@@ -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)
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
guard let self else {return}
......@@ -275,6 +288,16 @@ class HomeInfoViewController:BaseViewController {
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 titleText : String?
......@@ -373,6 +396,10 @@ class HomeInfoViewController:BaseViewController {
titleView.addSubview(seletedAllBtn)
titleLabel.x = titleView.backBtn.width + titleView.backBtn.x + 10
titleLabel.centerY = navCenterY
titleView.addSubview(titleLabel)
view.addSubview(tablewView)
view.addSubview(self.defaultImageView)
self.defaultImageView.snp.makeConstraints { make in
......
......@@ -62,7 +62,14 @@ class HomeViewController:BaseViewController {
case 3 :
DispatchQueue.main.async {[weak self] in
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
case 4 :
......@@ -142,9 +149,9 @@ class HomeViewController:BaseViewController {
let homeSimilarImageResourceUpdate = Notification.Name("HomeSimilarImageResourceUpdate")
NotificationCenter.default.addObserver(self, selector: #selector(handleHomeSimilarImageResourceUpdate(_:)), name: homeSimilarImageResourceUpdate, object: nil)
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
guard let self else {return}
......
......@@ -32,25 +32,25 @@ class HomeCollectionViewHeader : UICollectionReusableView {
return view
}()
private lazy var tipLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0 // 支持多行
return label
}()
// private lazy var tipLabel:UILabel = {
// let label = UILabel()
// label.numberOfLines = 0 // 支持多行
// return label
// }()
private func setupUI() {
// 文本
self.addSubview(self.tipLabel)
self.tipLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8)
make.top.equalToSuperview().offset(4)
make.height.equalTo(17)
}
// self.addSubview(self.tipLabel)
// self.tipLabel.snp.makeConstraints { make in
// make.left.equalToSuperview().offset(8)
// make.top.equalToSuperview().offset(44)
// make.height.equalTo(17)
// }
self.addSubview(self.progressBar)
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.height.equalTo(31)
make.left.equalToSuperview().offset(8)
......@@ -90,7 +90,7 @@ extension HomeCollectionViewHeader{
/// - Parameters:
/// - count: 文件数量
/// - fileSize: 文件总大小
func setFileAndCount(count:Int,fileSize:Double) {
func setFileAndCount(count:Int,fileSize:Double) -> NSMutableAttributedString {
let countString = "\(count)"
let fileSizeString = formatFileSize(fileSize)
......@@ -122,9 +122,9 @@ extension HomeCollectionViewHeader{
.foregroundColor: UIColor.colorWithHex(hexStr: black6Color)
], range: nsRange2)
}
return attributedText
// 将 attributedText 赋值给 UILabel
self.tipLabel.attributedText = attributedText
// self.tipLabel.attributedText = attributedText
}
}
......
......@@ -7,7 +7,7 @@
import UIKit
class HomeInfoView :UIView{
class HomeInfoView :UIView {
var ids:[[AssetModel]]?
......@@ -20,10 +20,11 @@ class HomeInfoView :UIView{
var callBack:callBack<Any> = {text in}
var deleteCallBack:callBack<[AssetModel]> = {array in }
var titleShowHideCallBack:callBack<Bool> = {isShow in}
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.separatorStyle = .none
sview.showsVerticalScrollIndicator = false
......@@ -35,16 +36,13 @@ class HomeInfoView :UIView{
sview.sectionHeaderTopPadding = 0
}
return sview
}()
lazy var headerView:HomeInfoTitleView = {
let sview:HomeInfoTitleView = HomeInfoTitleView(frame: CGRect(x: 0, y: 0, width: width, height: 84))
sview.titleLabel.text = self.titleText
tableView.addSubview(sview)
return sview
}()
......@@ -164,6 +162,7 @@ class HomeInfoView :UIView{
for section in 0..<self.tableView.numberOfSections {
for item in 0..<self.tableView.numberOfRows(inSection: section) {
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: {
cell.collectionView?.reloadData()
}, completion: nil)
......@@ -182,7 +181,6 @@ class HomeInfoView :UIView{
}
}
}
return selectedArray
}
......@@ -255,6 +253,20 @@ class HomeInfoView :UIView{
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 {
return ids?.count ?? 0
......@@ -284,13 +296,11 @@ extension HomeInfoView:UITableViewDataSource,UITableViewDelegate {
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerView.height
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerView
return UIView()
}
}
......
......@@ -9,7 +9,7 @@ import UIKit
class HomeNavView:UIView {
private var settingBtn:UIButton!
// private var settingBtn:UIButton!
private var proBtn:UIButton!
private lazy var homeTitle : UILabel = {
let label = UILabel()
......@@ -38,24 +38,22 @@ class HomeNavView:UIView {
self.addSubview(self.homeTitle)
self.homeTitle.snp.makeConstraints { make in
make.left.equalTo(15 + 8)
make.top.equalTo(8 + statusBarHeight)
make.top.equalTo(8)
make.height.equalTo(28)
make.width.equalTo(149)
}
// 设置按钮
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.homeTitle.snp.centerY)
make.right.equalTo(-marginLR)
make.width.height.equalTo(iconWH)
}
// 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.homeTitle.snp.centerY)
// make.right.equalTo(-marginLR)
// make.width.height.equalTo(iconWH)
//
// }
// 会员按钮
self.proBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: iconWH))
self.proBtn.setBackgroundImage(UIImage(named: "ic_pro_home"), for: .normal)
......@@ -63,7 +61,7 @@ class HomeNavView:UIView {
self.addSubview(proBtn)
self.proBtn.snp.makeConstraints { make in
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.height.equalTo(iconWH)
}
......@@ -73,11 +71,12 @@ class HomeNavView:UIView {
extension HomeNavView {
@objc private func settingBtnClick() {
let homeNavViewModel = HomeNavViewModel()
let settingViewController = SettingViewController()
homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
}
// @objc private func settingBtnClick() {
// let homeNavViewModel = HomeNavViewModel()
// let settingViewController = SettingViewController()
// homeNavViewModel.pushToDetailController(currentView: self, destnationController: settingViewController)
// }
@objc private func proBtnClick() {
if IAPManager.share.isSubscribed == false {
HomePayViewController.show {}
......
......@@ -11,6 +11,7 @@ import SnapKit
class HomeView:UIView {
private var homeTabbarView:HomeTabbarView?
private var settingBtn:UIButton!
private var homeNavView:HomeNavView?
......@@ -30,6 +31,17 @@ class HomeView:UIView {
var model:PhotosManagerModel?
var isScroll = false {
didSet {
if isScroll {
DispatchQueue.main.async {
self.tipLabel.attributedText = self.attribet
}
}
}
}
var attribet:NSAttributedString?
lazy var collectionView:UICollectionView = {
let cY:CGFloat = 16.RW()
......@@ -51,11 +63,19 @@ class HomeView:UIView {
if #available(iOS 11.0, *) {
sview.contentInsetAdjustmentBehavior = .never
}
sview.clipsToBounds = true
sview.backgroundColor = .clear
return sview
}()
private lazy var topNaviView: UIView = {
let backView = UIView()
backView.backgroundColor = UIColor(hex: "#DAEAFF")
addSubview(backView)
return backView
}()
override init(frame: CGRect) {
super.init(frame: frame)
......@@ -68,20 +88,21 @@ class HomeView:UIView {
}
func setTitle() {
self.attribet = self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0)
DispatchQueue.main.async {[weak self] in
guard let self else {return}
self.homeHeader?.setFileAndCount(count: model?.allFileNumber ?? 0, fileSize: model?.allFileSize ?? 0)
self.homeHeader?.setNeedsLayout()
self.homeHeader?.layoutIfNeeded()
if isScroll == false {
self.tipLabel.attributedText = self.attribet
self.homeHeader?.setNeedsLayout()
self.homeHeader?.layoutIfNeeded()
}
}
}
private func setupUI() {
backgroundColor = .clear
clipsToBounds = true
homeTabbarView = HomeTabbarView(frame: CGRect(x: 0, y: 0, width: self.width, height: safeHeight + 66))
......@@ -102,14 +123,29 @@ class HomeView:UIView {
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!)
homeNavView?.snp.makeConstraints({ make in
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?.backgroundColor = .white
self.addSubview(bottomView!)
......@@ -118,15 +154,19 @@ class HomeView:UIView {
make.bottom.equalToSuperview().offset(10)
make.height.equalTo(safeHeight + 10)
})
self.insertSubview(collectionView, at: 0)
collectionView.snp.makeConstraints { make in
make.top.equalTo(self.homeNavView!.snp.bottom).offset(0)
make.centerX.equalToSuperview()
make.top.centerX.equalToSuperview()
make.width.equalToSuperview().offset(-2 * marginLR)
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 {
......@@ -134,10 +174,53 @@ class HomeView:UIView {
return UICollectionViewCell()
}
private lazy var tipLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0 // 支持多行
return label
}()
}
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 {
return 2
......@@ -322,7 +405,7 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
if section == 0 {
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{
return CGSize(width: self.collectionView.width, height: 404)
}
......@@ -334,4 +417,12 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
let indexPath = IndexPath(item: 0, section: 0)
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 {
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
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: Notification.Name("applicationDidBecomeActive"), object: nil)
}
required init?(coder: NSCoder) {
......@@ -87,16 +98,20 @@ class HomeOtherCollectionCell: UICollectionViewCell {
backgroundColor = .white
self.contentView.addSubview(self.titleLabel)
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.sizeLabel)
self.infoBackView.addSubview(self.moreImageView)
}
@objc private func didBecomeActive() -> Void {
self.playerView.resume()
}
var model:HomePhotosModel? {
didSet {
......@@ -161,19 +176,35 @@ class HomeOtherCollectionCell: UICollectionViewCell {
// 从 PHAsset 获取 AVAsset
if let videoAsset = PhotoAndVideoMananger.mananger.getPHAsssetwithID(ids: [asset.localIdentifier]){
// 使用requestImageForAsset方法请求视频的第一帧图片
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("无法获取图片")
}
}
let options = PHVideoRequestOptions()
options.version = .current
options.deliveryMode = .automatic // 根据需求调整视频质量:ml-citation{ref="2,7" data="citationList"}
PHImageManager.default().requestAVAsset(
forVideo: videoAsset,
options: options
) { (avAsset, audioMix, info) in
guard let avAsset = avAsset as? AVURLAsset else { return }
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 {
make.height.equalTo(self.width - 32)
}
self.infoBackView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(40)
}
self.playImageView.snp.makeConstraints { make in
make.width.height.equalTo(43)
make.center.equalTo(self.imageView.snp.center)
// self.playImageView.snp.makeConstraints { make in
// make.width.height.equalTo(43)
// 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
......@@ -237,7 +270,10 @@ class HomeOtherCollectionCell: UICollectionViewCell {
make.right.equalToSuperview().offset(-12)
make.centerY.equalToSuperview()
}
// titleLabel.sizeToFit()
}
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name("applicationDidBecomeActive"), object: nil)
}
}
......@@ -54,7 +54,7 @@ class ImageCollectionCell:UICollectionViewCell {
backImageView = UIImageView()
backImageView?.isUserInteractionEnabled = true
backImageView?.contentMode = .scaleAspectFit
backImageView?.contentMode = .scaleAspectFill
backImageView?.clipsToBounds = true
backImageView?.layer.masksToBounds = true
backImageView?.isUserInteractionEnabled = true
......
......@@ -26,7 +26,6 @@ class HomePayModel: NSObject ,SKProductsRequestDelegate ,SKPaymentTransactionObs
private let productIdentifiers:[String] = ["com.app.phonemanager.week.member" , "com.app.phonemanager.lifetime.member"]
var isSubscribed:Bool = false
var isNoAd:Bool {
get {
......
......@@ -11,40 +11,62 @@ let PMShowImgCellID = "PMShowImgCell"
class PMShowImgCell: UICollectionViewCell {
var callblock:(()->Void) = {}
@objc private func selectTap() -> Void {
callblock()
}
var icon:UIImage = UIImage() {
didSet {
iconView.image = icon
var size = icon.size
if size.width != 0 && size.height != 0 {
if size.height < size.width {
let width = self.width
size = CGSize(width: width, height: size.height * (width/size.width) )
}else{
let width = self.width
let height = size.height * (width/size.width)
if height > self.height {
size = CGSize(width: width * (self.height/height), height: height )
}else {
size = CGSize(width: width, height: height )
}
}
}
iconView.snp.remakeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.size.equalTo(size)
}
scaleImg.icon = icon
// iconView.image = icon
// var size = icon.size
// if size.width != 0 && size.height != 0 {
// if size.height < size.width {
// let width = self.width
// size = CGSize(width: width, height: size.height * (width/size.width) )
// }else{
// let width = self.width
// let height = size.height * (width/size.width)
// if height > self.height {
// size = CGSize(width: width * (self.height/height), height: height )
// }else {
// size = CGSize(width: width, height: height )
// }
// }
// }
//
// iconView.snp.remakeConstraints { make in
// make.centerX.centerY.equalToSuperview()
// make.size.equalTo(size)
// }
}
}
private lazy var iconView: UIImageView = {
let info = UIImageView()
info.contentMode = .scaleToFill
info.contentMode = .scaleAspectFill
contentView.addSubview(info)
info.clipsToBounds = true
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) {
super.init(frame: frame)
setup()
......@@ -59,5 +81,13 @@ class PMShowImgCell: UICollectionViewCell {
iconView.snp.makeConstraints { make in
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
let PMShowItemCellID = "PMShowItemCell"
class PMShowItemCell: UICollectionViewCell {
var isCurrent:Bool = false {
didSet {
if isCurrent {
......@@ -37,6 +37,15 @@ class PMShowItemCell: UICollectionViewCell {
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) {
super.init(frame: frame)
clipsToBounds = true
......@@ -52,6 +61,11 @@ class PMShowItemCell: UICollectionViewCell {
iconV.snp.makeConstraints { make in
make.left.right.top.bottom.equalToSuperview()
}
selectBtn.snp.makeConstraints { make in
make.right.equalToSuperview()
make.width.height.equalTo(iconWH)
make.bottom.equalToSuperview()
}
}
}
......@@ -29,6 +29,7 @@ class PMShowImgVideoController: BaseViewController {
var homeDataSource : [ImageSeletedCollectionItem]?
var currentIdx = 0
var selectSet = NSMutableSet()
var url : URL?
......@@ -40,13 +41,13 @@ class PMShowImgVideoController: BaseViewController {
super.viewWillAppear(animated)
self.MaxCollection.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(20)
make.top.top.equalTo(titleView.snp.bottom).offset(20)
make.bottom.equalToSuperview().inset(100)
make.top.equalTo(titleView.snp.bottom).offset(20)
make.bottom.equalToSuperview().inset(100 + (cWindow?.safeAreaInsets.bottom ?? 0))
}
self.bottItems.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.left.right.equalTo(MaxCollection)
make.top.equalTo(MaxCollection.snp.bottom)
make.bottom.equalToSuperview()
make.bottom.equalToSuperview().offset(-(cWindow?.safeAreaInsets.bottom ?? 0))
}
self.view.layoutIfNeeded()
self.MaxCollection.scrollToItem(at: IndexPath(row: currentIdx, section: 0), at: .centeredHorizontally, animated: false)
......@@ -71,19 +72,20 @@ class PMShowImgVideoController: BaseViewController {
private lazy var bottItems: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout()
flowlayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
flowlayout.minimumInteritemSpacing = 0
flowlayout.sectionInset = UIEdgeInsets()
flowlayout.minimumInteritemSpacing = 10
flowlayout.minimumLineSpacing = 10
flowlayout.scrollDirection = .horizontal
let col = UICollectionView(frame: CGRect(), collectionViewLayout: flowlayout)
col.delegate = self;
col.dataSource = self;
col.register(PMShowItemCell.self, forCellWithReuseIdentifier: PMShowItemCellID)
col.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
col.showsHorizontalScrollIndicator = false
col.isPagingEnabled = true
view.addSubview(col)
return col
}()
}
extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
......@@ -94,29 +96,52 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let offsetx = MaxCollection.contentOffset.x
let width = collectView.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) {
Print("1")
guard let collectView = scrollView as? UICollectionView else { return }
if collectView == MaxCollection {
bottItems.reloadData()
}
// if collectView == MaxCollection {
// bottItems.reloadData()
// }
self.setMaxCollection(collectionView: collectView)
}
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) {
if collectionView == bottItems {
if currentIdx != indexPath.row {
currentIdx = indexPath.row
MaxCollection.scrollToItem(at: indexPath, at: .left, animated: false)
collectionView.reloadData()
if selectSet.contains(indexPath.row) {
selectSet.remove(indexPath.row)
}else{
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()
// }
}
}
......@@ -124,7 +149,11 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if self.state == .secret {
return imageVideoPath.count
}else {
return self.homeDataSource?.count ?? 0
if collectionView == MaxCollection{
return self.homeDataSource?.count ?? 0
}else{
return (self.homeDataSource?.count ?? 0) + 1
}
}
}
......@@ -172,12 +201,25 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowImgCellID, for: indexPath) as! PMShowImgCell
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
}else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isCurrent = (self.currentIdx == indexPath.row)
return cell
if indexPath.row < self.homeDataSource?.count ?? 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isCurrent = selectSet.contains(indexPath.row) //(self.currentIdx == indexPath.row)
return cell
}
}
}
......@@ -201,13 +243,15 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
cell.type = 1
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
cell.isCurrent = (self.currentIdx == indexPath.row)
return cell
if indexPath.row < self.homeDataSource?.count ?? 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PMShowItemCellID, for: indexPath) as! PMShowItemCell
cell.icon = self.homeDataSource![indexPath.row].image ?? UIImage()
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
}
......@@ -215,11 +259,13 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
if collectionView == MaxCollection {
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
/// - Parameters:
/// - localIdentifier: 资源标识
......
......@@ -14,6 +14,11 @@ class SecretVideoPlayer: UIView {
private var player: AVPlayer?
var isLooping = false
enum PlayerFrom {
case home
case other
}
enum playState {
case start
case playing
......@@ -21,6 +26,8 @@ class SecretVideoPlayer: UIView {
case end
}
var fromState:PlayerFrom = .other
var state:playState = .start
override init(frame: CGRect) {
......@@ -49,8 +56,11 @@ class SecretVideoPlayer: UIView {
}
private func setupPlayerLayer() {
backgroundColor = .clear
let playerLayer = AVPlayerLayer()
playerLayer.videoGravity = .resizeAspect
playerLayer.backgroundColor = UIColor.clear.cgColor
playerLayer.shouldRasterize = true
playerLayer.rasterizationScale = UIScreen.main.scale
layer.addSublayer(playerLayer)
let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick))
self.addGestureRecognizer(tap)
......@@ -60,6 +70,7 @@ class SecretVideoPlayer: UIView {
super.layoutSubviews()
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.frame = bounds
}
}
......@@ -71,6 +82,12 @@ class SecretVideoPlayer: UIView {
player = AVPlayer(url: url!)
if let playerLayer = layer.sublayers?.first as? AVPlayerLayer {
playerLayer.player = player
if fromState == .home {
playerLayer.videoGravity = .resizeAspectFill
player?.isMuted = true
}else{
playerLayer.videoGravity = .resizeAspect
}
}
NotificationCenter.default.addObserver(
self,
......@@ -79,6 +96,7 @@ class SecretVideoPlayer: UIView {
object: player?.currentItem
)
state = .playing
player?.play()
}
......
......@@ -20,6 +20,18 @@ class WidgetPublicModel: NSObject {
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: 已使用空间
......@@ -68,6 +80,10 @@ class WidgetPublicModel: NSObject {
return val
}
class func isLowPowerModeEnabled() -> Bool {
return ProcessInfo.processInfo.isLowPowerModeEnabled
}
}
class widgetAppgourp: NSObject {
......@@ -75,7 +91,12 @@ class widgetAppgourp: NSObject {
static let share = widgetAppgourp()
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") {
let encodedData = try? JSONEncoder().encode(data)
sharedDefaults.set(encodedData, forKey: "widgetSharedData")
......@@ -91,4 +112,8 @@ struct WidgetData: Codable {
var widget: Int
var battery: Int
var widgetStorage :Int
var AllSpace: Int
var UseSpace: Int
let batteryState: String
let isCharging: Bool
}
......@@ -24,13 +24,27 @@ class WidgetTopStackView: UIView {
if type == 0 {
battryBtn.isSelected = true
storageBtn.isSelected = false
battryBtn.backgroundColor = .white
storageBtn.backgroundColor = .clear
}else{
bronThem.isSelected = false
bronThem.backgroundColor = .clear
}else if type == 1{
battryBtn.isSelected = false
storageBtn.isSelected = true
battryBtn.backgroundColor = .clear
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 {
}
private func setUI() -> Void {
battryBtn.snp.makeConstraints { make in
make.left.top.bottom.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.snp.makeConstraints { make in
make.left.top.bottom.right.equalToSuperview().inset(4)
}
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 = {
let b = UIButton(type: .custom)
b.tag = 0
......@@ -61,7 +96,6 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
b.layer.cornerRadius = 4
addSubview(b)
return b
}()
......@@ -73,7 +107,17 @@ class WidgetTopStackView: UIView {
b.setTitleColor(.colorWithHex(hexStr: "#0082FF"), for: .selected)
b.addTarget(self, action: #selector(widgetTouchs(_:)), for: .touchUpInside)
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
}()
......
......@@ -9,21 +9,23 @@ import UIKit
class WidgetViewController: BaseViewController {
enum widgetType {
case battery
case storage
enum widgetType:Int {
case battery = 0
case storage = 1
case bothThem = 2
}
var widgets:widgetType = .battery {
didSet {
topButs.type = (self.widgets == .battery ? 0 : 1)
batterySta.widgetType = (self.widgets == .battery ? 0 : 1)
topButs.type = self.widgets.rawValue
batterySta.widgetType = self.widgets.rawValue
}
}
var widgetMode = 0 {// 0 1 2
didSet{
batterySta.widgetMode = widgetMode
born.widgetMode = widgetMode
}
}
......@@ -33,11 +35,16 @@ class WidgetViewController: BaseViewController {
setUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
widgetMode = 0
}
@objc func setWidgetTouch() -> Void {
let battery = WidgetPublicModel.battery()
let storage = WidgetPublicModel.UseDiskSpace() * 100
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))
PMAlert("Set Widget Successfully")
}
......@@ -61,14 +68,19 @@ class WidgetViewController: BaseViewController {
make.centerX.equalToSuperview()
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
make.centerX.equalToSuperview()
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
make.left.right.equalToSuperview().inset(15)
make.bottom.equalToSuperview().offset(-50)
make.bottom.equalToSuperview().offset(-30)
make.height.equalTo(46)
}
}
......@@ -84,24 +96,37 @@ class WidgetViewController: BaseViewController {
private lazy var topButs: WidgetTopStackView = {
let topbuts = WidgetTopStackView()
topbuts.type = (self.widgets == .battery ? 0 : 1)
topbuts.type = self.widgets.rawValue
topbuts.callback = { [weak self] idx in
self?.born.isHidden = true
if idx == 0 {
self?.widgets = .battery
self?.widgetPageCtrol.currentPage = 0
}else{
}else if idx == 1{
self?.widgets = .storage
self?.widgetPageCtrol.currentPage = 1
}else{
self?.born.isHidden = false
self?.widgets = .bothThem
self?.widgetPageCtrol.currentPage = 2
}
}
view.addSubview(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 = {
let stav = WidgetBatteryStView()
stav.layer.cornerRadius = 20
stav.widgetType = (self.widgets == .battery ? 0 : 1)
stav.widgetType = self.widgets.rawValue
stav.widgetMode = widgetMode
view.addSubview(stav)
return stav
......@@ -110,7 +135,7 @@ class WidgetViewController: BaseViewController {
private lazy var widgetPageCtrol: UIPageControl = {
let page = UIPageControl()
page.currentPage = 0
page.numberOfPages = 2
page.numberOfPages = 3
page.currentPageIndicatorTintColor = .colorWithHex(hexStr: "#0082FF")
page.pageIndicatorTintColor = .colorWithHex(hexStr: "#C6CEE0")
view.addSubview(page)
......
//
// 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 {
}
func cornerCut(radius:CGFloat,corner:UIRectCorner){
let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: corner, cornerRadii: CGSize.init(width: radius, height: radius))
let maskLayer = CAShapeLayer()
maskLayer.frame = bounds
......
......@@ -2,10 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSContactsUsageDescription</key>
<string>Phone Manager needs access to your contacts to find and merge duplicate contacts</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>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
......@@ -18,15 +16,10 @@
<string>ChargeShowIntent</string>
<string>LaunchAppIntent</string>
</array>
<key>NSWidgetUsageDescription</key>
<string>Need to access device data to provide real-time information</string>
<key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
......@@ -226,6 +219,11 @@
<string>3qcr597p9d.skadnetwork</string>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>processing</string>
......
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
platform :ios, '14.0'
source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
target 'PhoneManager' do
# Comment the next line if you don't want to use dynamic frameworks
......
This diff is collapsed.
......@@ -11,12 +11,14 @@ import SwiftUI
@main
struct widgetBundle: WidgetBundle {
var body: some Widget {
BatteryWidget()
widgetLockSreenView()
// BatteryWidget()
// BatteryWidget1()
// BatteryWidget2()
}
}
extension Color {
init(_ hex:String = "FFFFFF") {
let scanner = Scanner(string: hex)
scanner.currentIndex = hex.startIndex
......
//
// widgetLockSreenView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import SwiftUI
import WidgetKit
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